June 2003 - Posts

More useful code - lets oversimplify asymmetric encryption for general convenience . . .

using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Configuration;
using System.Collections;
namespace .ChrisDonnan.Cryptography.Asymmetric
{
        /// <summary>
        /// Summary description for Class1.
        /// </summary>
        public class CryptoUtils
        {
                RSACryptoServiceProvider rsaPublic;
                RSACryptoServiceProvider rsaPrivate;
                string publicKeyPath;
                string privateKeyPath;
                /// <summary>
                /// on instantiation, the PublicKeyPath and PrivateKeyPath are pulled from the ConfigurationSettings.AppSettings
                /// by default. If they are not found here, they default to "PublicKey.xml" and "PrivateKey.xml" respectively.
                /// </summary>
                public CryptoUtils()
                {
                        publicKeyPath = ConfigurationSettings.AppSettings["RSA.PublicKeyPath"];
                        privateKeyPath = ConfigurationSettings.AppSettings["RSA.PrivateKeyPath"];
                        
                        if(publicKeyPath==null)
                                PublicKeyPath = "PublicKey.xml";
                        if(privateKeyPath==null)
                                PrivateKeyPath = "PrivateKey.xml";              
                }
                /// <summary>
                /// used if you want to change Public key
                /// </summary>
                public void ReloadPublicKey()
                {
                        if(rsaPublic!=null)
                        {
                                rsaPublic.Clear();
                                rsaPublic = null;
                        }
                        rsaPublic = new RSACryptoServiceProvider();
                        rsaPublic.FromXmlString(GetTextFileAsString(publicKeyPath));
                }
                /// <summary>
                /// used if you want to change Public key
                /// </summary>
                /// <param name="privateKeyFileName"></param>
                public void ReloadPublicKey(string publicKeyFileName)
                {
                        PublicKeyPath = publicKeyFileName;
                        ReloadPublicKey();
                }
                /// <summary>
                /// used if you want to change Private key
                /// </summary>
                public void ReloadPrivateKey()
                {
                        if(rsaPrivate!=null)
                        {
                                rsaPrivate.Clear();
                                rsaPrivate = null;
                        }
                        rsaPrivate = new RSACryptoServiceProvider();
                        rsaPrivate.FromXmlString(GetTextFileAsString(privateKeyPath));
                }
                /// <summary>
                /// used if you want to change Private key
                /// </summary>
                /// <param name="privateKeyFileName"></param>
                public void ReloadPrivateKey(string privateKeyFileName)
                {
                        PrivateKeyPath = privateKeyFileName;
                        ReloadPrivateKey();
                }
                /// <summary>
                /// saves a key pair to the supplied files
                /// </summary>
                /// <param name="publicKeyFileName">a file name (path/path/file.ext etc, or file.ext)</param>
                /// <param name="privateKeyFileName">a file name (path/path/file.ext etc, or file.ext)</param>
                ///  <param name="keySize">between 384 (48 byte) and 16384 (2048 byte)</param>
                public static void GenerateKeyPair(int keySize, string publicKeyFileName, string privateKeyFileName)
                {
                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize);
                        string publicKey = rsa.ToXmlString(false);
                        string privateKey = rsa.ToXmlString(true);
                        SaveTextFile(publicKey,publicKeyFileName);
                        SaveTextFile(privateKey,privateKeyFileName);
                }
                /// <summary>
                /// Main encryption method for RSA Encryption
                /// This method uses the Public Key
                /// kyey size between 384 (48 byte) and 16384 (2048 byte)
                /// (key size bytes - 11 = byte blobk size)
                /// Modulus size - 11. (11 bytes is the minimum padding possible.)
                /// </summary>
                /// <param name="dataToEncrypt"></param>
                /// <returns>Base64 Encrypted data</returns>
                public string RSAEncrypt(string dataToEncrypt)
                {
                        if(dataToEncrypt==null)
                                return string.Empty;
                        if(rsaPublic==null)
                                rsaPublic= new RSACryptoServiceProvider();
                        rsaPublic.FromXmlString(GetTextFileAsString(publicKeyPath));
                        int keySizeInBytes = rsaPublic.KeySize/8;
                        int blockSize = keySizeInBytes - 11;
                        int iterations = 0;
                        if(dataToEncrypt.Length % blockSize  != 0)
                        {
                                iterations = ((int)dataToEncrypt.Length/blockSize) + 1 ;
                        }
                        else
                        {
                                iterations = (int)dataToEncrypt.Length/blockSize;
                        }
                        
                        byte[] allEncryptedBytes = new byte[iterations*keySizeInBytes];
                        char[] dataToEncryptAsChars = dataToEncrypt.ToCharArray();
                        int index = 0;
                        int counter = 0;
                        for(;counter < iterations; index+=blockSize, ++counter)
                        {
                                int doneSoFar = counter * blockSize;
                                int endIndex = 0;
                                //if 1st iteration and data smaller than block
                                if(counter == 0 && dataToEncryptAsChars.Length<blockSize)
                                {
                                        endIndex = dataToEncryptAsChars.Length;
                                }
                                else
                                {
                                        //final block
                                        if(counter==iterations-1)
                                        {
                                                endIndex = dataToEncryptAsChars.Length % blockSize;
                                        }
                                        else
                                        {
                                                endIndex = blockSize;
                                        }
                                }
                                byte[] buffer = ASCIIEncoding.ASCII.GetBytes(dataToEncryptAsChars,index,endIndex);
                                byte[] encryptedBytes = rsaPublic.Encrypt(buffer,false);
                                Array.Copy(encryptedBytes,0,allEncryptedBytes,counter*keySizeInBytes,keySizeInBytes);
                        }
                        return Convert.ToBase64String( allEncryptedBytes );
                }
                
