Asymmetric Encryption

Posted: September 3, 2012 in .NET
Tags: ,

We are in the mobile application era. Almost every development nowadays involves thinking about mobile.

Like in the past when we start o think about Web, a scenario where we have a lot of private data being passed in the wire, we need secure algorithms.

Since security problems are in the order of the day o decided to share one of the algorithms that better feet in this kind of scenarios. This algorithm had the benefit that the secret to get data is not shared by all the participants in the conversation.

In my opinion is one of the best approaches to  use in  mobile and internet scenarios since we have clients who don’t have keys while loading encrypted content to their computers.

In this algorithm Encryption and Decryption of data relies on the key pair where we have public and private key. The first key (known as the Public Key) in the pair can only be used to Encrypt the data, whereas the second key (known as the Private Key) can only be used to Decrypt the data encrypted by the Public Key.

the Sender has access to the Public Key so can Encrypt data.  Only the Receiver has access to the Private Key, therefore is the only person who can Decrypt the data. The Public Key can of course be distributed freely without any worry about who has access to it, since the only function available is to Encrypt data.

In the next figure you have an example of this kind of algorithm here Bob sends to Alice an encrypted file, and she opens that file with her private key

So after understanding what’s the algorithm is all about the next challenge is to know how to implement a situation like this, if that’s your question i present you one implementation of this algorithm using C#.

For that i had create the class AsymmetricEncryption that allow us to use the algorithm, this is a canonical approach feel free to use this implementation.

 

using System;
using System.Security.Cryptography;
using System.Text;
public static class AsymmetricEncryption
{
    private static bool _optimalAsymmetricEncryptionPadding = false;

    public static void GenerateKeys(int keySize, out string publicKey, out string publicAndPrivateKey)
    {
        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            publicKey = provider.ToXmlString(false);
            publicAndPrivateKey = provider.ToXmlString(true);
        }
    }

    public static string EncryptText(string text, int keySize, string publicKeyXml)
    {
        var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKeyXml);
        return Convert.ToBase64String(encrypted);
    }

    public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        int maxLength = GetMaxDataLength(keySize);
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");

        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicKeyXml);
            return provider.Encrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }

    public static string DecryptText(string text, int keySize, string publicAndPrivateKeyXml)
    {
        var decrypted = Decrypt(Convert.FromBase64String(text), keySize, publicAndPrivateKeyXml);
        return Encoding.UTF8.GetString(decrypted);
    }

    public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
    {
        if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
        if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
        if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");

        using (var provider = new RSACryptoServiceProvider(keySize))
        {
            provider.FromXmlString(publicAndPrivateKeyXml);
            return provider.Decrypt(data, _optimalAsymmetricEncryptionPadding);
        }
    }

    public static int GetMaxDataLength(int keySize)
    {
        if (_optimalAsymmetricEncryptionPadding)
        {
            return ((keySize - 384) / 8) + 7;
        }
        return ((keySize - 384) / 8) + 37;
    }

    public static bool IsKeySizeValid(int keySize)
    {
        return keySize >= 384 &&
                keySize <= 16384 &&
                keySize % 8 == 0;
    }
}

A sniped to test this code would be

AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);

string text = "text for encryption";
string encrypted = AsymmetricEncryption.EncryptText(text, keySize, publicKey);
string decrypted = AsymmetricEncryption.DecryptText(encrypted, keySize, publicAndPrivateKey);



Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s