Friday
Jul242009
C# Symmetric encryption wrapper
Friday, July 24, 2009 at 4:29PM The original class for this post can be found at codeproject.com. This class is a tidied up version (and disposes more aggressively). You may get issues with the GetLegalIV portion of the code, particularly with triple DES. This is because it pads the IV with spaces, and is not compatible with other implementations of the algorithm, such as the Perl one. The class uses UTF8.
using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
/// <summary>
/// Provides the standard 4 types of symmetric encryption
/// methods supported by the .net framework.
/// </summary>
public enum EncryptionType
{
/// <summary>
/// Data Encryption Standard algorithm, created in 1977.
/// The standard encryption strength of DES is 56bit. The
/// algorithm has been cracked using 100,00 PCs (combined power via the
/// internet) in 22 hours 15 minutes!
/// A detailed explanation can be found at:
/// http://www.tropsoft.com/strongenc/des.htm
/// </summary>
DES,
/// <summary>
/// RC2 was created by RSA as a proposed replacement for
/// the DES encryption standard. Its strength is 64bit
/// (64bit block sizes). The RFC for the standard can
/// be found at:
/// http://www.networksorcery.com/enp/rfc/rfc2268.txt
/// </summary>
RC2,
/// <summary>
/// Rijndael is the encryption algorithm used for
/// the Advanced Encryption Standard (AES), the standard
/// symmetric encryption method used by US Government organisations.
/// The block size can be 128, 192, or 256 bits.
/// Further information can be found at:
/// http://csrc.nist.gov/CryptoToolkit/aes/rijndael/
/// </summary>
Rijndael,
/// <summary>
/// Triple DES is a more powerful form of the original DES standard,
/// encrypting data using 364bit keys, giving Triple DES a strength
/// of 192bits. The data is encrypted with the first key,
/// decrypted with the second key, and finally encrypted again with
/// the third key.
/// A detailed explaination of the algorithm can be found at:
/// http://www.tropsoft.com/strongenc/des3.htm
/// </summary>
TripleDES
//RC4
}
/// <summary>
/// SymmetricEncryption is a wrapper of System.Security.Cryptography.SymmetricAlgorithm
/// classes and simplifies the interface. Symmetric encryption involves a private
/// key to encrypt the data, which enables the data to be de-crypted by other
/// clients, providing they have the private key.
///
/// This class is based on Frank Fang's 'SymmCrypto' class, found at:
/// http://www.codeproject.com/dotnet/encryption_decryption.asp
/// </summary>
public class SymmetricEncryption
{
private string _initialIV = "12345678";
private SymmetricAlgorithm _symmetricAlgorithm;
public string InitialIV
{
get
{
return _initialIV;
}
set
{
_initialIV = value;
}
}
/// <summary>
/// Creates a new SymmetricEncryption class with the EncryptionType provided.
/// </summary>
/// <param name="Type">The type of symmetric encryption to use.</param>
public SymmetricEncryption(EncryptionType Type)
{
switch (Type)
{
case EncryptionType.DES:
_symmetricAlgorithm = new DESCryptoServiceProvider();
break;
case EncryptionType.RC2:
_symmetricAlgorithm = new RC2CryptoServiceProvider();
break;
case EncryptionType.Rijndael:
_symmetricAlgorithm = new RijndaelManaged();
break;
case EncryptionType.TripleDES:
_symmetricAlgorithm = new TripleDESCryptoServiceProvider();
break;
/*case EncryptionType.RC4:
symmetricAlgorithm = new Org.Mentalis.Security.Cryptography.RC4CryptoServiceProvider();
break;*/
}
}
/// <summary>
/// Creates a new SymmetricEncryption class with the SymmetricAlgorithm
/// provided (which could include an implementation of an algorithm
/// not provided in the standard .net fcl).
/// </summary>
/// <param name="ServiceProvider">A</param>
public SymmetricEncryption(SymmetricAlgorithm ServiceProvider)
{
_symmetricAlgorithm = ServiceProvider;
}
/// <summary>
/// Encrypts data using the key provided, and the algorithm
/// specified in the constructor of the class.
/// </summary>
/// <param name="contents">The data to encrypt.</param>
/// <param name="key">The key to encrypt the data with. The longer
/// and more random the key, the stronger the encryption is.</param>
/// <returns>A string containing the contents, encrypted using the
/// key and the algorithm specified in the constructor of the class.</returns>
public string Encrypt(string contents, string key)
{
// Change to Unicode if you're using a wide character set
byte[] buffer = Encoding.UTF8.GetBytes(contents);
// Create a MemoryStream so that the process can be done without I/O files
using (MemoryStream memoryStream = new MemoryStream())
{
// Set the private key
_symmetricAlgorithm.Key = GetLegalKey(key);
_symmetricAlgorithm.IV = GetLegalIV();
// Create an Encryptor from the Provider Service instance
using (ICryptoTransform transform = _symmetricAlgorithm.CreateEncryptor())
{
// Create Crypto Stream that transforms a stream using the encryption
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
{
// write out encrypted content into MemoryStream
cryptoStream.Write(buffer, 0, buffer.Length);
cryptoStream.FlushFinalBlock();
memoryStream.Close();
byte[] result = memoryStream.ToArray();
// Convert into Base64 so that the result is XML or web safe
return Convert.ToBase64String(result);
}
}
}
}
/// <summary>
/// Decrypts data using the key provided, and the algorithm
/// specified in the constructor of the class.
/// </summary>
/// <param name="contents">The data to decrypt.</param>
/// <param name="key">The key to decrypt the data with.</param>
/// <returns>A string containing the contents, decrypted using the
/// key and the algorithm specified in the constructor of the class.</returns>
public string Decrypt(string contents, string key)
{
// Convert from Base64 to binary
byte[] buffer = Convert.FromBase64String(contents);
// Create a MemoryStream with the input
using (MemoryStream memorystream = new MemoryStream(buffer, 0, buffer.Length))
{
// Set the private key
_symmetricAlgorithm.Key = GetLegalKey(key);
_symmetricAlgorithm.IV = GetLegalIV();
// Create a Decryptor from the Provider Service instance
using (ICryptoTransform transform = _symmetricAlgorithm.CreateDecryptor())
{
// Create Crypto Stream that transforms a stream using the decryption
using (CryptoStream cryptoStream = new CryptoStream(memorystream, transform, CryptoStreamMode.Read))
{
// Read out the result from the Crypto Stream. Change to Unicode if you're using a wide character set
using (StreamReader reader = new StreamReader(cryptoStream,Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
}
private byte[] GetLegalKey(string Key)
{
string sTemp = Key;
_symmetricAlgorithm.GenerateKey();
byte[] bytTemp = _symmetricAlgorithm.Key;
int KeyLength = bytTemp.Length;
if (sTemp.Length > KeyLength)
sTemp = sTemp.Substring(0, KeyLength);
else if (sTemp.Length < KeyLength)
sTemp = sTemp.PadRight(KeyLength, ' ');
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
private byte[] GetLegalIV()
{
// The initial string of IV may be modified with any data you like
string sTemp = _initialIV;
_symmetricAlgorithm.GenerateIV();
byte[] bytTemp = _symmetricAlgorithm.IV;
int IVLength = bytTemp.Length;
if (sTemp.Length > IVLength)
sTemp = sTemp.Substring(0, IVLength);
else if (sTemp.Length < IVLength)
sTemp = sTemp.PadRight(IVLength, ' ');
return ASCIIEncoding.ASCII.GetBytes(sTemp);
}
}






Reader Comments