                /// <summary>
                /// Override for dealing with a supplied publicKeyPath
                /// </summary>
                /// <param name="dataToEncrypt"></param>
                /// <param name="publicKeyPath"></param>
                /// <returns></returns>
                public string RSAEncrypt(string dataToEncrypt, string publicKeyPath)
                {
                        PublicKeyPath = publicKeyPath;
                        return RSAEncrypt(dataToEncrypt);
                }
                /// <summary>
                /// This method uses the private key
                /// </summary>
                /// <param name="dataToDecrypt">Base64 RSA Encrypted data</param>
                /// <returns></returns>
                public string RSADecrypt(string dataToDecrypt)
                {
                        if(dataToDecrypt==null)
                                return string.Empty;
                        if(rsaPrivate==null)
                                rsaPrivate= new RSACryptoServiceProvider();
                        rsaPrivate.FromXmlString(GetTextFileAsString(privateKeyPath));
                        int keySizeInBytes = rsaPublic.KeySize/8;
                        int blockSize = keySizeInBytes - 11;
                        int iterations = 0;
                        byte[] dataToDecryptBuffer = Convert.FromBase64String(dataToDecrypt);
                        if(dataToDecryptBuffer.Length % keySizeInBytes  != 0)
                                throw new ApplicationException("malformed data to decrypt");
                        iterations = dataToDecryptBuffer.Length/ keySizeInBytes;
                        int counter = 0;
                        Queue q = new Queue();
                        for(;counter < iterations; ++counter)
                        {
                                int doneSoFar = counter * keySizeInBytes;
                                byte[] buffer = new byte[keySizeInBytes];
                                Array.Copy(dataToDecryptBuffer,counter*keySizeInBytes,buffer,0,keySizeInBytes);
                                byte[] decryptedBytes = rsaPrivate.Decrypt(buffer,false);
                                q.Enqueue(decryptedBytes);
                        }
                        int byteCount = 0;
                        foreach(byte[] b in q)
                        {
                                byteCount+=b.Length;
                        }
                        byte[] allDecryptedBytes = new byte[byteCount];
                        counter = 0;
                        foreach(byte[] b in q)
                        {
                                //last one
                                if(counter==iterations-1)
                                {
                                        Array.Copy(b,0,allDecryptedBytes,allDecryptedBytes.Length-b.Length,b.Length);
                                }
                                else
                                {
                                        Array.Copy(b,0,allDecryptedBytes,counter*blockSize,blockSize);
                                }
                                ++counter;
                        }
                        
                        return ASCIIEncoding.ASCII.GetString( allDecryptedBytes );
                }
                /// <summary>
                /// Override for dealing with a supplied privateKeyPath
                /// </summary>
                /// <param name="dataToDecrypt"></param>
                /// <param name="privateKeyPath"></param>
                /// <returns></returns>
                public string RSADecrypt(string dataToDecrypt, string privateKeyPath)
                {
                        PrivateKeyPath = privateKeyPath;
                        return RSADecrypt(dataToDecrypt);
                }
                /// <summary>
                /// path to XML persisted RSA key; the public or distributable key
                /// </summary>
                public string PublicKeyPath
                {
                        set {publicKeyPath = value;}
                }
                /// <summary>
                /// path to XML persisted RSA key; the private or non-distributable key
                /// </summary>
                public string PrivateKeyPath
                {
                        set {privateKeyPath = value;}
                }
                static void SaveTextFile(string text, string file)      
                {
                        StreamWriter writer = new StreamWriter (new FileStream(file, FileMode.Create));
                        writer.Write(text);
                        writer.Close();
                }
                static byte[] BinaryFileAsBytes(string fileName)        
                {
                        FileStream fs = File.OpenRead(fileName);
                        BinaryReader br = new BinaryReader(fs);
                        return br.ReadBytes((int)fs.Length);
                }
                static string GetTextFileAsString(string fileName)      
                {
                        return Encoding.ASCII.GetString(BinaryFileAsBytes(fileName));
                }
        }
}

ReturnCode.cs - helper class of the day :) Use it :)

Document
using System;
namespace Utils
{
        ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Class to encapsulate the result of a method call.
        /// </summary>
        public class ReturnCode {
                private int number = 0;
                private string message;
                private DateTime created;
                private object resultObject;
                /// <summary>
                /// 
                /// </summary>
                public int Number       {
                        get     { return number;        }
                        set { number = value;   }               
                }
                /// <summary>
                /// 
                /// </summary>
                public string Message   {
                        get     { return message;       }
                        set { message = value;  }               
                }       
                /// <summary>
                /// 
                /// </summary>
                public DateTime Created {
                        get     { return created;       }
                        set { created = value;  }               
                }
                /// <summary>
                /// 
                /// </summary>
                public object ResultObject
                {
                        get     { return resultObject;  }
                        set { resultObject = value;     }               
                }
                /// <summary>
                /// 
                /// </summary>
                /// <param name="number"></param>
                /// <param name="message"></param>
                public ReturnCode( int number, string message   )       
                {
                        this.Number = number;
                        this.Message = message;
                        this.Created = DateTime.Now;
                }                       
                /// <summary>
                /// 
                /// </summary>
                /// <returns></returns>
                public override strin