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); } }