in Development

Encrypting with Certificates

.NET provides us with several algorithm implementations to perform encryption and decryption. Next you can see an easy way to make use of a certificate to encrypt / decrypt  using the RSACryptoServiceProvider

The first thing we need to do is to create a test certificate, this can be done by using the tool makecert. Just open the VS 2005 command prompt and type the next line:

makecert -n CN=Test -pe -ss My -sr LocalMachine

The command above will create a certificate called “Test” and will install it in the “My” location (displayed as “Personal”) of the Local Computer, the -pe will mark the private key as exportable.

You can see the test certificate you have created following the next steps:

1. Run the Microsoft Management Console (MMC) snap-in utility by running the command mmc from a command prompt.
2. On the File menu, click Add/Remove Snap-in.
3. In the dialog box that displays, click Add.
4. Under Snap-in, double-click Certificates.
5. Click Computer account to access the LocalMachine store, and then click Next.
6. Click Finish.
7. Click the Certificates node, Personal, Certificates and et voila, your certificate is there.

Now let’s see how we can make use of the certificate.

   1: public static X509Certificate2 LoadCertificate(StoreName storeName, 
   2:         StoreLocation storeLocation, string certificateName)
   3: {
   4:     X509Store store = new X509Store(storeName, storeLocation);
   5:  
   6:     try
   7:     {
   8:         store.Open(OpenFlags.ReadOnly);
   9:  
  10:         X509Certificate2Collection certificateCollection =
  11:             store.Certificates.Find(X509FindType.FindBySubjectName, 
  12:                                     certificateName, false);
  13:  
  14:         if (certificateCollection.Count > 0)
  15:         {
  16:             //  We ignore if there is more than one matching cert, 
  17:             //  we just return the first one.
  18:             return certificateCollection[0];
  19:         }
  20:         else
  21:         {
  22:             throw new ArgumentException("Certificate not found");
  23:         }
  24:     }
  25:     finally
  26:     {
  27:         store.Close();
  28:     }
  29: }
  30:  
  31: public static byte[] Encrypt(byte[] plainData, bool fOAEP, 
  32:                              X509Certificate2 certificate)
  33: {
  34:     if (plainData == null)
  35:     {
  36:         throw new ArgumentNullException("plainData");
  37:     }
  38:     if (certificate == null)
  39:     {
  40:         throw new ArgumentNullException("certificate");
  41:     }
  42:  
  43:     using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
  44:     {
  45:         // Note that we use the public key to encrypt
  46:         provider.FromXmlString(GetPublicKey(certificate));
  47:  
  48:         return provider.Encrypt(plainData, fOAEP);
  49:     }
  50: }
  51:  
  52: public static byte[] Decrypt(byte[] encryptedData, bool fOAEP, 
  53:                              X509Certificate2 certificate)
  54: {
  55:     if (encryptedData == null)
  56:     {
  57:         throw new ArgumentNullException("encryptedData");
  58:     }
  59:     if (certificate == null)
  60:     {
  61:         throw new ArgumentNullException("certificate");
  62:     }
  63:  
  64:     using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
  65:     {
  66:         // Note that we use the private key to decrypt
  67:         provider.FromXmlString(GetXmlKeyPair(certificate));
  68:  
  69:         return provider.Decrypt(encryptedData, fOAEP);
  70:     }
  71: }
  72:  
  73: public static string GetPublicKey(X509Certificate2 certificate)
  74: {
  75:     if (certificate == null)
  76:     {
  77:         throw new ArgumentNullException("certificate");
  78:     }
  79:  
  80:     return certificate.PublicKey.Key.ToXmlString(false);
  81: }
  82:  
  83: public static string GetXmlKeyPair(X509Certificate2 certificate)
  84: {
  85:     if (certificate == null)
  86:     {
  87:         throw new ArgumentNullException("certificate");
  88:     }
  89:  
  90:     if (!certificate.HasPrivateKey)
  91:     {
  92:         throw new ArgumentException("certificate does not have a private key");
  93:     }
  94:     else
  95:     {
  96:         return certificate.PrivateKey.ToXmlString(true);
  97:     }
  98: }

The code to use the above methods is very simple:

   1: X509Certificate2 cert = LoadCertificate(
   2:      System.Security.Cryptography.X509Certificates.StoreName.My,
   3:      System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, "Test");
   4:  
   5: byte[] encoded = System.Text.UTF8Encoding.UTF8.GetBytes("Encrypt me");
   6:  
   7: byte[] encrypted = Encrypt(encoded, true, cert);
   8: byte[] decrypted = Decrypt(encrypted, true, cert);
   9:  
  10: System.Console.Out.WriteLine(System.Text.UTF8Encoding.UTF8.GetString(decrypted));