using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Configuration;
using System.Collections;
namespace .ChrisDonnan.Cryptography.Asymmetric
{
public class CryptoUtils
{
RSACryptoServiceProvider rsaPublic;
RSACryptoServiceProvider rsaPrivate;
string publicKeyPath;
string privateKeyPath;
public CryptoUtils()
{
publicKeyPath = ConfigurationSettings.AppSettings["RSA.PublicKeyPath"];
privateKeyPath = ConfigurationSettings.AppSettings["RSA.PrivateKeyPath"];
if(publicKeyPath==null)
PublicKeyPath = "PublicKey.xml";
if(privateKeyPath==null)
PrivateKeyPath = "PrivateKey.xml";
}
public void ReloadPublicKey()
{
if(rsaPublic!=null)
{
rsaPublic.Clear();
rsaPublic = null;
}
rsaPublic = new RSACryptoServiceProvider();
rsaPublic.FromXmlString(GetTextFileAsString(publicKeyPath));
}
public void ReloadPublicKey(string publicKeyFileName)
{
PublicKeyPath = publicKeyFileName;
ReloadPublicKey();
}
public void ReloadPrivateKey()
{
if(rsaPrivate!=null)
{
rsaPrivate.Clear();
rsaPrivate = null;
}
rsaPrivate = new RSACryptoServiceProvider();
rsaPrivate.FromXmlString(GetTextFileAsString(privateKeyPath));
}
public void ReloadPrivateKey(string privateKeyFileName)
{
PrivateKeyPath = privateKeyFileName;
ReloadPrivateKey();
}
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);
}
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(counter == 0 && dataToEncryptAsChars.Length<blockSize)
{
endIndex = dataToEncryptAsChars.Length;
}
else
{
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 );
}
public string RSAEncrypt(string dataToEncrypt, string publicKeyPath)
{
PublicKeyPath = publicKeyPath;
return RSAEncrypt(dataToEncrypt);
}
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)
{
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 );
}
public string RSADecrypt(string dataToDecrypt, string privateKeyPath)
{
PrivateKeyPath = privateKeyPath;
return RSADecrypt(dataToDecrypt);
}
public string PublicKeyPath
{
set {publicKeyPath = value;}
}
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));
}
}
}