Fast Lightweight .NET Client Encryption -> Server Decryption - c#

I have a simple client/server setup. The client and the server both have a private key.
What does .NET offer me in the way of
ClientData-> ClientEncrypt with KEY-> Transmit to Server-> ServerDecrypt with KEY-> ClientData
Can anyone suggest any fast simple libraries to read up on?
Thanks

RijndaelManaged:
Here's an example:
private static string CreateEncryptedString(string myString, string hexiv, string key)
{
RijndaelManaged alg = new RijndaelManaged();
alg.Padding = PaddingMode.Zeros;
alg.Mode = CipherMode.CBC;
alg.BlockSize = 16 * 8;
alg.Key = ASCIIEncoding.UTF8.GetBytes(key);
alg.IV = StringToByteArray(hexiv);
ICryptoTransform encryptor = alg.CreateEncryptor(alg.Key, alg.IV);
MemoryStream msStream = new MemoryStream();
CryptoStream mCSWriter = new CryptoStream(msStream, encryptor, CryptoStreamMode.Write);
StreamWriter mSWriter = new StreamWriter(mCSWriter);
mSWriter.Write(myString);
mSWriter.Flush();
mCSWriter.FlushFinalBlock();
var EncryptedByte = new byte[msStream.Length];
msStream.Position = 0;
msStream.Read(EncryptedByte, 0, (int)msStream.Length);
return ByteArrayToHexString(EncryptedByte);
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
public static string ByteArrayToHexString(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
You can easily come out with a decryption algorithm and the examples ( or just google it around!)

using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;
namespace ServiceConsole
{
public class Obfuscation
{
public static byte[] Encrypt(string data)
{
return Encrypt(data, SecurityCredentials.KeyString, SecurityCredentials.IvString);
}
public static byte[] Encrypt(string data, string key, string iv)
{
return Encrypt(data, key, iv, SecurityCredentials.PaddingString);
}
public static byte[] Encrypt(string data, string key, string iv, char paddingCharacter)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key.PadLeft(32, paddingCharacter).Substring(0, 32));
byte[] ivBytes = Encoding.UTF8.GetBytes(iv.PadLeft(32, paddingCharacter).Substring(0, 32));
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.BlockSize = 256;
rijndaelManaged.KeySize = 256;
MemoryStream memoryStream = new MemoryStream();
ICryptoTransform iCryptoTransform = rijndaelManaged.CreateEncryptor(keyBytes, ivBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, iCryptoTransform, CryptoStreamMode.Write);
StreamWriter streamWriter = new StreamWriter(cryptoStream);
streamWriter.Write(data);
streamWriter.Flush();
cryptoStream.FlushFinalBlock();
byte[] returnBytes = memoryStream.ToArray();
/// Disposal
streamWriter.Dispose();
cryptoStream.Dispose();
iCryptoTransform.Dispose();
memoryStream.Dispose();
rijndaelManaged.Clear();
///
return returnBytes;
}
public static string Decrypt(byte[] data)
{
return Decrypt(data, SecurityCredentials.KeyString, SecurityCredentials.IvString);
}
public static string Decrypt(byte[] data, string key, string iv)
{
return Decrypt(data, key, iv, SecurityCredentials.PaddingString);
}
public static string Decrypt(byte[] data, string key, string iv, char paddingCharacter)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key.PadLeft(32, paddingCharacter).Substring(0, 32));
byte[] ivBytes = Encoding.UTF8.GetBytes(iv.PadLeft(32, paddingCharacter).Substring(0, 32));
RijndaelManaged rijndaelManaged = new RijndaelManaged();
rijndaelManaged.BlockSize = 256;
rijndaelManaged.KeySize = 256;
MemoryStream memoryStream = new MemoryStream(data);
ICryptoTransform iCryptoTransform = rijndaelManaged.CreateDecryptor(keyBytes, ivBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, iCryptoTransform, CryptoStreamMode.Read);
StreamReader streamReader = new StreamReader(cryptoStream);
string returnString = streamReader.ReadLine();
/// Disposal
streamReader.Dispose();
cryptoStream.Dispose();
iCryptoTransform.Dispose();
memoryStream.Dispose();
rijndaelManaged.Clear();
///
return returnString;
}
}
}

Related

Why RijndaelManaged raises the following exception: Padding is invalid and cannot be removed?

