Asymmetric encryption in C# using RSA

Feel free to re-use this code for asymmetric encryption/decryption of large data.

    /// <summary>
    /// Asymmetric key pair container.
    /// </summary>
    public class AsymmetricKeyPair
    {
        private readonly string _publicKey;
        private readonly string _privateKey;

        internal AsymmetricKeyPair(string publicKey, string privateKey)
        {
            _publicKey = publicKey;
            _privateKey = privateKey;
        }

        /// <summary>
        /// Asymmetric private RSA key.
        /// </summary>
        public string PrivateKey
        {
            get { return _privateKey; }
        }

        /// <summary>
        /// Asymmetric public RSA key.
        /// </summary>
        public string PublicKey
        {
            get { return _publicKey; }
        }
    }
    /// <summary>
    /// Asymmetric encryption class that provides:
    /// <ul>
    /// <li>Generation of Asymmetric encryption/decryption keys using RSA.</li>
    /// <li>Encryption of text using asymmetric public key.</li>
    /// <li>Decryption of text using asymmetric private key.</li>
    /// </ul>
    /// </summary>
    public static class AsymmetricEncryption
    {
        #region "Private members"
        private static bool _optimalAsymmetricEncryptionPadding = false;
        #endregion

        #region "Public members"
        public static bool OptimalAsymmetricEncryptionPadding
        {
            get { return _optimalAsymmetricEncryptionPadding; }
            set { _optimalAsymmetricEncryptionPadding = value; }
        }
        #endregion

        #region "Public methods"
        /// <summary>
        /// Generates a new pair of asymmetric encryption/decryption keys
        /// </summary>
        /// <param name="keySize">The size of the key to be used in bits. Recommended 1024.</param>
        /// <returns>Returns <see cref="AsymmetricKeyPair"/></returns>
        /// <exception cref="ArgumentException">Thrown in the following situations
        /// <ul>
        /// <li>An invalid key size is provided.</li>
        /// </ul>
        /// </exception>
        public static AsymmetricKeyPair GenerateKeys(int keySize)
        {
            if (!IsKeySizeValid(keySize)) throw new ArgumentException("The provided key size is invalid.", "keySize");
            using (var provider = new RSACryptoServiceProvider(keySize))
            {
                return new AsymmetricKeyPair(provider.ToXmlString(false), provider.ToXmlString(true));
            }
        }

        /// <summary>
        /// Encrypts the provided text using the public key.
        /// </summary>
        /// <param name="text">Text to be encrypted.</param>
        /// <param name="publicKeyXml">XML string containing the public RSA key.</param>
        /// <param name="keySize">Size of the key used when generating the key pair. Default 1024 bits.</param>
        /// <returns>Encrypted text.</returns>
        /// <exception cref="ArgumentException">Thrown in the following situations
        /// <ul>
        /// <li>The provided text is empty or null.</li>
        /// <li>Length of the provided text exceeds the maximum string length that can be encrypted for the specified key size.</li>
        /// <li>An invalid key size is provided.</li>
        /// <li>The provided key is null or empty.</li>
        /// </ul>
        /// </exception>
        /// <exception cref="CryptographicException">Thrown when the format of the provided key is invalid.</exception>
        public static string EncryptText(string text, string publicKeyXml, int keySize)
        {
            int byteKeySize = keySize / 8;
            byte[] bytes = Encoding.UTF32.GetBytes(text);
            int maxLength = byteKeySize - 42;
            int dataLength = bytes.Length;
            int iterations = dataLength / maxLength;
            StringBuilder stringBuilder = new StringBuilder();

            if (!IsKeySizeValid(keySize)) throw new ArgumentException("The provided key size is invalid.", "keySize");
            if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("The provided key is null or empty", "publicKeyXml");

            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(keySize);
            rsaCryptoServiceProvider.FromXmlString(publicKeyXml);

            for (int counter = 0; counter <= iterations; counter++)
            {
                byte[] tempBytes = new byte[(dataLength - maxLength * counter > maxLength) ? maxLength : dataLength - maxLength * counter];
                Buffer.BlockCopy(bytes, maxLength * counter, tempBytes, 0, tempBytes.Length);
                byte[] encryptedBytes = rsaCryptoServiceProvider.Encrypt(tempBytes, true);
                Array.Reverse(encryptedBytes);
                stringBuilder.Append(Convert.ToBase64String(encryptedBytes));
            }
            return stringBuilder.ToString();

        }

        /// <summary>
        /// Decrypts the provided text using the public and private RSA key.
        /// </summary>
        /// <param name="text">Text to be decrypted.</param>
        /// <param name="publicAndPrivateKeyXml">XML string containing the public and private RSA key.</param>
        /// <param name="keySize">Size of the key used when generating the key pair. Default 1024 bits.</param>
        /// <returns>Decrypted text.</returns>
        /// <exception cref="ArgumentException">Thrown in the following situations
        /// <ul>
        /// <li>The provided text is empty or null.</li>
        /// <li>An invalid key size is provided.</li>
        /// <li>The provided key is null or empty.</li>
        /// </ul>
        /// </exception>
        /// <exception cref="CryptographicException">Thrown when the format of the provided key is invalid.</exception>
        public static string DecryptText(string text, string publicAndPrivateKeyXml, int keySize)
        {

            RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider(keySize);
            rsaCryptoServiceProvider.FromXmlString(publicAndPrivateKeyXml);

            int base64BlockSize = ((keySize / 8) % 3 != 0) ? (((keySize / 8) / 3) * 4) + 4 : ((keySize / 8) / 3) * 4;
            int iterations = text.Length / base64BlockSize;
            var arrayList = new ArrayList();

            for (int i = 0; i < iterations; i++)
            {
                byte[] encryptedBytes = Convert.FromBase64String(text.Substring(base64BlockSize * i, base64BlockSize));
                Array.Reverse(encryptedBytes);
                arrayList.AddRange(rsaCryptoServiceProvider.Decrypt(encryptedBytes, true));
            }
            return Encoding.UTF32.GetString(arrayList.ToArray(Type.GetType("System.Byte")) as byte[]);

        }

        #endregion

        #region "Private methods"
        private static bool IsKeySizeValid(int keySize)
        {
            return keySize >= 384 &&
                   keySize <= 16384 &&
                   keySize % 8 == 0;
        }

        private static int GetMaxDataLength(int keySize)
        {
            //Uncomment the following if we enable toggling of the OAEP option
            if (OptimalAsymmetricEncryptionPadding)
            {
                return ((keySize - 384) / 8) + 7;
            }
            return ((keySize - 384) / 8) + 37;
        }
        #endregion
    }

You can download the nuget package here.