none
How to encrypt and decrypt a larger string using RSA public and private key RRS feed

  • Question

  • Hi everybody,

    Actually I want to encrypt a larger string and decrypt it using RSA public and private keys. But actually what is happening for a 1024 key size, I can only able to use 117 byte length string.

    But I want to encrypt and decrypt a larger string. Please someone give me an idea or simple solutions to do this.

    Regards,

    T.Selvakumar

    Thursday, February 7, 2013 11:53 AM

All replies

  • Hi,

    can you give the code how you encrypt / decrypt so far? The 117byte length limit is really confusing and I am wondering what you did.

    The RsaCryproServiceProvide already contains example code on how to decrypt and encrypt:
    http://msdn.microsoft.com/en-us/library/system.security.cryptography.rsacryptoserviceprovider.aspx

    With kind regards,

    Konrad


    Thursday, February 7, 2013 11:58 AM
  • Hi,

    This is the code I use.

    const int keySize = 1024;
                string publicAndPrivateKey;
                string publicKey;

                AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
                int maxDataLength = AsymmetricEncryption.GetMaxDataLength(keySize);

                string text = "this is a string to encrypt and decrypt using RSA cryptographic algorithm. this is a string to encrypt and decrypt using RSA cryptographic algorithm";
                
                string  encrypted = AsymmetricEncryption.EncryptText(text, keySize, publicKey);
                Console.WriteLine(encrypted);
                string decrypted = AsymmetricEncryption.DecryptText(encrypted, keySize, publicAndPrivateKey);
                Console.WriteLine("Encrypted: {0}", encrypted);
                Console.WriteLine("Decrypted: {0}", decrypted);

    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 (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
                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;
            }
        }

    Now I want to change this algorithm to suite that can encrypt as much of text I can. This code written my ex-colleague. Now I am modifying it.

    Regards,

    T.Selvakumar

    Thursday, February 7, 2013 1:31 PM
  • Hi,

    sorry that I didn't understand you directly. I simply misses the RSA part / forgot that RSA has this limitation.

    The core solutions are:

    a) increase the size of the key. That will increase the possible size of the unencrypted text.
    b) use a symetric encryption of the core content and only use the asymetric RSA algorithm to encrypt the symetric key.  (I think this is the common approach)
    c) Technically you could chop up the message in a lot of smaller messages but that is seen as unsafe and is really not recommend.

    With kind regards,

    Konrad

    Thursday, February 7, 2013 2:35 PM
  • Hi,

    Thanks for your reply. Finally I found a new sample code to encrypt a larger text. But I need to know How to decrypt it?

    Here is my encryption codepublic static string Encrypt(string publicKey, string data, RsaKeyLengths length)
            {
                // full array of bytes to encrypt
                byte[] bytesToEncrypt;

                // worker byte array
                byte[] block;

                // encrypted bytes
                byte[] encryptedBytes;

                // length of bytesToEncrypt
                var dataLength = 0;

                // number of bytes in key                
                var keySize = 0;

                // maximum block length to encrypt          
                var maxLength = 0;

                // how many blocks must we encrypt to encrypt entire message?
                var iterations = 0;

                // the encrypted data
                var encryptedData = new StringBuilder();

                // instantiate the crypto provider with the correct key length
                var rsaCryptoServiceProvider = new RSACryptoServiceProvider((int)length);

                // initialize the RSA object from the given public key
                rsaCryptoServiceProvider.FromXmlString(publicKey);

                // convert data to byte array
                bytesToEncrypt = Encoding.Unicode.GetBytes(data);

                // get length of byte array
                dataLength = bytesToEncrypt.Length;

                // convert length of key from bits to bytes
                keySize = (int)length / 8;

                // .NET RSACryptoServiceProvider uses SHA1 Hash function
                // use this to work out the maximum length to encrypt per block
                maxLength = ((keySize - 2) - (2 * SHA1.Create().ComputeHash(bytesToEncrypt).Length));

                // how many blocks do we need to encrypt?
                iterations = dataLength / maxLength;

                // encrypt block by block
                for (int index = 0; index <= iterations; index++)
                {
                    // is there more than one full block of data left to encrypt?
                    if ((dataLength - maxLength * index) > maxLength)
                    {
                        block = new byte[maxLength];
                    }
                    else
                    {
                        block = new byte[dataLength - maxLength * index];
                    }

                    // copy the required number of bytes from the array of bytes to encrypt to our worker array
                    Buffer.BlockCopy(bytesToEncrypt, maxLength * index, block, 0, block.Length);

                    // encrypt the current worker array block of bytes
                    encryptedBytes = rsaCryptoServiceProvider.Encrypt(block, true);

                    // RSACryptoServiceProvider reverses the order of encrypted bytesToEncrypt after encryption and before decryption.
                    // Undo this reversal for compatibility with other implementations
                    Array.Reverse(encryptedBytes);

                    // convert to base 64 string
                    encryptedData.Append(Convert.ToBase64String(encryptedBytes));

                }
                return encryptedData.ToString();

            }

    Any Idea about decryption?

    Regards,

    T. Selvakumar

    • Proposed as answer by Mahesh Chatla Saturday, April 6, 2013 9:12 AM
    Friday, February 8, 2013 10:28 AM
  • HI SelvaKumar,

    i need the same like how you did, i need to encrypt the some plain text and give it to another client for the decryption along with the public key.

    Could you please explain me on this how to do clearly.

    Thanks in Advance,

    Mahesh.


    Mahesh

    Saturday, April 6, 2013 12:06 PM