In a .NET4/C# application, I have the following encryption methods:
public static byte[] Encrypt(byte[] data, byte[] key, out byte[] iv)
{
byte[] encryptedData;
using (var aes = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = KEY_SIZE,
BlockSize = BLOCK_SIZE
})
{
aes.GenerateIV();
var encryptor = aes.CreateEncryptor(key, aes.IV);
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
csEncrypt.Write(data, 0, data.Length);
csEncrypt.FlushFinalBlock();
}
encryptedData = msEncrypt.ToArray();
}
iv = new byte[aes.IV.Length];
aes.IV.CopyTo(iv, 0);
}
return encryptedData;
}
public static byte[] Encrypt(byte[] data, string sKey, out byte[] iv)
{
return Encrypt(data, Encoding.UTF8.GetBytes(sKey), out iv);
}
and the following decryption methods:
public static byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] iv)
{
byte[] data;
using (var aes = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = KEY_SIZE,
BlockSize = BLOCK_SIZE
})
{
var decryptor = aes.CreateDecryptor(key, iv);
using (var msData = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msData, decryptor, CryptoStreamMode.Read))
{
csEncrypt.Read(encryptedData, 0, encryptedData.Length);
}
data = msData.ToArray();
}
}
return data;
}
public static byte[] Decrypt(byte[] encryptedData, string sKey, byte[] iv)
{
return Decrypt(encryptedData, Encoding.UTF8.GetBytes(sKey), iv);
}
I wrote this unit test.
[TestMethod]
public void TestEncryptDecryptBytes()
{
Random rnd = new Random(666);
string key = "ABCDEFGHABCDEFGHABCDEFGHABCDEFGH";
//Run 100 times
for (int i = 0; i < 100; i++)
{
byte[] buf = new byte[rnd.Next(100, 1024)];
rnd.NextBytes(buf);
byte[] iv;
var enc = Crypto.Encrypt(buf, key, out iv);
var dec = Crypto.Decrypt(enc, key, iv);
Assert.AreEqual(buf.Length, dec.Length);
for (int j = 0; j < buf.Length; j++)
{
Assert.AreEqual(buf[j], dec[j]);
}
}
}
And I get the following exception while decrypting the encrypted data.
System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
Can't figure out what is wrong. I am pretty sure the key and the IV are the same during encryption and decryption. Block size and key size are also the same. Any help is appreciated.
You are decrypting the data incorrectly. Try this:
public static byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] iv)
{
byte[] data;
using (var aes = new RijndaelManaged()
{
Padding = PaddingMode.PKCS7,
Mode = CipherMode.CBC,
KeySize = KEY_SIZE,
BlockSize = BLOCK_SIZE
})
{
var decryptor = aes.CreateDecryptor(key, iv);
using (var encStream = new MemoryStream(encryptedData))
{
using (var csDecrypt = new CryptoStream(encStream, decryptor, CryptoStreamMode.Read))
{
using (var msData = new MemoryStream())
{
csDecrypt.CopyTo(msData);
data = msData.ToArray();
}
}
}
}
return data;
}

C# like Encrypting/decrypting secret in javascript

I have writted code in C# to securely store values in azure kv usign followjg code (in C#):
Example of what I had written before:
private readonly ILogger<AesCryptoProvider> _logger;
private const int Rfc2898KeygenIterations = 100;
private const int AesKeySizeInBits = 256;
private const int SaltSizeInBits = 32;
public byte[] Decrypt(string key, byte[] dataToDecrypt)
{
try
{
byte[] encryptedData = dataToDecrypt.Take(dataToDecrypt.Length - SaltSizeInBits).ToArray();
byte[] salt = dataToDecrypt.Skip(dataToDecrypt.Length - SaltSizeInBits).ToArray();
byte[] decryptedData;
using (Aes aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = AesKeySizeInBits;
int keyStrengthInBytes = aes.KeySize / 16;
var rfc2898 = new Rfc2898DeriveBytes(key, salt, Rfc2898KeygenIterations);
aes.Key = rfc2898.GetBytes(keyStrengthInBytes);
aes.IV = rfc2898.GetBytes(keyStrengthInBytes);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(encryptedData, 0, encryptedData.Length);
}
decryptedData = ms.ToArray();
}
}
return decryptedData;
}
catch (CryptographicException ex)
{
throw;
}
}
public byte[] Encrypt(string key, byte[] dataToEncrypt)
{
try
{
byte[] salt = new byte[SaltSizeInBits];
RandomNumberGenerator.Create().GetBytes(salt);
byte[] encryptedData;
using (Aes aes = new AesManaged())
{
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = AesKeySizeInBits;
int keyStrengthInBytes = aes.KeySize / 16;
var rfc2898 = new Rfc2898DeriveBytes(key, salt, Rfc2898KeygenIterations);
aes.Key = rfc2898.GetBytes(keyStrengthInBytes);
aes.IV = rfc2898.GetBytes(keyStrengthInBytes);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(dataToEncrypt, 0, dataToEncrypt.Length);
}
encryptedData = ms.ToArray();
long encryptedDataLength = encryptedData.Length;
Array.Resize(ref encryptedData, encryptedData.Length + SaltSizeInBits);
Array.Copy(salt, 0, encryptedData, encryptedDataLength, SaltSizeInBits);
}
}
return encryptedData;
}
catch (CryptographicException ex)
{
throw;
}
}
Now I need to have the same encrypt/decrypt methods in node.js
Unfortunately, I could not find api methods in node crypto module.
Could you please give me hint how to achive that or is it wrong?

