public static byte[] SymmetricDecrypt( byte[] input, byte[] key )
{
Debug.Assert( key.Length == 32 );
using ( var aes = new RijndaelManaged() )
{
aes.BlockSize = 128;
aes.KeySize = 256;
// first 16 bytes of input is the ECB encrypted IV
byte[] cryptedIv = new byte[ 16 ];
byte[] iv = new byte[ cryptedIv.Length ];
Array.Copy( input, 0, cryptedIv, 0, cryptedIv.Length );
// the rest is ciphertext
byte[] cipherText = new byte[ input.Length - cryptedIv.Length ];
Array.Copy( input, cryptedIv.Length, cipherText, 0, cipherText.Length );
// decrypt the IV using ECB
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
using ( var aesTransform = aes.CreateDecryptor( key, null ) )
{
iv = aesTransform.TransformFinalBlock( cryptedIv, 0, cryptedIv.Length );
}
// decrypt the remaining ciphertext in cbc with the decrypted IV
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using ( var aesTransform = aes.CreateDecryptor( key, iv ) )
using ( var ms = new MemoryStream( cipherText ) )
using ( var cs = new CryptoStream( ms, aesTransform, CryptoStreamMode.Read ) )
{
// plaintext is never longer than ciphertext
byte[] plaintext = new byte[ cipherText.Length ];
int len = cs.Read( plaintext, 0, plaintext.Length );
byte[] output = new byte[ len ];
Array.Copy( plaintext, 0, output, 0, len );
return output;
}
}
}