/// <summary> /// Creates a symmetric Rijndael encryptor. /// </summary> /// <param name="password">The password to encrypt the plaintext with.</param> /// <param name="iv">The initialization vector. Must be 128-bits.</param> /// <param name="keySize">The cipher key size. 256-bit is stronger, but slower.</param> /// <returns>The symmetric encryptor.</returns> public static ICryptoTransform CreateEncryptor(string password, byte[] iv, KeySize keySize) { #if NET47 || NET48 var rijndael = new RijndaelManaged { Mode = BlockCipherMode }; #else var rijndael = Aes.Create(); rijndael.Mode = BlockCipherMode; #endif return(rijndael.CreateEncryptor(GenerateKey(password, keySize), iv)); }
/// <summary> /// Initialize a new instance of the <see cref="KeyProvider"/> class /// using string password and key size. /// </summary> /// <param name="password">string password to build other binary keys based on it</param> /// <param name="keySize"></param> public KeyProvider(string password, KeySize keySize, KeySize ivSize = Cryptography.KeySize._128) { if (string.IsNullOrEmpty(password)) throw new ArgumentNullException("Password is null or empty", nameof(password)); Password = password; //set for public view KeySize = (int)keySize; //set for public view KeyBuilder = new Rfc2898DeriveBytes(password, new byte[SaltSize], Iterations); KeyBuilder.Salt = KeyBuilder.GetBytes(SaltSize); IV = KeyBuilder.GetBytes((int)ivSize / 8); Key = KeyBuilder.GetBytes(ByteKeySize); }
private byte[,] State; // State matrix public Aes(KeySize keySize, byte[] keyBytes) { SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes keyBytes.CopyTo(this.key, 0); BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w } // Aes constructor
private byte[,] w; // key schedule array. #endregion Fields #region Constructors public Aes(KeySize keySize, byte[] keyBytes) { SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes // keyBytes.CopyTo(this.key, 0); key = keyBytes; BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w }
/// <summary> /// Generates a RSA-Key Pair - 1: Private Key, 2: Public Key /// </summary> /// <returns>1: Private Key, 2: Public Key</returns> private Tuple <string, string> CreateKeyPair(KeySize size) { CspParameters cspParams = new CspParameters { ProviderType = 1 }; RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(Convert.ToInt32(size), cspParams); string publicKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(false)); string privateKey = Convert.ToBase64String(rsaProvider.ExportCspBlob(true)); return(new Tuple <string, string>(privateKey, publicKey)); }
public Cryptographer(string password, KeySize keySize = KeySize._256, byte saltSize = 7) { if (saltSize == 0) { throw new ArgumentException("0 salt length is forbidden", nameof(saltSize)); } rng = RandomNumberGenerator.Create(); SaltSize = saltSize; KeyProvider = new KeyProvider(password, keySize, KeySize._128); }
internal void init(Mode aes_mode, KeySize aes_key_size, byte[] key) { _mode = aes_mode; switch (aes_key_size) { case KeySize.Aes128: _key_size = 16; break; case KeySize.Aes192: _key_size = 24; break; case KeySize.Aes256: _key_size = 32; break; default: _key_size = 0; break; } _counter.Zeroize(); _counter_out.Zeroize(); _keystream_pointer = 0xFFFF; // initialize WinCrypt AES-128 key. ms_aes_key key_blob = new ms_aes_key(); key_blob.header.bType = BlobType.PlainText; key_blob.header.bVersion = CurrentBlobVersion; key_blob.header.reserved = 0; key_blob.header.aiKeyAlg = (uint)aes_key_size; key_blob.size = _key_size; Buffer.BlockCopy(key, 0, key_blob.key, 0, (int)key_blob.size); int nativeKeySize; IntPtr nativeKey = key_blob.Serialize(out nativeKeySize); try { bool result = Crypt32.CryptImportKey(_provider.Handle, nativeKey, nativeKeySize, IntPtr.Zero, 0, out _key); } finally { Marshal.FreeCoTaskMem(nativeKey); } _mode = aes_mode; // WinCrypt cannot do CTR mode, we have to do it manually. IntPtr buffer = Marshal.AllocCoTaskMem(sizeof(int)); try { int mode = (int)((aes_mode == Mode.Ctr) ? Mode.Ecb : aes_mode); Marshal.WriteInt32(buffer, mode); bool result = Crypt32.CryptSetKeyParam(_key, 4 /* KP_MODE*/, buffer, 0); } finally { Marshal.FreeCoTaskMem(buffer); } }
private void Init(BlockSize blockSize, KeySize keySize) { if (blockSize == BlockSize.B128) { Nb = 2; if (keySize == KeySize.K128) { Nk = 2; Nr = 10; } else if (keySize == KeySize.K256) { Nk = 4; Nr = 14; } else { throw new ArgumentNullException("Key size not supported"); } } else if (blockSize == BlockSize.B256) { Nb = 4; if (keySize == KeySize.K256) { Nk = 4; Nr = 14; } else if (keySize == KeySize.K512) { Nk = 8; Nr = 18; } else { throw new ArgumentNullException("Key size not supported"); } } else { Nb = 8; if (keySize == KeySize.K512) { Nk = 8; Nr = 18; } else { throw new ArgumentNullException("Key size not supported"); } } }
public static string Decrypt(string encryptedText, string passKey, KeySize keySize = KeySize._256) { RijndaelManaged aesEncryption = new RijndaelManaged(); aesEncryption.KeySize = (int)keySize; aesEncryption.BlockSize = 128; aesEncryption.Mode = CipherMode.ECB; aesEncryption.Padding = PaddingMode.ISO10126; byte[] KeyInBytes = Encoding.UTF8.GetBytes(_GenerateAPassKey(passKey)); aesEncryption.Key = KeyInBytes; ICryptoTransform decrypto = aesEncryption.CreateDecryptor(); byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length); return ASCIIEncoding.UTF8.GetString(decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length)); }
/// <summary> /// Decrypts ciphertext using the Rijndael cipher in CBC mode with a password derived HMAC SHA-512 salt. /// </summary> /// <param name="ciphertext">The ciphertext to decrypt.</param> /// <param name="password">The password to decrypt the ciphertext with.</param> /// <param name="keySize">The size of the cipher key used to create the ciphertext.</param> /// <returns>The plaintext.</returns> public static string Decrypt(byte[] ciphertext, string password, KeySize keySize) { using (var ms = new MemoryStream(ciphertext)) { // Extract the IV from the ciphertext var iv = new byte[InitializationVectorSize]; ms.Read(iv, 0, iv.Length); // Create a CryptoStream to decrypt the ciphertext using (var cs = new CryptoStream(ms, CreateDecryptor(password, iv, keySize), CryptoStreamMode.Read)) { // Decrypt the ciphertext using (var sr = new StreamReader(cs, Encoding.UTF8)) return sr.ReadToEnd(); } } }
internal static int ConvertToInt(this KeySize keysize) { switch (keysize) { case KeySize._128: return(128); case KeySize._192: return(192); case KeySize._256: return(256); } throw new ArgumentException("Unknown KeySize"); }
internal static int NumRounds(this KeySize keysize) { switch (keysize) { case KeySize._128: return(10); case KeySize._192: return(12); case KeySize._256: return(14); } throw new ArgumentException("Unknown KeySize"); }
public SyrisAES(KeySize keySize) { SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes AESKey.CopyTo(this.key, 0); BuildSbox(); BuildInvSbox(); InitdBox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w }
/// <summary> /// Decrypt a byte array into a byte array using a Key and an IV /// </summary> public static byte[] Decrypt(byte[] cipherData, byte[] key, byte[] iv, KeySize keySize, BlockSize blockSize) { if (cipherData == null) { throw new ArgumentNullException(nameof(cipherData)); } if (key == null || key.Length <= 0) { throw new ArgumentNullException(nameof(key)); } if (iv == null || iv.Length <= 0) { throw new ArgumentNullException(nameof(iv)); } if (cipherData.Length < 1) { throw new ArgumentException("cipherData"); } // Create a MemoryStream that is going to accept the decrypted bytes using (var memoryStream = new MemoryStream()) { // Create a symmetric algorithm. // We are going to use Rijndael because it is strong and available on all platforms. // You can use other algorithms, to do so substitute the next line with something like // TripleDES alg = TripleDES.Create(); using (var alg = GetRijndaelManaged(key, iv, keySize, blockSize)) { // Create a CryptoStream through which we are going to be pumping our data. // CryptoStreamMode.Write means that we are going to be writing data to the stream // and the output will be written in the MemoryStream we have provided. using (var cs = new CryptoStream(memoryStream, alg.CreateDecryptor(), CryptoStreamMode.Write)) { // Write the data and make it do the decryption cs.Write(cipherData, 0, cipherData.Length); // Close the crypto stream (or do FlushFinalBlock). // This will tell it that we have done our decryption and there is no more data coming in, // and it is now a good time to remove the padding and finalize the decryption process. cs.FlushFinalBlock(); cs.Close(); } } // Now get the decrypted data from the MemoryStream. // Some people make a mistake of using GetBuffer() here, which is not the right way. var decryptedData = memoryStream.ToArray(); return(decryptedData); } }
/// <summary> /// AES解密函数 /// </summary> /// <param name="text">被加密的字符串</param> /// <param name="key">密钥</param> /// <param name="keysize">密钥长度</param> /// <returns>解密后的字符串</returns> public string DecryptString(string text, string key, KeySize keysize = KeySize.B128) { switch (keysize) { case KeySize.B192: return(DecryptString(text, key, 192)); case KeySize.B256: return(DecryptString(text, key, 256)); default: return(DecryptString(text, key, 128)); } }
public Aes(KeySize keySize, byte[] keyBytes, BlockSize blockSize) { BuildNaNkNr(); SetNbNkNr(keySize, blockSize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); }
public ECC(KeySize keySize, byte[] signingKey) { /* ECC : 2 Key Len for Public + 1 Key Len for Private */ int expectedLength = ((int)keySize * 3); if (signingKey.Length != (int)expectedLength) { throw new Exception("Invalid Private Key"); } this.keySize = keySize; this.signingKeyData.AddRange(NIST_PRIVATE_KEY_PREFIX); this.signingKeyData.AddRange(signingKey); }
public static string Encrypt(string plainStr, string passKey, KeySize keySize = KeySize._256) { RijndaelManaged aesEncryption = new RijndaelManaged(); aesEncryption.KeySize = (int)keySize; aesEncryption.BlockSize = 128; aesEncryption.Mode = CipherMode.ECB; aesEncryption.Padding = PaddingMode.ISO10126; byte[] KeyInBytes = Encoding.UTF8.GetBytes(_GenerateAPassKey(passKey)); aesEncryption.Key = KeyInBytes; byte[] plainText = ASCIIEncoding.UTF8.GetBytes(plainStr); ICryptoTransform crypto = aesEncryption.CreateEncryptor(); byte[] cipherText = crypto.TransformFinalBlock(plainText, 0, plainText.Length); return Convert.ToBase64String(cipherText); }
} // Aes constructor private void Init(KeySize keySize, byte[] keyBytes) { int i = 0; int keyLen = 0, kbLen = 0; byte nextByte = 1; try { SetNbNkNr(keySize); // set the key this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes // if the password is the right size, just copy the array if (this.key.Length == keyBytes.Length) { keyBytes.CopyTo(this.key, 0); } else // password is different size, so manually copy { // get the key lengths keyLen = this.key.Length; kbLen = keyBytes.Length; // manuually add the password for (i = 0; i < keyLen; i++) { // make sure we can use the keyBytes if (i < kbLen) { this.key[i] = keyBytes[i]; } else // we need to add some extra bytes { this.key[i] = nextByte++; } } } // build the two matrixes BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w } catch (Exception e) { AES_ShowError(e, "Init"); } }
} // set key size public Aes(KeySize keySize, byte[] keyBytes) { // AES constructor SetKeySizeNumRounds(keySize); this.key = new byte[this.keySize * 4]; // 16, 24, 32 bytes keyBytes.CopyTo(this.key, 0); BuildSbox(); // load sboxes into memory BuildInvSbox(); BuildRcon(); // calculate round constants KeyExpansion(); // expand the given key into a key schedule } // AES constructor
public void CreateKey(KeySize keySize = KeySize.KS2048) { AsymmetricKeyAlgorithmProvider asym = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); CryptographicKey key = asym.CreateKeyPair((uint)keySize); var privateKey = key.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey); var publicKey = key.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey); //System.Diagnostics.Debug.WriteLine($"private : {BitConverter.ToString(privateKey.ToArray())}"); //System.Diagnostics.Debug.WriteLine($"public : {BitConverter.ToString(publicKey.ToArray())}"); PublicKey = new PublicKey(publicKey); PrivateKey = new PrivateKey(privateKey); }
//密钥生成 public int GenKey(KeySize size) { int keySize = 0; switch (size) { case KeySize.size_128: keySize = 128; symmetry = cryTool.Cry_KeySize.Key_128; break; case KeySize.size_192: keySize = 192; symmetry = cryTool.Cry_KeySize.Key_192; break; case KeySize.size_256: keySize = 256; symmetry = cryTool.Cry_KeySize.Key_256; break; default: keySize = 128; symmetry = cryTool.Cry_KeySize.Key_128; break; } k1 = new byte[keySize / 8]; //生成k1密钥 using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()) { rng.GetBytes(k1); } //生成K2密钥 cryTool tool = new cryTool(symmetry); k2 = tool.GenerateKey(); k3 = tool.GenerateIV(); //初始化 history = new List <string>(); rw = new Dictionary <string, List <string> >(); rf = new Dictionary <string, List <string> >(); return(0); }
public AES(KeySize keySize) { SetNbNkNr(keySize); key = new byte[Nk * 4]; // 16, 24, 32 bytes // keyBytes.CopyTo(this.key, 0); key = new byte[] {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; ; BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); } // Aes constructor
/// <summary> /// Устанавливает первичные настройки для блоков текста и ключа /// </summary> /// <param name="blockSize"></param> /// <param name="keySize"></param> /// <param name="key"></param> public void SetSettings(BlockSize blockSize, KeySize keySize, byte[] key) { var keyLengthInBytes = RijndaelSizesConverter.KeySizeToInt(keySize) / 8; if (key.Length != keyLengthInBytes) { throw new Exception("Неверная длина ключа"); } _blockSize = blockSize; _keySize = keySize; _key = key; GenerateKeyExpansion(); }
public RSAProvider(KeySize size) { keySize = size; number1 = InitializeRandom(); number2 = InitializeRandom(); composition = number1 * number2; eulerFunc = (number1 - 1) * (number2 - 1); publicExhibitor = GetPublicExhibitor(); privateExhibitor = GetPrivateExhibitor(); PublicKey = new RSAKey(publicExhibitor, composition); PrivateKey = new RSAKey(privateExhibitor, composition); //SessionKey = InitializeRandom(); }
} // Aes constructor public AesHelper(KeySize keySize, string s) { byte[] keyBytes = Encoding.UTF8.GetBytes(s); SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes keyBytes.CopyTo(this.key, 0); BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w } // Aes constructor
internal static List <BitArray> ExpandKey(BitArray key, KeySize keySize) { int rounds = keySize.NumRounds(); int length = keySize.ConvertToInt(); var keys = new BitArray(rounds * length); var prev = key; for (int i = 0; i < rounds; i++) { var next = prev.Next(i + 1); next.CopyTo(keys, length * i); } return(keys.SeparateBlocks()); }
private byte[] Encrypt(byte[] toEncrypt, byte[] pwd, KeySize keySize, BlockSize blockSize) { using (MemoryStream ms = new MemoryStream()) { using (RijndaelManaged rm = new RijndaelManaged()) { rm.KeySize = (int)keySize; rm.BlockSize = (int)blockSize; var key = new Rfc2898DeriveBytes(pwd, GetRandomBytes(), 1000); rm.Key = key.GetBytes(rm.KeySize / 8); rm.IV = key.GetBytes(rm.BlockSize / 8); } } throw new NotImplementedException(); }
public void InitCipher(byte[] keyBytes) { KeySize keySize = KeySize.Bits256; switch (keyBytes.Length) { case 16: keySize = KeySize.Bits128; break; case 24: keySize = KeySize.Bits192; break; } SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes keyBytes.CopyTo(this.key, 0); KeyExpansion(); // expand the seed key into a key schedule and store in w }
private void method_3(KeySize A_0) { this.int_0 = 4; if (A_0 == KeySize.Bits128) { this.int_1 = 4; this.int_2 = 10; } else if (A_0 == KeySize.Bits192) { this.int_1 = 6; this.int_2 = 12; } else if (A_0 == KeySize.Bits256) { this.int_1 = 8; this.int_2 = 14; } }
public static string EncryptToBase64(this string clearText, string password, KeySize keySize = KeySize.Normal_128) { using (var memory = new MemoryStream()) { Encrypt( password, memory, cryptoStream => { using (var swEncrypt = new StreamWriter(cryptoStream)) { swEncrypt.Write(clearText); } }, keySize); var result = Convert.ToBase64String(memory.ToArray()); return(result); } }
/// <summary> /// </summary> /// <param name="keySize"></param> private void SetNbNkNr(KeySize keySize) { this.Nb = 4; if (keySize == KeySize.Bits128) { this.Nk = 4; this.Nr = 10; } else if (keySize == KeySize.Bits192) { this.Nk = 6; this.Nr = 12; } else if (keySize == KeySize.Bits256) { this.Nk = 8; this.Nr = 14; } }
public static int KeySizeToInt(KeySize keySize) { { switch (keySize) { case KeySize.Size128: return(128); case KeySize.Size192: return(192); case KeySize.Size256: return(256); default: throw new ArgumentOutOfRangeException(nameof(keySize), keySize, null); } } }
public void InitCipher(byte[] keyBytes) { KeySize keySize = KeySize.Bits256; switch (keyBytes.Length) { case 0x10: keySize = KeySize.Bits128; break; case 0x18: keySize = KeySize.Bits192; break; } this.SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; keyBytes.CopyTo(this.key, 0); this.KeyExpansion(); }
private static string _GenerateAPassKey(string passKey, KeySize keySize = KeySize._256) { // Pass Phrase can be any string string passPhrase = passKey; // Salt Value can be any string(for simplicity use the same value as used for the pass phrase) string saltValue = passKey; // Hash Algorithm can be "SHA1 or MD5" string hashAlgorithm = "SHA1"; // Password Iterations can be any number int passwordIterations = 2; // Convert Salt passphrase string to a Byte Array byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue); // Using System.Security.Cryptography.PasswordDeriveBytes to create the Key PasswordDeriveBytes pdb = new PasswordDeriveBytes(passPhrase, saltValueBytes, hashAlgorithm, passwordIterations); //When creating a Key Byte array from the base64 string the Key must have 32 dimensions. byte[] Key = pdb.GetBytes(((int)keySize) / 11); String KeyString = Convert.ToBase64String(Key); return KeyString; }
/// <summary> /// </summary> /// <param name="keySize"></param> /// <param name="keyBytes"></param> public CryptoEngineAES(KeySize keySize, byte[] keyBytes) { this.SetNbNkNr(keySize); this.key = new byte[this.Nk * 4]; keyBytes.CopyTo(this.key, 0); this.Sbox = new byte[,] { { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 1, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 }, { 0xca, 130, 0xc9, 0x7d, 250, 0x59, 0x47, 240, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 }, { 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 }, { 4, 0xc7, 0x23, 0xc3, 0x18, 150, 5, 0x9a, 7, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 }, { 9, 0x83, 0x2c, 0x1a, 0x1b, 110, 90, 160, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 }, { 0x53, 0xd1, 0, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 190, 0x39, 0x4a, 0x4c, 0x58, 0xcf }, { 0xd0, 0xef, 170, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 2, 0x7f, 80, 60, 0x9f, 0xa8 }, { 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 210 }, { 0xcd, 12, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 100, 0x5d, 0x19, 0x73 }, { 0x60, 0x81, 0x4f, 220, 0x22, 0x2a, 0x90, 0x88, 70, 0xee, 0xb8, 20, 0xde, 0x5e, 11, 0xdb }, { 0xe0, 50, 0x3a, 10, 0x49, 6, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 }, { 0xe7, 200, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 8 }, { 0xba, 120, 0x25, 0x2e, 0x1c, 0xa6, 180, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a }, { 0x70, 0x3e, 0xb5, 0x66, 0x48, 3, 0xf6, 14, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e }, { 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 30, 0x87, 0xe9, 0xce, 0x55, 40, 0xdf }, { 140, 0xa1, 0x89, 13, 0xbf, 230, 0x42, 0x68, 0x41, 0x99, 0x2d, 15, 0xb0, 0x54, 0xbb, 0x16 } }; this.iSbox = new byte[,] { { 0x52, 9, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb }, { 0x7c, 0xe3, 0x39, 130, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb }, { 0x54, 0x7b, 0x94, 50, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 11, 0x42, 250, 0xc3, 0x4e }, { 8, 0x2e, 0xa1, 0x66, 40, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 }, { 0x72, 0xf8, 0xf6, 100, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 }, { 0x6c, 0x70, 0x48, 80, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 70, 0x57, 0xa7, 0x8d, 0x9d, 0x84 }, { 0x90, 0xd8, 0xab, 0, 140, 0xbc, 0xd3, 10, 0xf7, 0xe4, 0x58, 5, 0xb8, 0xb3, 0x45, 6 }, { 0xd0, 0x2c, 30, 0x8f, 0xca, 0x3f, 15, 2, 0xc1, 0xaf, 0xbd, 3, 1, 0x13, 0x8a, 0x6b }, { 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 220, 0xea, 0x97, 0xf2, 0xcf, 0xce, 240, 180, 230, 0x73 }, { 150, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 110 }, { 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 14, 170, 0x18, 190, 0x1b }, { 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 210, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 120, 0xcd, 90, 0xf4 }, { 0x1f, 0xdd, 0xa8, 0x33, 0x88, 7, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f }, { 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 13, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef }, { 160, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 200, 0xeb, 0xbb, 60, 0x83, 0x53, 0x99, 0x61 }, { 0x17, 0x2b, 4, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 20, 0x63, 0x55, 0x21, 12, 0x7d } }; this.Rcon = new byte[,] { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, { 2, 0, 0, 0 }, { 4, 0, 0, 0 }, { 8, 0, 0, 0 }, { 0x10, 0, 0, 0 }, { 0x20, 0, 0, 0 }, { 0x40, 0, 0, 0 }, { 0x80, 0, 0, 0 }, { 0x1b, 0, 0, 0 }, { 0x36, 0, 0, 0 } }; this.KeyExpansion(); }
/// <summary>This version of EncryptData takes the message, password /// and IV as strings and encrypts the message, returning the encrypted text as a string. /// </summary> /// <param name="message">The plain text message</param> /// <param name="password">The password/key to encrypt the message with</param> /// <param name="initialisationVector">The IV as a string</param> /// <param name="blockSize">The block size used to encrypt the message</param> /// <param name="keySize">The key size used to encrypt the message</param> /// <param name="cryptMode">The encryption mode, CBC or ECB, used to encrypt the message</param> /// <param name="returnAsHex">Whether the encrypted message is to be returned as Hex</param> public static string EncryptData(string message, string password, string initialisationVector, BlockSize blockSize, KeySize keySize, EncryptionMode cryptMode, bool returnAsHex) { byte[] messageData, passwordData, vectorData; // If message is empty dont bother doing any work if (message.Length <= 0) return ""; //System.Text.UnicodeEncoding encoderUnicode = new System.Text.UnicodeEncoding(); //MTreat // Convert message, key and IV to byte arrays //messageData = encoderUnicode.GetBytes(message); //MTreat //passwordData = encoderUnicode.GetBytes(password); //MTreat //vectorData = encoderUnicode.GetBytes(initialisationVector); //MTreat System.Text.ASCIIEncoding encoderASCII = new System.Text.ASCIIEncoding(); //MTreat // Convert message, key and IV to byte arrays messageData = encoderASCII.GetBytes(message); //MTreat passwordData = encoderASCII.GetBytes(password); //MTreat vectorData = encoderASCII.GetBytes(initialisationVector); //MTreat // Return encrypted message as string (hex version of bytes if required) if (returnAsHex) return BytesToHex(EncryptData(messageData, passwordData, vectorData, blockSize, keySize, cryptMode)); else //return encoderUnicode.GetString(EncryptData(messageData, passwordData, //MTreat // vectorData, blockSize, keySize, cryptMode)); //MTreat return encoderASCII.GetString(EncryptData(messageData, passwordData, //MTreat vectorData, blockSize, keySize, cryptMode)); //MTreat }
/// <summary> /// Initializes the AES engine /// </summary> /// <param name="keySize">Size of the key</param> /// <param name="keyBytes">the password, in a byte array</param> public AES(KeySize keySize, byte[] keyBytes) { Init(keySize, keyBytes); }
/// <summary>This version of DecryptData takes the encrypted message, password /// and IV as byte arrays and decrypts the message, returning the plain text as /// a byte array. /// </summary> /// <param name="message">The encrypted message</param> /// <param name="password">The password/key that was used to encrypt the message</param> /// <param name="initialisationVector">The IV</param> /// <param name="blockSize">The block size used in encrypting the message</param> /// <param name="keySize">The key size used in encrypting the message</param> /// <param name="cryptMode">The encryption mode, CBC or ECB, used in encrypting the message</param> public static byte[] DecryptData(byte[] message, byte[] password, byte[] initialisationVector, BlockSize blockSize, KeySize keySize, EncryptionMode cryptMode) { byte[] messageData, keyBlock, vectorBlock, dataBlock; int messageLength, encodedLength, nb, nk; // Dont do any work if message is empty encodedLength = message.Length; if (encodedLength <= 0) return message; // Set up arrays based on block size switch (blockSize) { case BlockSize.Block128: nb = 4; break; case BlockSize.Block192: nb = 6; break; default: // assume 256 nb = 8; break; } vectorBlock = new byte[nb * 4]; dataBlock = new byte[nb * 4]; for (int i = 0; i < (nb * 4); i++) { vectorBlock[i] = 0; dataBlock[i] = 0; } // Set up array based on key size switch (keySize) { case KeySize.Key128: nk = 4; break; case KeySize.Key192: nk = 6; break; default: // assume 256 nk = 8; break; } keyBlock = new byte[nk * 4]; for (int i = 0; i < (nk * 4); i++) { keyBlock[i] = 0; } // Key will be zero padded, or trimmed to correct size for (int i = 0; (i < password.Length) && (i < (nk * 4)); i++) keyBlock[i] = password[i]; // Vector will be zero padded, or trimmed to correct size for (int i = 0; (i < initialisationVector.Length) && (i < (nb * 4)); i++) vectorBlock[i] = initialisationVector[i]; // Prepare the key and tables using the Rijndael fuinctions gentables(); gkey(nb, nk, keyBlock); // Decrypt a block at a time for (int i = 0; i < encodedLength; i += (nb * 4)) { Array.Copy(message, i, dataBlock, 0, (nb * 4)); decrypt(dataBlock); // If CBC mode we need to do some extra XORing if (cryptMode == EncryptionMode.ModeCBC) { for (int j = 0; j < (nb * 4); j++) dataBlock[j] ^= vectorBlock[j]; Array.Copy(message, i, vectorBlock, 0, (nb * 4)); } Array.Copy(dataBlock, 0, message, i, (nb * 4)); } // Message length was originally put on front of message, so retrieve it messageLength = (int)message[0] | (((int)message[1]) << 8) | (((int)message[2]) << 16) | (((int)message[3]) << 24); // Get the original message from the clear text messageData = new byte[messageLength]; Array.Copy(message, 4, messageData, 0, messageLength); return messageData; }
/// <summary>This version of DecryptData takes the encrypted message, password /// and IV as strings and decrypts the message, returning the plain text as a string. /// </summary> /// <param name="message">The encrypted message</param> /// <param name="password">The password/key that was used to encrypt the message</param> /// <param name="initialisationVector">The IV as a string</param> /// <param name="blockSize">The block size used in encrypting the message</param> /// <param name="keySize">The key size used in encrypting the message</param> /// <param name="cryptMode">The encryption mode, CBC or ECB, used in encrypting the message</param> /// <param name="messageAsHex">Whether the encrypted message was returned as Hex</param> public static string DecryptData(string message, string password, string initialisationVector, BlockSize blockSize, KeySize keySize, EncryptionMode cryptMode, bool messageAsHex) { byte[] messageData, passwordData, vectorData; // Dont do any work is the message is empty if (message.Length <= 0) return ""; //System.Text.UnicodeEncoding encoderUnicode = new System.Text.UnicodeEncoding(); //MTreat System.Text.ASCIIEncoding encoderASCII = new System.Text.ASCIIEncoding(); //MTreat // Was message supplied in Hex or as simple string if (messageAsHex) messageData = HexToBytes(message); else //messageData = encoderUnicode.GetBytes(message); //MTreat messageData = encoderASCII.GetBytes(message); //MTreat // Convert key and IV to byte arrays //passwordData = encoderUnicode.GetBytes(password); //MTreat //vectorData = encoderUnicode.GetBytes(initialisationVector); //MTreat passwordData = encoderASCII.GetBytes(password); //MTreat vectorData = encoderASCII.GetBytes(initialisationVector); //MTreat // Return the decrypted plain test as a string //return encoderUnicode.GetString(DecryptData(messageData, passwordData, //MTreat // vectorData, blockSize, keySize, cryptMode)); //MTreat return encoderASCII.GetString(DecryptData(messageData, passwordData, //MTreat vectorData, blockSize, keySize, cryptMode)); //MTreat }
/// <summary>Encrypts the given stream using AES and returns an encryted memory stream</summary> /// <param name="source">The stream to be encryted</param> /// <param name="passphrase">Passphrase from which a psuedo-random password will be generated</param> /// <param name="salt">Salt value used along with the passphrase to generate the password</param> /// <param name="hashAlgorithm">Hash algorithm used to generate password (MD5, or SHA1)</param> /// <param name="passwordIterations">The number of passes used to generate password</param> /// <param name="initVector">16 character Initialization Vector (IV)</param> /// <param name="keySize">Size of the encryption key (128, 192, or 256 bits)</param> /// <returns>Encrypted memory stream</returns> private MemoryStream Encrypt(Stream source, string passphrase, string salt, string hashAlgorithm, int passwordIterations, string initVector, KeySize keySize) { // Copy the source stream to a new memory buffer using (MemoryStream memBuffer = new MemoryStream((int)source.Length)) { int bytesRead; byte[] buffer = new byte[1024]; while ((bytesRead = source.Read(buffer, 0, 1024)) > 0) { memBuffer.Write(buffer, 0, bytesRead); } memBuffer.Position = 0; // Encryt the file using AES byte[] initVectorBytes = System.Text.Encoding.ASCII.GetBytes(initVector); byte[] saltValueBytes = System.Text.Encoding.ASCII.GetBytes(salt); PasswordDeriveBytes password = new PasswordDeriveBytes(passphrase, saltValueBytes, hashAlgorithm, passwordIterations); byte[] keyBytes = password.GetBytes((int)keySize / 8); AesManaged aes = new AesManaged(); aes.Mode = CipherMode.CBC; aes.BlockSize = 128; aes.KeySize = (int)keySize; aes.Padding = PaddingMode.PKCS7; aes.Key = keyBytes; aes.IV = initVectorBytes; ICryptoTransform encryptor = aes.CreateEncryptor(keyBytes, initVectorBytes); MemoryStream encrytionOutput = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(encrytionOutput, encryptor, CryptoStreamMode.Write); // Encrypt the xml file cryptoStream.Write(memBuffer.GetBuffer(), 0, (int)memBuffer.Length); cryptoStream.FlushFinalBlock(); encrytionOutput.Position = 0; return encrytionOutput; } }
private byte[,] w; // key schedule array. #endregion Fields #region Constructors /// <summary> /// Initializes the AES engine /// </summary> /// <param name="keySize">Size of the key</param> /// <param name="Password">the password</param> public AES(KeySize keySize, string Password) { // convert the password to a byte array, then call the other init func byte[] keyBytes = ConvertStringToByteArray(Password); Init(keySize, keyBytes); }
public Key(string password, KeySize s) { GenerateFromPassword(password, s); }
private void Init(KeySize keySize, byte[] keyBytes) { int i = 0; int keyLen = 0, kbLen = 0; byte nextByte = 1; try { SetNbNkNr(keySize); // set the key this.key = new byte[this.Nk * 4]; // 16, 24, 32 bytes // if the password is the right size, just copy the array if (this.key.Length == keyBytes.Length) keyBytes.CopyTo(this.key, 0); else // password is different size, so manually copy { // get the key lengths keyLen = this.key.Length; kbLen = keyBytes.Length; // manuually add the password for (i = 0; i < keyLen; i++) { // make sure we can use the keyBytes if (i < kbLen) this.key[i] = keyBytes[i]; else // we need to add some extra bytes this.key[i] = nextByte++; } } // build the two matrixes BuildSbox(); BuildInvSbox(); BuildRcon(); KeyExpansion(); // expand the seed key into a key schedule and store in w } catch (Exception e) { AES_ShowError(e, "Init"); } }
public void GenerateFromPassword(string password, KeySize s) { var _s = 0; switch (s) { case KeySize._128bits: { _s = 128/8; break; } case KeySize._256bits: { _s = 256/8; break; } } var _salt = new byte[8]; for (var i = 0; i < 8; i++) { _salt[i] = 0; } _bytes = new Rfc2898DeriveBytes(password, _salt).GetBytes(_s); }
private void SetNbNkNr(KeySize keySize) { this.Nb = 4; // block size always = 4 words = 16 bytes = 128 bits for AES if (keySize == KeySize.Bits128) { this.Nk = 4; // key size = 4 words = 16 bytes = 128 bits this.Nr = 10; // rounds for algorithm = 10 } else if (keySize == KeySize.Bits192) { this.Nk = 6; // 6 words = 24 bytes = 192 bits this.Nr = 12; } else if (keySize == KeySize.Bits256) { this.Nk = 8; // 8 words = 32 bytes = 256 bits this.Nr = 14; } }
/// <SUMMARY> /// Decrypts specified ciphertext using Rijndael symmetric key algorithm. /// </SUMMARY> /// <PARAM name="cipherText"> /// Base64-formatted ciphertext value. /// </PARAM> /// <PARAM name="passPhrase"> /// Passphrase from which a pseudo-random password will be derived. The /// derived password will be used to generate the encryption key. /// Passphrase can be any string. In this example we assume that this /// passphrase is an ASCII string. /// </PARAM> /// <PARAM name="saltValue"> /// Salt value used along with passphrase to generate password. Salt can /// be any string. In this example we assume that salt is an ASCII string. /// </PARAM> /// <PARAM name="hashAlgorithm"> /// Hash algorithm used to generate password. Allowed values are: "MD5" and /// "SHA1". SHA1 hashes are a bit slower, but more secure than MD5 hashes. /// </PARAM> /// <PARAM name="passwordIterations"> /// Number of iterations used to generate password. One or two iterations /// should be enough. /// </PARAM> /// <PARAM name="initVector"> /// Initialization vector (or IV). This value is required to encrypt the /// first block of plaintext data. For RijndaelManaged class IV must be /// exactly 16 ASCII characters long. /// </PARAM> /// <PARAM name="keySize"> /// Size of encryption key in bits. Allowed values are: 128, 192, and 256. /// Longer keys are more secure than shorter keys. /// </PARAM> /// <RETURNS> /// Decrypted string value. /// </RETURNS> /// <REMARKS> /// Most of the logic in this function is similar to the Encrypt /// logic. In order for decryption to work, all parameters of this function /// - except cipherText value - must match the corresponding parameters of /// the Encrypt function which was called to generate the /// ciphertext. /// </REMARKS> private static string Decrypt(string cipherText, string passPhrase, string saltValue, HashAlgorithm hashAlgorithm, int passwordIterations, KeySize keySize) { const string initVector = "@4E1D4A5C3E2g2e7"; string _hashAlgorithm = hashAlgorithm == HashAlgorithm.MD5 ? "MD5" : "SHA1"; // Convert strings defining encryption key characteristics into byte // arrays. Let us assume that strings only contain ASCII codes. // If strings include Unicode characters, use Unicode, UTF7, or UTF8 // encoding. byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector); byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue); // Convert our ciphertext into a byte array. byte[] cipherTextBytes = Convert.FromBase64String(cipherText); // First, we must create a password, from which the key will be // derived. This password will be generated from the specified // passphrase and salt value. The password will be created using // the specified hash algorithm. Password creation can be done in // several iterations. PasswordDeriveBytes password = new PasswordDeriveBytes( passPhrase, saltValueBytes, _hashAlgorithm, passwordIterations); // Use the password to generate pseudo-random bytes for the encryption // key. Specify the size of the key in bytes (instead of bits). #pragma warning disable 618,612 byte[] keyBytes = password.GetBytes((int) keySize/8); #pragma warning restore 618,612 // Create uninitialized Rijndael encryption object. RijndaelManaged symmetricKey = new RijndaelManaged {Mode = CipherMode.CBC}; // It is reasonable to set encryption mode to Cipher Block Chaining // (CBC). Use default options for other symmetric key parameters. // Generate decryptor from the existing key bytes and initialization // vector. Key size will be defined based on the number of the key // bytes. ICryptoTransform decryptor = symmetricKey.CreateDecryptor( keyBytes, initVectorBytes); // Define memory stream which will be used to hold encrypted data. MemoryStream memoryStream = new MemoryStream(cipherTextBytes); // Define cryptographic stream (always use Read mode for encryption). CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); // Since at this point we don't know what the size of decrypted data // will be, allocate the buffer long enough to hold ciphertext; // plaintext is never longer than ciphertext. byte[] plainTextBytes = new byte[cipherTextBytes.Length]; // Start decrypting. int decryptedByteCount = 0; bool status = true; try { decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); } catch { status = false; } // Close both streams. memoryStream.Close(); cryptoStream.Close(); if (status == false) return null; // Convert decrypted data into a string. // Let us assume that the original plaintext string was UTF8-encoded. string plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount); // Return decrypted string. return plainText; }
/// <SUMMARY> /// This class uses a symmetric key algorithm (Rijndael/AES) to encrypt and /// decrypt data. As long as encryption and decryption routines use the same /// parameters to generate the keys, the keys are guaranteed to be the same. /// The class uses static functions with duplicate code to make it easier to /// demonstrate encryption and decryption logic. In a real-life application, /// this may not be the most efficient way of handling encryption, so - as /// soon as you feel comfortable with it - you may want to redesign this class. /// </SUMMARY> /// <SUMMARY> /// Encrypts specified plaintext using Rijndael symmetric key algorithm /// and returns a base64-encoded result. /// </SUMMARY> /// <PARAM name="plainText"> /// Plaintext value to be encrypted. /// </PARAM> /// <PARAM name="passPhrase"> /// Passphrase from which a pseudo-random password will be derived. The /// derived password will be used to generate the encryption key. /// Passphrase can be any string. In this example we assume that this /// passphrase is an ASCII string. /// </PARAM> /// <PARAM name="saltValue"> /// Salt value used along with passphrase to generate password. Salt can /// be any string. In this example we assume that salt is an ASCII string. /// </PARAM> /// <PARAM name="hashAlgorithm"> /// Hash algorithm used to generate password. Allowed values are: "MD5" and /// "SHA1". SHA1 hashes are a bit slower, but more secure than MD5 hashes. /// </PARAM> /// <PARAM name="passwordIterations"> /// Number of iterations used to generate password. One or two iterations /// should be enough. /// </PARAM> /// <PARAM name="initVector"> /// Initialization vector (or IV). This value is required to encrypt the /// first block of plaintext data. For RijndaelManaged class IV must be /// exactly 16 ASCII characters long. /// </PARAM> /// <PARAM name="keySize"> /// Size of encryption key in bits. Allowed values are: 128, 192, and 256. /// Longer keys are more secure than shorter keys. /// </PARAM> /// <RETURNS> /// Encrypted value formatted as a base64-encoded string. /// </RETURNS> /// private static string Encrypt(string plainText, string passPhrase, string saltValue, HashAlgorithm hashAlgorithm, int passwordIterations, KeySize keySize) { const string initVector = "@4E1D4A5C3E2g2e7"; string _hashAlgorithm = hashAlgorithm == HashAlgorithm.MD5 ? "MD5" : "SHA1"; // Convert strings into byte arrays. // Let us assume that strings only contain ASCII codes. // If strings include Unicode characters, use Unicode, UTF7, or UTF8 // encoding. byte[] initVectorBytes = Encoding.ASCII.GetBytes(initVector); byte[] saltValueBytes = Encoding.ASCII.GetBytes(saltValue); // Convert our plaintext into a byte array. // Let us assume that plaintext contains UTF8-encoded characters. byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); // First, we must create a password, from which the key will be derived. // This password will be generated from the specified passphrase and // salt value. The password will be created using the specified hash // algorithm. Password creation can be done in several iterations. PasswordDeriveBytes password = new PasswordDeriveBytes( passPhrase, saltValueBytes, _hashAlgorithm, passwordIterations); // Use the password to generate pseudo-random bytes for the encryption // key. Specify the size of the key in bytes (instead of bits). #pragma warning disable 618,612 byte[] keyBytes = password.GetBytes((int) keySize/8); #pragma warning restore 618,612 // Create uninitialized Rijndael encryption object. RijndaelManaged symmetricKey = new RijndaelManaged {Mode = CipherMode.CBC}; // It is reasonable to set encryption mode to Cipher Block Chaining // (CBC). Use default options for other symmetric key parameters. // Generate encryptor from the existing key bytes and initialization // vector. Key size will be defined based on the number of the key // bytes. ICryptoTransform encryptor = symmetricKey.CreateEncryptor( keyBytes, initVectorBytes); // Define memory stream which will be used to hold encrypted data. MemoryStream memoryStream = new MemoryStream(); // Define cryptographic stream (always use Write mode for encryption). CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); // Start encrypting. cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length); // Finish encrypting. cryptoStream.FlushFinalBlock(); // Convert our encrypted data from a memory stream into a byte array. byte[] cipherTextBytes = memoryStream.ToArray(); // Close both streams. memoryStream.Close(); cryptoStream.Close(); // Convert encrypted data into a base64-encoded string. string cipherText = Convert.ToBase64String(cipherTextBytes); // Return encrypted string. return cipherText; }
///<summary> /// Sets the size of the secret key used by the algorithm ///</summary> ///<param name="keySize">The size of the secret key used by the algorithm</param> ///<returns></returns> public RijndaelEngine SetKeySize(KeySize keySize) { KeySize = keySize; GenerateEngine(); return this; }
// ------------------------------------------------------------------------------------- // The code below are utility functions for calling the Rijndael code above // ------------------------------------------------------------------------------------- /// <summary>This version of EncryptData takes the message, password /// and IV as byte arrays and encrypts the message, returning the encrypted text /// as a byte array. /// /// NOTE: In this implementation I add four bytes to the start of the message and /// use that space to store the length of the message. Then the sister DecryptData /// function knows where to trim the message before returning it. Not all /// encryption routines will use this method. The only parts specified in the /// Rijndael standard are for use of the gentables, gkey, encrypt and decrypt /// functions. So if you have some data encrypted with another implementation /// of Rijndael, or you are encypting data that will be decrypted with another /// implementation, then you will need to know how they are recording the length of /// the message (if at all), and if you are encrypting/decrypting strings whether /// they based it on Ascii or Unicode (or some other character set). /// </summary> /// <param name="message">The encrypted message</param> /// <param name="password">The password/key to encrypt the message with</param> /// <param name="initialisationVector">The IV as a string</param> /// <param name="blockSize">The block size used to encrypt the message</param> /// <param name="keySize">The key size used to encrypt the message</param> /// <param name="cryptMode">The encryption mode, CBC or ECB, used to encrypt the message</param> public static byte[] EncryptData(byte[] message, byte[] password, byte[] initialisationVector, BlockSize blockSize, KeySize keySize, EncryptionMode cryptMode) { byte[] messageData, keyBlock, vectorBlock, dataBlock; int messageLength, encodedLength, nb, nk; // Dont do any work if message is empty messageLength = message.Length; if (messageLength <= 0) return message; // Set up arrays based on block size switch (blockSize) { case BlockSize.Block128: nb = 4; break; case BlockSize.Block192: nb = 6; break; default: // assume 256 nb = 8; break; } vectorBlock = new byte[nb * 4]; dataBlock = new byte[nb * 4]; for (int i = 0; i < (nb * 4); i++) { vectorBlock[i] = 0; dataBlock[i] = 0; } // Set up array based on key size switch (keySize) { case KeySize.Key128: nk = 4; break; case KeySize.Key192: nk = 6; break; default: // assume 256 nk = 8; break; } keyBlock = new byte[nk * 4]; for (int i = 0; i < (nk * 4); i++) { keyBlock[i] = 0; } // Key will be zero padded, or trimmed to correct size for (int i = 0; (i < password.Length) && (i < (nk * 4)); i++) keyBlock[i] = password[i]; // Vector will be zero padded, or trimmed to correct size for (int i = 0; (i < initialisationVector.Length) && (i < (nb * 4)); i++) vectorBlock[i] = initialisationVector[i]; // Prepare the key and tables using the Rijndael fuinctions gentables(); gkey(nb, nk, keyBlock); // Add 4 bytes to message to store message length, then make sure the length // is a Mod of the block size encodedLength = messageLength + 4; if ((encodedLength % (nb * 4)) != 0) encodedLength += ((nb * 4) - (encodedLength % (nb * 4))); messageData = new byte[encodedLength]; // Put message length on front of message messageData[0] = (byte)messageLength; messageData[1] = (byte)(messageLength >> 8); messageData[2] = (byte)(messageLength >> 16); messageData[3] = (byte)(messageLength >> 24); Array.Copy(message, 0, messageData, 4, messageLength); // Zero pad the end of the array for (int i = (messageLength + 4); i < encodedLength; i++) messageData[i] = 0; // Loop through the message encrypting it a block at a time for (int i = 0; i < encodedLength; i += (nb * 4)) { Array.Copy(messageData, i, dataBlock, 0, (nb * 4)); // Do some XORing if in CBC mode if (cryptMode == EncryptionMode.ModeCBC) for (int j = 0; j < (nb * 4); j++) dataBlock[j] ^= vectorBlock[j]; encrypt(dataBlock); if (cryptMode == EncryptionMode.ModeCBC) Array.Copy(dataBlock, 0, vectorBlock, 0, dataBlock.Length); Array.Copy(dataBlock, 0, messageData, i, (nb * 4)); } return messageData; }
public void SetKeySize(KeySize keySize) { string clearText = GenerateClearText(); string key = GeneratePassPhrase(); string init = GenerateInitVector(); var minSalt = (byte)DataGenerator.RandomInteger(4, 100); var maxSalt = (byte)DataGenerator.RandomInteger(100, 250); string saltKey = GenerateRandomSalt(); ICryptoEngine engine = new RijndaelEngine(key) .SetInitVector(init) .SetRandomSaltLength(minSalt, maxSalt) .SetSalt(saltKey) .SetKeySize(keySize); string encrypted = engine.Encrypt(clearText); string decrypted = engine.Decrypt(encrypted); Assert.AreNotEqual(clearText, encrypted); Assert.AreEqual(clearText, decrypted); }