PHP and C# AES256 encryption -> decryption

I want to encrypt a text in PHP and to decrypt in in C#, but i can't.
This is my PHP code:
define('AES_256_ECB', 'aes-256-ecb');
$encryption_key = "SomeSimpleTest";
$data = "Test123";
$encryptedData = openssl_encrypt($data, AES_256_ECB, $encryption_key, 0);
..and this is my C# code:
(AESEncryption.cs class)
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
namespace AESCrypto
{
class AESEncryption
{
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
// Set your salt here to meet your flavor:
byte[] saltBytes = passwordBytes;
// Example:
//saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 256;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.ECB;
//AES.Padding = PaddingMode.PKCS7;
using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
public static string Decrypt(string decryptedText, byte[] passwordBytes)
{
byte[] bytesToBeDecrypted = Convert.FromBase64String(decryptedText);
// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] decryptedBytes = AES_Decrypt(bytesToBeDecrypted, passwordBytes);
// Getting the size of salt
int saltSize = GetSaltSize(passwordBytes);
// Removing salt bytes, retrieving original bytes
byte[] originalBytes = new byte[decryptedBytes.Length - saltSize];
for (int i = saltSize; i < decryptedBytes.Length; i++)
{
originalBytes[i - saltSize] = decryptedBytes[i];
}
return Encoding.UTF8.GetString(originalBytes);
}
public static int GetSaltSize(byte[] passwordBytes)
{
var key = new Rfc2898DeriveBytes(passwordBytes, passwordBytes, 1000);
byte[] ba = key.GetBytes(2);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ba.Length; i++)
{
sb.Append(Convert.ToInt32(ba[i]).ToString());
}
int saltSize = 0;
string s = sb.ToString();
foreach (char c in s)
{
int intc = Convert.ToInt32(c.ToString());
saltSize = saltSize + intc;
}
return saltSize;
}
public static byte[] GetRandomBytes(int length)
{
byte[] ba = new byte[length];
RNGCryptoServiceProvider.Create().GetBytes(ba);
return ba;
}
}
}
Usage of it:
using AESCrypto;
...
public string DecryptText(string input, string password)
{
// Get the bytes of the string
byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesDecrypted = AESEncryption.AES_Decrypt(bytesToBeDecrypted, passwordBytes);
string result = Encoding.UTF8.GetString(bytesDecrypted);
return result;
}
private void btn1_Click(object sender, EventArgs e)
{
textBox1.Text = DecryptText("KEY_ENCRYPTED_WITH_PHP", "SomeSimpleTest");
}
I even tried with CBC but does not work...The mode of encryption is not important. I only want to make it work as it should.
Thanks.
php code:
define('AES_128_ECB', 'aes-128-ecb');
$encryption_key = "MY_16_CHAR_KEY:)";
$data = "MyOwnEncryptedSecretText";
$encryptedData = openssl_encrypt($data, AES_128_ECB, $encryption_key, 0);
C# code:
public String Decrypt(String text, String key)
{
//decode cipher text from base64
byte[] cipher = Convert.FromBase64String(text);
//get key bytes
byte[] btkey = Encoding.ASCII.GetBytes(key);
//init AES 128
RijndaelManaged aes128 = new RijndaelManaged();
aes128.Mode = CipherMode.ECB;
aes128.Padding = PaddingMode.PKCS7;
//decrypt
ICryptoTransform decryptor = aes128.CreateDecryptor(btkey, null);
MemoryStream ms = new MemoryStream(cipher);
CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
byte[] plain = new byte[cipher.Length];
int decryptcount = cs.Read(plain, 0, plain.Length);
ms.Close();
cs.Close();
//return plaintext in String
return Encoding.UTF8.GetString(plain, 0, decryptcount);
}
and usage of it:
string DecryptedText = Decrypt("GENERATED_KEY", "MY_16_CHAR_KEY:)");
Now it works great :)
Thanks.

