Reputation: 55720
I'm trying to get up to speed on how to get some code that uses OpenSSL for cryptography, to play nice with another program that I'm writing in C#, using the Microsoft cryptography providers available in .NET.
More to the point, I'm trying to have the C# program verify an RSA message signature generated by the OpenSSL code. The code that generates the signature looks something like this:
// Code in C, using the OpenSSL RSA implementation
char msgToSign[] = "Hello World"; // the message to be signed
char signature[RSA_size(rsa)]; // buffer that will hold signature
int slen = 0; // will contain signature size
// rsa is an OpenSSL RSA context, that's loaded with the public/private key pair
memset(signature, 0, sizeof(signature));
RSA_sign(NID_sha1
, (unsigned char*)msgToSign
, strlen(msgToSign)
, signature
, &slen
, rsa);
// now signature contains the message signature
// and can be verified using the RSA_verify counterpart
// .. I would like to verify the signature in C#
In C#, I would do the following:
RSACryptoServiceProvider
objectI've got the first two parts working (I've verified that the public key is loading properly because I managed to send an RSA encrypted text from the C# code to the OpenSSL code in C and successfully have it decrypted)
In order to verify the signature in C#, I've tried using the: VerifySignature method of the RSACryptoServiceProvider but that didn't work. And digging around the internet I was only able to find some vague information pointing out that .NET uses a different method for generating the signature than OpenSSL does. So, does anybody know how to accomplish this?
EDIT
Since there was a request, here's the C# side of things..
byte[] receivedSignature;
// ....
// receivedSignature is set to the byte array generated by the OpenSSL side
// I've verified this much is working correctly
// I use my utility to parse a PEM file and extract the other side's public key
// also, verified to be working correctly - the public key is good.
RSACryptoServiceProvider rsa = MyPEMLoader.LoadFromFile("publicKey.pem");
string msgToVerify = "Hello World";
byte[] msgBytes = Encoding.ASCII.GetBytes(msg); // other side uses ASCII, so do the same
bool verified = rsa.VerifyHash(msgBytes, "SHA1", receivedSignature);
// verfied is false.. verfification failed!
Upvotes: 2
Views: 5059
Reputation: 27931
You should remove your pem utility, this is not required and use
var cert = new X509Certificate2(HttpContext.Current.Request.MapPath("~/App_Data/PublicKey.pem"), "");
var rsaCryptoIPT = (RSACryptoServiceProvider)cert.PublicKey.Key;
var sha1 = new SHA1CryptoServiceProvider();
if (!rsaCryptoIPT.VerifyData(data, sha1, signature))
throw new InvalidOperationException("Invalid signature from bank ");
If this does not help can you post pem file reader code.
Upvotes: 0
Reputation: 273244
It might help if you showed your C# code. I think it should be something like:
string msg = ...;
byte[] localData = Encoding.UTF8.GetBytes(msg);
bool ok = rsa.VerifyHash(localData, "SHA1", receivedhash);
And of course I'm just guessing the UTF-8 part. Might be ASCII as well.
Edit: Here is the MSDN page. The example seems to do it different, localData is hashed first.
hashedData = hash.ComputeHash(signedData);
return rsaCSP.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signature);
Upvotes: 1