Warm tip: This article is reproduced from serverfault.com, please click

RSA Encryption of large data in C#

发布于 2011-12-07 15:37:55

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("simonlanghoff@gmail.com");


        string plainText = "Hello play with me, please";
        string publicKey = crypto.GetPublicKey("simonlanghoff@gmail.com");

        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.

Questioner
Simon Langhoff
Viewed
0
143k 2016-06-24 16:41:09

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.