Mad about .NET A blog from Jose Fco Bonnin


Recently, I recorded a Spanish video about how to encrypt/sign information using certificates and I thought it would be nice to write also a post about it. The thing is that when I tried to post it I received an alert about having a post with the same title, I already wrote this post more than two years ago :(, so while I try to figure out why I have this memory leak in my brain I will write only the missed part: how sign data using X509 certificates.

Since we already have in the previous post the code to load certificates we will focus on two methods Sign and VerifyHash.

   1:  public static byte[] Sign(byte[] hash, 
   2:      X509Certificate2 certificate)
   3:  {
   4:      if (hash == null)
   5:      {
   6:          throw new ArgumentNullException("hash");
   7:      }
   8:      if (certificate == null)
   9:      {
  10:          throw new ArgumentNullException("certificate");
  11:      }
  12:   
  13:      using (RSACryptoServiceProvider provider = 
  14:          new RSACryptoServiceProvider())
  15:      { 
  16:          provider.FromXmlString(
  17:              certificate.PrivateKey.ToXmlString(true));
  18:          return provider.SignHash(
  19:              hash,
  20:              CryptoConfig.MapNameToOID("SHA1"));
  21:      }  
  22:  }
  23:   
  24:  public static bool VerifyHash(byte[] hash, byte[] signature, 
  25:      X509Certificate2 certificate)
  26:  {
  27:      if (hash == null)
  28:      {
  29:          throw new ArgumentNullException("hash");
  30:      }
  31:      if (signature == null)
  32:      {
  33:          throw new ArgumentNullException("signature");
  34:      }
  35:      if (certificate == null)
  36:      {
  37:          throw new ArgumentNullException("certificate");
  38:      }
  39:   
  40:      using (RSACryptoServiceProvider provider = 
  41:          new RSACryptoServiceProvider())
  42:      {
  43:          provider.FromXmlString(
  44:              certificate.PublicKey.Key.ToXmlString(false));
  45:          return provider.VerifyHash(
  46:              hash, 
  47:              CryptoConfig.MapNameToOID("SHA1"), 
  48:              signature);
  49:      }
  50:  }

The idea behind these two methods is the next:

We have one party A who needs to send a message to B. B wants to be sure that the messaged received has not been modified by a third party C. To do that, A will create a digital signature that will be sent together with the message. To generate the signature A needs to compute a hash of the message, this hash is then used with method "Sign". Once A has the signature he can transmit the message and the signature to B.

When B receives the message and the signature, B needs to verify the hash. So, B computes again a hash of the received message and uses the method VerifyHash, which will return true if the message has not been modified. The next code shows you an example on how to call both methods.

   1:  static void Main(string[] args)
   2:  {
   3:      string certificateName = "Test";
   4:   
   5:      X509Certificate2 cert = LoadCertificate(
   6:          StoreName.My, 
   7:          StoreLocation.LocalMachine, 
   8:          certificateName);  
   9:      
  10:      byte[] messageSent = 
  11:          UTF8Encoding.UTF8.GetBytes("Message sent from A to B");
  12:   
  13:      // A generates the signature before send to B
  14:      SHA1Managed sha1 = new SHA1Managed();
  15:      byte[] hashA = sha1.ComputeHash(messageSent);
  16:      byte[] signature = Sign(hashA, cert);
  17:   
  18:      // B receives the message and the digital signature
  19:      byte[] messageReceived = 
  20:          UTF8Encoding.UTF8.GetBytes("Message sent from A to B");
  21:      //byte[] messageReceived = 
  22:      //  UTF8Encoding.UTF8.GetBytes("Message hacked by C");
  23:   
  24:      byte[] hashB = sha1.ComputeHash(messageReceived);
  25:   
  26:      if (VerifyHash(hashB, signature, cert))
  27:      {
  28:          Console.WriteLine("Verified");
  29:      }
  30:      else
  31:      {
  32:          Console.WriteLine("Not verified");
  33:      }
  34:   
  35:      Console.ReadKey();
  36:  }

This piece of code using the rest of methods mentioned shows you how we can verify a message has not been altered during the transmission. If you comment lines 19,20 and uncomment 21,22 you will see that after message has been altered the hash cannot be validated anymore. These short methods are one the basis of security when we try to guarantee information is not being altered from origin to destine. We have used a very basic message, but imagine you have an online shop and you don´t want people can alter from the message the number of items that will be delivered after you have authorized a payment.

Checking similar methods like SignData and VerifyData will be left as an exercise for the reader.




Comments

December 29 2009

West Virginia Payday Loans

Nice post . keep up the good work

West Virginia Payday Loans

Add comment


(Will show your Gravatar icon)

  Country flag

Captcha Image biuquote
  • Comment
  • Preview
Loading