Showing posts with label public key. Show all posts
Showing posts with label public key. Show all posts

Wednesday, January 26, 2011

How to implement digital signature in .Net using RSA

Recently I was requested to make a automatic scenario test script for a third party co company.
I needed to find a way to get the results of the tests and to verify that everything passed the 'entry criteria'. In order to do that i made my script to generate a test log file with a result line for every method.
Before i go on, I must say that i fully trust my colleagues, but i though that it will be very cool if i can really verify that no one messes with that output file and to refresh my memory on things that i haven't use for a while and even share it with some people...

so... I wanted to make a digital signature of the output file.. i will not explain how the file and all the mechanism works but i'll give you my code of a simple RSA asymetric encryption algorithm.

In here I will demonstrate a most basic implementation but that should work for a quick dive.

So in my implementation i got 3 parts:
1. Generating public and private key
2. Encrypting
3. Decrypting


using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace Tester {
   public static class Program {
      public static void Main() {
         const string privateKeyFile = @"C:\private.key";
         const string publicKeyFile = @"C:\public.key";

         DigitalSignProvider.GenerateKeysAndStoreOnFileSystem(publicKeyFile, privateKeyFile);

         var data = new byte[] { 1, 2, 3, 4, 5 };
         Console.WriteLine("Data: {0}", GetArrayString(data));

         var enData = DigitalSignProvider.Encrypt(publicKeyFile, data);
         Console.WriteLine("Encrypted Data: {0}", GetArrayString(enData));

         var deData = DigitalSignProvider.Decrypt(privateKeyFile, enData);
         Console.WriteLine("Decrypted Data: {0}", GetArrayString(deData));
      }

      private static string GetArrayString(IEnumerable array) {
         var str = new StringBuilder();
         foreach (var current in array) {
            str.AppendFormat("{0} ", current);
         }
         return str.ToString();
      }
   }

   public class DigitalSignProvider {
      const bool fOAEP = false;

      public static void GenerateKeysAndStoreOnFileSystem(string publicKeyPath, string privateKeyPath) {
         const int keyStrength = 512;
         var csp = new RSACryptoServiceProvider(keyStrength);
         var privateKey = csp.ExportCspBlob(true);
         var publicKey = csp.ExportCspBlob(false);

         using (var privateKeyFile = new FileStream(privateKeyPath, FileMode.Create)) {
            privateKeyFile.Write(privateKey, 0, privateKey.Length);
         }
         using (var publicKeyFile = new FileStream(publicKeyPath, FileMode.Create)) {
            publicKeyFile.Write(publicKey, 0, publicKey.Length);
         }
      }

      public static byte[] Decrypt(string keyPath, byte[] encryptedData) {
         var decryptionKey = File.ReadAllBytes(keyPath);
         var csp = new RSACryptoServiceProvider();
         csp.Clear();
         csp.ImportCspBlob(decryptionKey);
         return csp.Decrypt(encryptedData, fOAEP);
      }

      public static byte[] Encrypt(string keyPath, byte[] data) {
         var encryptionKey = File.ReadAllBytes(keyPath);
         var csp = new RSACryptoServiceProvider();
         csp.Clear();
         csp.ImportCspBlob(encryptionKey);
         return csp.Encrypt(data, fOAEP);
      }
   }
}


you can of course use your own key size or algorithm abstraction if you use the following
interface and abstract class: AsymmetricAlgorithm, ICspAsymmetricAlgorithm
under System.Security.Cryptorgraphy namespace


Enjoy


Gur