Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signing and verifying signatures with RSA C#

I recently posted about issues with encrypting large data with RSA, I am finally done with that and now I am moving on to implementing signing with a user's private key and verifying with the corresponding public key. However, whenever I compare the signed data and the original message I basically just get false returned. I am hoping some of your could see what I am doing wrong.

Here is the code:

public static string SignData(string message, RSAParameters privateKey)     {         //// The array to store the signed message in bytes         byte[] signedBytes;         using (var rsa = new RSACryptoServiceProvider())         {             //// Write the message to a byte array using UTF8 as the encoding.             var encoder = new UTF8Encoding();             byte[] originalData = encoder.GetBytes(message);              try             {                 //// Import the private key used for signing the message                 rsa.ImportParameters(privateKey);                  //// Sign the data, using SHA512 as the hashing algorithm                  signedBytes = rsa.SignData(originalData, CryptoConfig.MapNameToOID("SHA512"));             }             catch (CryptographicException e)             {                 Console.WriteLine(e.Message);                 return null;             }             finally             {                 //// Set the keycontainer to be cleared when rsa is garbage collected.                 rsa.PersistKeyInCsp = false;             }         }         //// Convert the a base64 string before returning         return Convert.ToBase64String(signedBytes);     } 

So that is the first step, to sign the data, next I move on to verifying the data:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey)     {         bool success = false;         using (var rsa = new RSACryptoServiceProvider())         {             byte[] bytesToVerify = Convert.FromBase64String(originalMessage);             byte[] signedBytes = Convert.FromBase64String(signedMessage);             try             {                 rsa.ImportParameters(publicKey);                  SHA512Managed Hash = new SHA512Managed();                  byte[] hashedData = Hash.ComputeHash(signedBytes);                  success = rsa.VerifyData(bytesToVerify, CryptoConfig.MapNameToOID("SHA512"), signedBytes);             }             catch (CryptographicException e)             {                 Console.WriteLine(e.Message);             }             finally             {                 rsa.PersistKeyInCsp = false;             }         }         return success;     } 

And here is the test client:

public static void Main(string[] args)     {         PublicKeyInfrastructure pki = new PublicKeyInfrastructure();         Cryptograph crypto = new Cryptograph();         RSAParameters privateKey = crypto.GenerateKeys("[email protected]");          const string PlainText = "This is really sent by me, really!";          RSAParameters publicKey = crypto.GetPublicKey("[email protected]");          string encryptedText = Cryptograph.Encrypt(PlainText, publicKey);          Console.WriteLine("This is the encrypted Text:" + "\n " + encryptedText);          string decryptedText = Cryptograph.Decrypt(encryptedText, privateKey);          Console.WriteLine("This is the decrypted text: " + decryptedText);          string messageToSign = encryptedText;          string signedMessage = Cryptograph.SignData(messageToSign, privateKey);          //// Is this message really, really, REALLY sent by me?         bool success = Cryptograph.VerifyData(messageToSign, signedMessage, publicKey);          Console.WriteLine("Is this message really, really, REALLY sent by me? " + success);      } 

Am I missing a step here? According to the Cryptography API and the examples there, I shouldn't manually compute any hashes, since I supply the algorithm within the method call itself.

Any help will be greatly appreciated.

like image 872
Simon Langhoff Avatar asked Dec 08 '11 20:12

Simon Langhoff


People also ask

How do I verify my RSA signature?

RSA Digital Signatures To sign a message m, just apply the RSA function with the private key to produce a signature s; to verify, apply the RSA function with the public key to the signature, and check that the result equals the expected message.

How can RSA be used for digital signature?

Signatures are created using the RSA algorithm by applying the RSA algorithm using the private key and then distributing the result as the signature. Because of the way the RSA algorithm works, this means the signature can be decrypted using the public key.

How do I verify a signature in Openssl?

To verify a signature, the recipient first decrypts the signature using a public key that matches with the senders private key. This produces a digest. Then the recipient calculates a digest from the received data and verifies that it matches with the one in the signature. If the digest match, the signature is valid.


1 Answers

Your problem is at the beginning of the VerifyData method:

public static bool VerifyData(string originalMessage, string signedMessage, RSAParameters publicKey) {     bool success = false;     using (var rsa = new RSACryptoServiceProvider())     {         //Don't do this, do the same as you did in SignData:         //byte[] bytesToVerify = Convert.FromBase64String(originalMessage);         var encoder = new UTF8Encoding();         byte[] bytesToVerify = encoder.GetBytes(originalMessage);          byte[] signedBytes = Convert.FromBase64String(signedMessage);         try         ... 

For some reason you switched to FromBase64String instead of UTF8Encoding.GetBytes.

like image 138
csharptest.net Avatar answered Oct 02 '22 15:10

csharptest.net