Rijndael decryption returns weird ouput

I have used Rijndael Algorithm for Encryption and decryption.
The Decryption works fine when i do it with Encryption.
But when i try to do Decryption alone it returns something like this
J˿m"�e��c4�ħ�dB̵��Dq#W�.
Also i have used two buttons one is for encryption and another one is for decryption and called the methods when button clicks.
I cannot able to get any idea regarding why the output is returning like this. Even i used same convertion(UTF8 Encoding) for both methods.
Please help me to solve this problem.
Below is my code:
public partial class Form1 : Form
{
private RijndaelManaged myRijndael = new RijndaelManaged();
private int iterations;
private byte [] salt;
public Form1(string strPassword)
{
myRijndael.BlockSize = 128;
myRijndael.KeySize = 128;
myRijndael.IV = HexStringToByteArray("e84ad660c4721ae0e84ad660c4721ae0");
myRijndael.Padding = PaddingMode.PKCS7;
myRijndael.Mode = CipherMode.CBC;
iterations = 1000;
salt = System.Text.Encoding.UTF8.GetBytes("cryptography123example");
myRijndael.Key = GenerateKey(strPassword);
}
public string Encrypt(string strPlainText)
{
byte[] strText = new System.Text.UTF8Encoding().GetBytes(strPlainText);
MemoryStream ms = new MemoryStream();
ICryptoTransform transform = myRijndael.CreateEncryptor();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(strText, 0, strText.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
public string Decrypt(string encryptedText)
{
var encryptedBytes = Convert.FromBase64String(encryptedText);
MemoryStream ms = new MemoryStream();
ICryptoTransform transform = myRijndael.CreateDecryptor();
CryptoStream cs = new CryptoStream(ms, transform, CryptoStreamMode.Write);
cs.Write(encryptedBytes, 0, encryptedBytes.Length);
return System.Text.Encoding.UTF8.GetString(ms.ToArray());
}
public static byte[] HexStringToByteArray(string strHex)
{
dynamic r = new byte[strHex.Length / 2];
for (int i = 0; i <= strHex.Length - 1; i += 2)
{
r[i / 2] = Convert.ToByte(Convert.ToInt32(strHex.Substring(i, 2), 16));
}
return r;
}
private byte[] GenerateKey(string strPassword)
{
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(strPassword), salt, iterations);
return rfc2898.GetBytes(128 / 8);
}
private void button1_Click(object sender, EventArgs e)
{
EncryptOutput.Text = Encrypt(EncryptInput.Text);
}
private void button2_Click(object sender, EventArgs e)
{
DecryptOutput.Text = Decrypt(DecryptInput.Text);
}
}
Try this code:
public string Encrypt(string strPlainText) {
byte[] strText = System.Text.Encoding.UTF8.GetBytes(strPlainText);
using (ICryptoTransform encryptor = myRijndael.CreateEncryptor())
using (MemoryStream input = new MemoryStream(strText))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) {
input.CopyTo(cs);
cs.FlushFinalBlock();
return Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
}
}
public string Decrypt(string encryptedText) {
byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
using (ICryptoTransform decryptor = myRijndael.CreateDecryptor())
using (MemoryStream input = new MemoryStream(encryptedBytes))
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) {
cs.CopyTo(output);
return System.Text.Encoding.UTF8.GetString(output.GetBuffer(), 0, (int)output.Length);
}
}
public static byte[] HexStringToByteArray(string strHex) {
var r = new byte[strHex.Length / 2];
for (int i = 0; i < strHex.Length; i += 2) {
r[i / 2] = byte.Parse(strHex.Substring(i, 2), NumberStyles.HexNumber);
}
return r;
}
Please, remember using the using pattern... And dynamic should be used only in very special cases.
Note that the Encrypt is doable with one less Stream, in a very similar way to the one you wrote it:
public string Encrypt(string strPlainText) {
byte[] strText = System.Text.Encoding.UTF8.GetBytes(strPlainText);
using (ICryptoTransform encryptor = myRijndael.CreateEncryptor())
using (MemoryStream output = new MemoryStream())
using (CryptoStream cs = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) {
cs.Write(strText, 0, strText.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(output.GetBuffer(), 0, (int)output.Length);
}
}
but the Decrypt needs two Stream, because the CryptoStream needs a Stream as a parameter, containing the encrypted data, and it is easier to write its output (of which you don't know the exact lenth, thanks to padding) to another stream.
cs.FlushFinalBlock(); forgotten in Decrypt()? I just round-tripped a test string with your code once I fixed that

How to encrypt/decrypt an XML file?

I am trying to encrypt/decrypt an XML file. I found this sample for encrypting but I do not know how to decrypt? Any idea? Thanks!
// Load this XML file
System.Xml.XmlDocument myDoc = new System.Xml.XmlDocument();
myDoc.Load(#"c:\persons.xml");
// Get a specified element to be encrypted
System.Xml.XmlElement element = myDoc.GetElementsByTagName("Persons")[0] as System.Xml.XmlElement;
// Create a new TripleDES key.
System.Security.Cryptography.TripleDESCryptoServiceProvider tDESkey = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
// Form a Encrypted XML with the Key
System.Security.Cryptography.Xml.EncryptedXml encr = new System.Security.Cryptography.Xml.EncryptedXml();
encr.AddKeyNameMapping("Deskey", tDESkey);
// Encrypt the element data
System.Security.Cryptography.Xml.EncryptedData ed = encr.Encrypt(element, "Deskey");
// Replace the existing data with the encrypted data
System.Security.Cryptography.Xml.EncryptedXml.ReplaceElement(element, ed, false);
// saves the xml file with encrypted data
myDoc.Save(#"c:\encryptedpersons.xml");
But I do not know how I would decrypt that? Any ideas? Thanks!
Something like this:
public static class Encryption
{
private const string InitVector = "T=A4rAzu94ez-dra";
private const int KeySize = 256;
private const int PasswordIterations = 1000; //2;
private const string SaltValue = "d=?ustAF=UstenAr3B#pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE#ras!a+uc#";
public static string Decrypt(string encryptedText, string passPhrase)
{
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
string plainText;
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize / 8);
RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };
try
{
using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
//TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
byte[] plainTextBytes = new byte[encryptedTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
catch (CryptographicException)
{
plainText = string.Empty; // Assume the error is caused by an invalid password
}
return plainText;
}
public static string Encrypt(string plainText, string passPhrase)
{
string encryptedText;
byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
byte[] keyBytes = password.GetBytes(KeySize / 8);
RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};
using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(keyBytes, initVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
encryptedText = Convert.ToBase64String(cipherTextBytes);
}
}
}
return encryptedText;
}
}
Edit:
Sani Huttunen pointed out that my static implementation above has a severe performance issue if you will be encrypting multiple pieces of data using the same password. You can read more about it here: http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/
Edit: A non-static implementation that is much more efficient if you need to perform multiple encryptions/decryptions using the same password (~32ms original ~1ms new).
public class SimpleEncryption
{
#region Constructor
public SimpleEncryption(string password)
{
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);
_DeriveBytes = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
_InitVectorBytes = Encoding.UTF8.GetBytes(InitVector);
_KeyBytes = _DeriveBytes.GetBytes(32);
}
#endregion
#region Private Fields
private readonly Rfc2898DeriveBytes _DeriveBytes;
private readonly byte[] _InitVectorBytes;
private readonly byte[] _KeyBytes;
#endregion
private const string InitVector = "T=A4rAzu94ez-dra";
private const int PasswordIterations = 1000; //2;
private const string SaltValue = "d=?ustAF=UstenAr3B#pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE#ras!a+uc#";
public string Decrypt(string encryptedText)
{
byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
string plainText;
RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };
try
{
using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(_KeyBytes, _InitVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
{
//TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
byte[] plainTextBytes = new byte[encryptedTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
}
}
}
}
catch (CryptographicException exception)
{
plainText = string.Empty; // Assume the error is caused by an invalid password
}
return plainText;
}
public string Encrypt(string plainText)
{
string encryptedText;
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};
using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(_KeyBytes, _InitVectorBytes))
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
encryptedText = Convert.ToBase64String(cipherTextBytes);
}
}
}
return encryptedText;
}
}
There's a complete example on MSDN, although is uses RSA and not TripleDES.

Categories