public ProcessBlock ( byte input, int inOff, byte output, int outOff ) : int | ||
input | byte | |
inOff | int | |
output | byte | |
outOff | int | |
return | int |
public byte[] TransformKey(byte[] transformSeed, int rounds) { var block = BufferEx.Clone(_hash); var cipher = new AesEngine(); cipher.Init(true, new KeyParameter(transformSeed)); var aesEcb = SymmetricKeyAlgorithmProvider .OpenAlgorithm(SymmetricAlgorithmNames.AesEcb); var key = aesEcb.CreateSymmetricKey( CryptographicBuffer.CreateFromByteArray(transformSeed)); for (int i = 0; i < rounds; i++) { cipher.ProcessBlock(block, 0, block, 0); cipher.ProcessBlock(block, 16, block, 16); } return BufferEx.GetHash(block); }
private static void TestRijndael() { // Test vector (official ECB test vector #356) byte[] pbIV = new byte[16]; byte[] pbTestKey = new byte[32]; byte[] pbTestData = new byte[16]; byte[] pbReferenceCT = new byte[16] { 0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22, 0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7 }; int i; for(i = 0; i < 16; ++i) pbIV[i] = 0; for(i = 0; i < 32; ++i) pbTestKey[i] = 0; for(i = 0; i < 16; ++i) pbTestData[i] = 0; pbTestData[0] = 0x04; #if KeePassUAP AesEngine r = new AesEngine(); r.Init(true, new KeyParameter(pbTestKey)); if(r.GetBlockSize() != pbTestData.Length) throw new SecurityException(KLRes.EncAlgorithmAes + " (BS)."); r.ProcessBlock(pbTestData, 0, pbTestData, 0); #else RijndaelManaged r = new RijndaelManaged(); if(r.BlockSize != 128) // AES block size { Debug.Assert(false); r.BlockSize = 128; } r.IV = pbIV; r.KeySize = 256; r.Key = pbTestKey; r.Mode = CipherMode.ECB; ICryptoTransform iCrypt = r.CreateEncryptor(); iCrypt.TransformBlock(pbTestData, 0, 16, pbTestData, 0); #endif if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT)) throw new SecurityException(KLRes.EncAlgorithmAes + "."); }
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32, ulong uNumRounds) { #if KeePassRT KeyParameter kp = new KeyParameter(pbKeySeed32); AesEngine aes = new AesEngine(); aes.Init(true, kp); for(ulong i = 0; i < uNumRounds; ++i) { aes.ProcessBlock(pbNewKey32, 0, pbNewKey32, 0); aes.ProcessBlock(pbNewKey32, 16, pbNewKey32, 16); } #else byte[] pbIV = new byte[16]; Array.Clear(pbIV, 0, pbIV.Length); RijndaelManaged r = new RijndaelManaged(); if(r.BlockSize != 128) // AES block size { Debug.Assert(false); r.BlockSize = 128; } r.IV = pbIV; r.Mode = CipherMode.ECB; r.KeySize = 256; r.Key = pbKeySeed32; ICryptoTransform iCrypt = r.CreateEncryptor(); // !iCrypt.CanReuseTransform -- doesn't work with Mono if((iCrypt == null) || (iCrypt.InputBlockSize != 16) || (iCrypt.OutputBlockSize != 16)) { Debug.Assert(false, "Invalid ICryptoTransform."); Debug.Assert((iCrypt.InputBlockSize == 16), "Invalid input block size!"); Debug.Assert((iCrypt.OutputBlockSize == 16), "Invalid output block size!"); return false; } for(ulong i = 0; i < uNumRounds; ++i) { iCrypt.TransformBlock(pbNewKey32, 0, 16, pbNewKey32, 0); iCrypt.TransformBlock(pbNewKey32, 16, 16, pbNewKey32, 16); } #endif return true; }
/// <summary> /// Benchmark the <c>TransformKey</c> method. Within /// <paramref name="uMilliseconds"/> ms, random keys will be transformed /// and the number of performed transformations are returned. /// </summary> /// <param name="uMilliseconds">Test duration in ms.</param> /// <param name="uStep">Stepping. /// <paramref name="uStep" /> should be a prime number. For fast processors /// (PCs) a value of <c>3001</c> is recommended, for slower processors (PocketPC) /// a value of <c>401</c> is recommended.</param> /// <returns>Number of transformations performed in the specified /// amount of time. Maximum value is <c>uint.MaxValue</c>.</returns> public static ulong TransformKeyBenchmark(uint uMilliseconds, ulong uStep) { ulong uRounds; // Try native method if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds)) return uRounds; byte[] pbKey = new byte[32]; byte[] pbNewKey = new byte[32]; for(int i = 0; i < pbKey.Length; ++i) { pbKey[i] = (byte)i; pbNewKey[i] = (byte)i; } #if KeePassRT KeyParameter kp = new KeyParameter(pbKey); AesEngine aes = new AesEngine(); aes.Init(true, kp); #else byte[] pbIV = new byte[16]; Array.Clear(pbIV, 0, pbIV.Length); RijndaelManaged r = new RijndaelManaged(); if(r.BlockSize != 128) // AES block size { Debug.Assert(false); r.BlockSize = 128; } r.IV = pbIV; r.Mode = CipherMode.ECB; r.KeySize = 256; r.Key = pbKey; ICryptoTransform iCrypt = r.CreateEncryptor(); // !iCrypt.CanReuseTransform -- doesn't work with Mono if((iCrypt == null) || (iCrypt.InputBlockSize != 16) || (iCrypt.OutputBlockSize != 16)) { Debug.Assert(false, "Invalid ICryptoTransform."); Debug.Assert(iCrypt.InputBlockSize == 16, "Invalid input block size!"); Debug.Assert(iCrypt.OutputBlockSize == 16, "Invalid output block size!"); return PwDefs.DefaultKeyEncryptionRounds; } #endif uRounds = 0; int tStart = Environment.TickCount; while(true) { for(ulong j = 0; j < uStep; ++j) { #if KeePassRT aes.ProcessBlock(pbNewKey, 0, pbNewKey, 0); aes.ProcessBlock(pbNewKey, 16, pbNewKey, 16); #else iCrypt.TransformBlock(pbNewKey, 0, 16, pbNewKey, 0); iCrypt.TransformBlock(pbNewKey, 16, 16, pbNewKey, 16); #endif } uRounds += uStep; if(uRounds < uStep) // Overflow check { uRounds = ulong.MaxValue; break; } uint tElapsed = (uint)(Environment.TickCount - tStart); if(tElapsed > uMilliseconds) break; } return uRounds; }