Я публикую это в надежде, что это сэкономит кому-то еще часы, которые я потратил на эту действительно глупую проблему, связанную с преобразованием форматов открытых ключей. Если кто-нибудь видит более простое решение или проблему, пожалуйста, дайте мне знать!
Используемая мной система электронной коммерции отправляет мне некоторые данные вместе с подписью. Они также дают мне свой открытый ключ в формате .pem. Файл .pem выглядит так:
----- НАЧАТЬ ПУБЛИЧНЫЙ КЛЮЧ -----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe + hkicNP7ROHUssGNtHwiT2Ew
HFrSk / qwrcq8v5metRtTTFPE / nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc
VrOSClpD5Ri2hER / GcNrxVRP7RlWOqB1C03q4QYmwjHZ + zlM4OUhCCAtSWflB4wC
Ka1g88CjFwRw / PB9kwIDAQAB
----- КОНЕЦ ОБЩЕСТВЕННОГО КЛЮЧА -----
Вот магический код, позволяющий превратить вышеперечисленное в «RSACryptoServiceProvider», который способен проверять подпись. Использует библиотеку BouncyCastle, поскольку .NET, по-видимому (и, к сожалению, не может сделать это без каких-либо серьезных проблем с файлами сертификатов):
RSACryptoServiceProvider thingee;
using (var reader = File.OpenText(@"c:\pemfile.pem"))
{
var x = new PemReader(reader);
var y = (RsaKeyParameters)x.ReadObject();
thingee = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
var pa = new RSAParameters();
pa.Modulus = y.Modulus.ToByteArray();
pa.Exponent = y.Exponent.ToByteArray();
thingee.ImportParameters(pa);
}
А потом код для проверки подлинности подписи:
var signature = ... //reads from the packet sent by the eCommerce system
var data = ... //reads from the packet sent by the eCommerce system
var sha = new SHA1CryptoServiceProvider();
byte[] hash = sha.ComputeHash(Encoding.ASCII.GetBytes(data));
byte[] bSignature = Convert.FromBase64String(signature);
///Verify signature, FINALLY:
var hasValidSig = thingee.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), bSignature);