Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSA Encryption of large data in C#

This is my first post, so hope I haven't missed anything important. I'm doing a project in C# where I need to use public/private key encryption to encrypt a message and then send it over an SSL connection.

I chose to use the RSACryptoService, as according to the documentation, that was the only asymmetric encryption scheme used for encrypting data. The problem is that I am having a lot of problems with this. (I wanted to do symmetric encryption, but that is not what my teacher want me to do, and according to him it should be easy to just determine a block size and then it should do all the work for you.) Well, so far no luck and I've tried some different approaches, but now I'm back to basics and trying again, this is my current code:

    public string[] GenerateKeysToStrings(string uniqueIdentifier)
    {
        string[] keys;
        using (var rsa = new RSACryptoServiceProvider(4096))
        {
            try
            {
                string privateKey = rsa.ToXmlString(true);
                string publicKey = rsa.ToXmlString(false);

                this.pki.StoreKey(publicKey, uniqueIdentifier);

                keys = new string[2];
                keys[0] = privateKey;
                keys[1] = publicKey;
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return keys;
    }

As you can see, I generate the keys and I mimmick a PKI by sending the public key to a simple class that stores it, and then the private key is written to a file (Notice that I also have another method that does the same but stores it to an array instead, just because I wanted to test and simplify things as I get No such key exceptions and sometimes cryptographic exceptions when I do it the way shown in the example, so I wanted to simplify it by simply storing the rsa.ToXmlString string, as a string in an array, but no luck.)

Now I have an encrypt and decrypt method as follows:

    public string Encrypt(string keyString, string message)
    {
        string encryptedMessage;
        using (var rsa = new RSACryptoServiceProvider())
        {
            try
            {
                //// Load the key from the specified path
                var encryptKey = new XmlDocument();
                encryptKey.Load(@"C:\Test\PrivateKeyInfo.xml");
                rsa.FromXmlString(encryptKey.OuterXml);


                //// Conver the string message to a byte array for encryption
                //// var encoder = new UTF8Encoding();
                ASCIIEncoding byteConverter = new ASCIIEncoding();
                byte[] dataToEncrypt = byteConverter.GetBytes(message);

                byte[] encryptedData = rsa.Encrypt(dataToEncrypt, false);

                //// Convert the byte array back to a string message
                encryptedMessage = byteConverter.GetString(encryptedData);
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return encryptedMessage;
    }

Decryption:

    public string Decrypt(string keyString, string message)
    {
        string decryptedText;
        using (var rsa = new RSACryptoServiceProvider())
        {
            try
            {
                //// Loads the keyinfo into the rsa parameters from the keyfile
                /*
                var privateKey = new XmlDocument();
                privateKey.Load(keyString);
                 */
                rsa.FromXmlString(keyString);

                //// Convert the text from string to byte array for decryption
                ASCIIEncoding byteConverter = new ASCIIEncoding();
                var encryptedBytes = byteConverter.GetBytes(message);

                //// Create an aux array to store all the encrypted bytes
                byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, false);

                decryptedText = byteConverter.GetString(decryptedBytes);
            }
            finally
            {
                //// Clear the RSA key container, deleting generated keys.
                rsa.PersistKeyInCsp = false;
            }
        }
        return decryptedText;
    }

I know that this is a wall of text, but I hope you can help me out because I've been banging my head against the wall for so long now it's not funny :)

The problem is, how do I go about encrypting messages with RSA (or any other public/private key encryption)

Here is the Test client:

    public static void Main(string[] args)
    {
        PublicKeyInfrastructure pki = new PublicKeyInfrastructure();
        Cryptograph crypto = new Cryptograph();
        string[] keys = crypto.GenerateKeysToStrings("[email protected]");


        string plainText = "Hello play with me, please";
        string publicKey = crypto.GetPublicKey("[email protected]");

        string encryptedText = crypto.Encrypt(keys[0], plainText);


        string decryptedText = crypto.Decrypt(keys[1], encryptedText);

    }

As I mentioned, the string arrays are there because I wanted to eliminate bad parsing error from XML documents...

When I run the test client, if I use the private key to encrypt and public key to decrypt, I get a "Key does not exist exception" and if I do it the other way around, I get a bad data exception.

Please help me out guys, if you know of any good guide, or can tell me how to somewhat straightfoward implement public/private key encryption on string messages, please help me out.

I appreciate any help.

like image 340
Simon Langhoff Avatar asked Dec 07 '11 15:12

Simon Langhoff


People also ask

Can RSA encrypt large data?

As a rule of thumb, we should only encrypt data as large as the RSA key length when encrypting with RSA. Although RSA is not ideal for encrypting large files, we can use it to encrypt a key file generated from the standard AES symmetric encryption.

How much data can RSA encrypt?

RSA is only able to encrypt data to a maximum amount equal to your key size (2048 bits = 256 bytes), minus any padding and header data (11 bytes for PKCS#1 v1. 5 padding). As a result, it is often not possible to encrypt files with RSA directly (and RSA is not designed for this).

Why is RSA not suitable to encrypt large amounts of data?

Simply, RSA is very resource expensive algorithm, it takes time to generate RSA keys and to perform operations on these enormous prime numbers. As the size of data increases, the process load increases and the whole thing ends up taking too much time to complete.


1 Answers

This is not how RSA encryption should be done.

RSA is all about math. What you encrypt is a number so it has to be of finite length and matching the RSA keypair length you're using. Further length limitations are imposed by the padding used (either PKCS#1 or OAEP).

If you want to encrypt large data with RSA you need to do it indirectly - i.e. use a symmetric key to encrypt the large data and encrypt this key using the RSA public key.

You can read about implementing this on my blog.

like image 141
poupou Avatar answered Oct 05 '22 23:10

poupou