using System; using System.IO; using System.Security.Cryptography; namespace ZeroLevel.Services.Encryption { public class RijndaelEncryptor : IDisposable { protected const int DEFAULT_STREAM_BUFFER_SIZE = 16384; private static readonly byte[] SALT = new byte[] { 0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c }; #region Crypt fields private Rijndael _rijndael; private CryptoStream _stream; #endregion public RijndaelEncryptor(Stream stream, string password, byte[] salt = null) { _rijndael = Rijndael.Create(); using (var pdb = new Rfc2898DeriveBytes(password, SALT)) { _rijndael.Key = pdb.GetBytes(32); _rijndael.IV = pdb.GetBytes(16); } _stream = new CryptoStream(stream, _rijndael.CreateEncryptor(), CryptoStreamMode.Write); } public void Write(byte[] data) { _stream.Write(data, 0, data.Length); } #region OneTime Read/Write protected static void Transfer(Stream input, Stream output) { if (input.CanRead == false) { throw new InvalidOperationException("Input stream can not be read."); } if (output.CanWrite == false) { throw new InvalidOperationException("Output stream can not be write."); } var readed = 0; var buffer = new byte[DEFAULT_STREAM_BUFFER_SIZE]; while ((readed = input.Read(buffer, 0, buffer.Length)) != 0) { output.Write(buffer, 0, readed); } output.Flush(); } public static byte[] Encrypt(byte[] plain, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(plain, 0, plain.Length); cryptoStream.Close(); return memoryStream.ToArray(); } } } } } public static byte[] Encrypt(Stream stream, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write)) { Transfer(stream, cryptoStream); cryptoStream.Close(); return memoryStream.ToArray(); } } } } } public static void Encrypt(Stream inputStream, Stream outputStream, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var cryptoStream = new CryptoStream(outputStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write)) { Transfer(inputStream, cryptoStream); cryptoStream.Close(); } } } } public static byte[] Decrypt(byte[] cipher, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(cipher, 0, cipher.Length); cryptoStream.Close(); return memoryStream.ToArray(); } } } } } public static byte[] Decrypt(Stream stream, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write)) { Transfer(stream, cryptoStream); cryptoStream.Close(); return memoryStream.ToArray(); } } } } } public static void Decrypt(Stream inputStream, Stream outputStream, string password, byte[] salt = null) { using (var rijndael = Rijndael.Create()) { using (var pdb = new Rfc2898DeriveBytes(password, salt ?? SALT)) { rijndael.Key = pdb.GetBytes(32); rijndael.IV = pdb.GetBytes(16); using (var cryptoStream = new CryptoStream(outputStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write)) { Transfer(inputStream, cryptoStream); cryptoStream.Close(); } } } } #endregion public void Dispose() { try { _stream.Flush(); _stream.Close(); _stream.Dispose(); } catch { } _rijndael.Clear(); _rijndael.Dispose(); } } }