RSA_sign and RSACryptoProvider.VerifySignature

I am trying to speed up the process of getting code that uses OpenSSL for crypto to play well with another program I am writing in C # using Microsoft crypto providers available in .NET.

In general, I am trying to verify that a C # program validates the RSA 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 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:

  • import the other party's public key into an object RSACryptoServiceProvider

  • get message and signature
  • try to verify the signature

The first two parts work for me (I verified that the public key is loaded as expected because I was able to send the RSA ciphertext from C # code to OpenSSL C code and decrypt it successfully)

To verify the signature in C #, I tried to use the VerifySignature method for RSACryptoServiceProvider, but it didn't work. And while digging around on the internet, I could find some vague information indicating that .NET uses a different method to generate the signature than OpenSSL. So, does anyone know how to do 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 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!

      

+2


a source to share


2 answers


It might help if you put your code in C #. 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. ASCII is also possible.



Strike>

Edit: here is the MSDN page . The example seems to be different from this, localData is hashed first.

hashedData = hash.ComputeHash(signedData);
return rsaCSP.VerifyHash(hashedData, CryptoConfig.MapNameToOID("SHA1"), signature);

      

+1


a source


You have to uninstall your pem utility, it 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 that doesn't help, you can post the pem reader code.

0


a source







All Articles