Wednesday, January 12, 2011

Cryptography & .NET: Simple encryption & descryption using certificates

Here's a simple toy that describes encryption with a public key by a sender and decryption with a private key by the receiver. Notice that the only object that's sent is the cipher text. Other than that, all entities don't cross boundaries, nor the certificate (which in one case is read from the store, from the file in the other).

First, you have to create a suitable certificate. Only caveats: mark its key for 'Exchange' type, and its private key exportable:

makecert.exe Test.cer -r -n "CN=Test Subject" -sr LocalMachine -ss My -sky Exchange -pe



Then, the code, which is mostly self explanatory. (Keys are accessed through providers that encapsulate calculations performed with them.)

        private void TestSenderReceiver()
{
//////////////////////////////////////////////////////
// SENDER CODE
//////////////////////////////////////////////////////

// get certificate
var certSender = new X509Certificate2(@"C:\Test.cer");

// encrypt with public key
var providerSender = (RSACryptoServiceProvider)certSender.PublicKey.Key;
var plainSender = Encoding.Default.GetBytes("this is plain text");
var cipher = providerSender.Encrypt(plainSender, false);

//////////////////////////////////////////////////////
// RECEIVER CODE
//////////////////////////////////////////////////////

// get certificate
var store = new X509Store("MY", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
var certReceiver = store.Certificates.Find(X509FindType.FindBySubjectName, "Test Subject", false)[0];

// decrypt with private key
var providerReceiver = (RSACryptoServiceProvider)certReceiver.PrivateKey;
var plainReceiver = providerReceiver.Decrypt(cipher, false);

// check they are same
int i;
for (i = 0; i < plainSender.Length && i < plainReceiver.Length; i++)
{
if(plainSender[i] != plainReceiver[i])
{
break;
}
}
if(i == plainSender.Length && i == plainReceiver.Length)
{
Console.WriteLine("Same!");
}
}

No comments: