c# How to Verify Signature, Loading PUBLIC KEY From PEM file?
- by bbirtle
I'm posting this in the hope it saves somebody else the hours I lost on this really stupid problem involving converting formats of public keys. If anybody sees a simpler solution or a problem, please let me know!
The eCommerce system I'm using sends me some data along with a signature. They also give me their public key in .pem format. The .pem file looks like this:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew
HFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc
VrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC
Ka1g88CjFwRw/PB9kwIDAQAB
-----END PUBLIC KEY-----
Here's the magic code to turn the above into an "RSACryptoServiceProvider" which is capable of verifying the signature. Uses the BouncyCastle library, since .NET apparently (and appallingly cannot do it without some major headaches involving certificate files):
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);
}
And then the code to actually verify the signature:
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);