/// <remarks> /// Expand the key and set state variables /// </remarks> private UInt32[] ExpandKey(byte[] Key, bool Encryption) { // block and key in 32 bit words _wrdBlocks = _blockSize / 4; // expanded key size int keySize = _wrdBlocks * (_dfnRounds + 1); // hkdf return array int keyBytes = keySize * 4; byte[] rawKey = new byte[keyBytes]; int saltSize = Key.Length - _ikmSize; // salt must be divisible of hash blocksize if (saltSize % _keyEngine.BlockSize != 0) saltSize = saltSize - saltSize % _keyEngine.BlockSize; // hkdf input byte[] hkdfKey = new byte[_ikmSize]; byte[] hkdfSalt = new byte[saltSize]; // copy hkdf key and salt from user key Buffer.BlockCopy(Key, 0, hkdfKey, 0, _ikmSize); Buffer.BlockCopy(Key, _ikmSize, hkdfSalt, 0, saltSize); // HKDF generator expands array using an SHA512 HMAC using (HKDF gen = new HKDF(_keyEngine, false)) { gen.Initialize(hkdfSalt, hkdfKey, _hkdfInfo); gen.Generate(rawKey); } // initialize working key UInt32[] wK = new UInt32[keySize]; // copy bytes to working key Buffer.BlockCopy(rawKey, 0, wK, 0, keyBytes); // inverse cipher if (!Encryption) { // reverse key for (int i = 0, k = keySize - _wrdBlocks; i < k; i += _wrdBlocks, k -= _wrdBlocks) { for (int j = 0; j < _wrdBlocks; j++) { UInt32 temp = wK[i + j]; wK[i + j] = wK[k + j]; wK[k + j] = temp; } } // sbox inversion for (int i = _wrdBlocks; i < keySize - _wrdBlocks; i++) { wK[i] = IT0[SBox[(wK[i] >> 24)]] ^ IT1[SBox[(byte)(wK[i] >> 16)]] ^ IT2[SBox[(byte)(wK[i] >> 8)]] ^ IT3[SBox[(byte)wK[i]]]; } } return wK; }
private Int32[] ExpandKey(byte[] Key) { Int32 Y0, Y1, Y2, Y3; int k64Cnt = 8; int keyCtr = 0; int keySize = _dfnRounds * 2 + 8; int kbtSize = keySize * 4; byte[] rawKey = new byte[kbtSize]; byte[] sbKey = new byte[32]; Int32[] eKm = new Int32[k64Cnt]; Int32[] oKm = new Int32[k64Cnt]; Int32[] wK = new Int32[keySize]; int saltSize = Key.Length - _ikmSize; // salt must be divisible of hash blocksize if (saltSize % _keyEngine.BlockSize != 0) saltSize = saltSize - saltSize % _keyEngine.BlockSize; // hkdf input byte[] hkdfKey = new byte[_ikmSize]; byte[] hkdfSalt = new byte[saltSize]; // copy hkdf key and salt from user key Buffer.BlockCopy(Key, 0, hkdfKey, 0, _ikmSize); Buffer.BlockCopy(Key, _ikmSize, hkdfSalt, 0, saltSize); // HKDF generator expands array using an SHA512 HMAC using (HKDF gen = new HKDF(_keyEngine, false)) { gen.Initialize(hkdfSalt, hkdfKey, _hkdfInfo); gen.Generate(rawKey); } // copy bytes to working key Buffer.BlockCopy(rawKey, 0, wK, 0, kbtSize); for (int i = 0; i < k64Cnt; i++) { // round key material eKm[i] = BytesToInt32(rawKey, keyCtr); keyCtr += 4; oKm[i] = BytesToInt32(rawKey, keyCtr); keyCtr += 4; // sbox key material Int32ToBytes(MDSEncode(eKm[i], oKm[i]), sbKey, ((4 * k64Cnt) - 4) - (i * 4)); } keyCtr = 0; // create keyed sbox while (keyCtr < KEY_BITS) { Y0 = Y1 = Y2 = Y3 = keyCtr; Y0 = (byte)Q1[Y0] ^ sbKey[28]; Y1 = (byte)Q0[Y1] ^ sbKey[29]; Y2 = (byte)Q0[Y2] ^ sbKey[30]; Y3 = (byte)Q1[Y3] ^ sbKey[31]; Y0 = (byte)Q1[Y0] ^ sbKey[24]; Y1 = (byte)Q1[Y1] ^ sbKey[25]; Y2 = (byte)Q0[Y2] ^ sbKey[26]; Y3 = (byte)Q0[Y3] ^ sbKey[27]; Y0 = (byte)Q0[Y0] ^ sbKey[20]; Y1 = (byte)Q1[Y1] ^ sbKey[21]; Y2 = (byte)Q1[Y2] ^ sbKey[22]; Y3 = (byte)Q0[Y3] ^ sbKey[23]; Y0 = (byte)Q0[Y0] ^ sbKey[16]; Y1 = (byte)Q0[Y1] ^ sbKey[17]; Y2 = (byte)Q1[Y2] ^ sbKey[18]; Y3 = (byte)Q1[Y3] ^ sbKey[19]; Y0 = (byte)Q1[Y0] ^ sbKey[12]; Y1 = (byte)Q0[Y1] ^ sbKey[13]; Y2 = (byte)Q0[Y2] ^ sbKey[14]; Y3 = (byte)Q1[Y3] ^ sbKey[15]; Y0 = (byte)Q1[Y0] ^ sbKey[8]; Y1 = (byte)Q1[Y1] ^ sbKey[9]; Y2 = (byte)Q0[Y2] ^ sbKey[10]; Y3 = (byte)Q0[Y3] ^ sbKey[11]; // sbox members as MDS matrix multiplies _sprBox[keyCtr * 2] = MDS0[(byte)Q0[(byte)Q0[Y0] ^ sbKey[4]] ^ sbKey[0]]; _sprBox[keyCtr * 2 + 1] = MDS1[(byte)Q0[Q1[Y1] ^ sbKey[5]] ^ sbKey[1]]; _sprBox[(keyCtr * 2) + 0x200] = MDS2[(byte)Q1[(byte)Q0[Y2] ^ sbKey[6]] ^ sbKey[2]]; _sprBox[keyCtr++ * 2 + 0x201] = MDS3[(byte)Q1[(byte)Q1[Y3] ^ sbKey[7]] ^ sbKey[3]]; } return wK; }
private Int32[] ExpandKey(byte[] Key) { // expanded key size int keySize = 4 * (_dfnRounds + 1); // hkdf return array int keyBytes = keySize * 4; byte[] rawKey = new byte[keyBytes]; int saltSize = Key.Length - _ikmSize; // salt must be divisible of hash blocksize if (saltSize % _keyEngine.BlockSize != 0) saltSize = saltSize - saltSize % _keyEngine.BlockSize; // hkdf input byte[] hkdfKey = new byte[_ikmSize]; byte[] hkdfSalt = new byte[saltSize]; // copy hkdf key and salt from user key Buffer.BlockCopy(Key, 0, hkdfKey, 0, _ikmSize); Buffer.BlockCopy(Key, _ikmSize, hkdfSalt, 0, saltSize); // HKDF generator expands array using an SHA512 HMAC using (HKDF gen = new HKDF(_keyEngine, false)) { gen.Initialize(hkdfSalt, hkdfKey, _hkdfInfo); gen.Generate(rawKey); } // initialize working key Int32[] wK = new Int32[keySize]; // copy bytes to working key Buffer.BlockCopy(rawKey, 0, wK, 0, keyBytes); return wK; }
private void HKDFTest(int Size, byte[] Salt, byte[] Key, byte[] Info, byte[] Output) { byte[] outBytes = new byte[Size]; using (HKDF gen = new HKDF(new SHA256())) { gen.Initialize(Salt, Key, Info); gen.Generate(outBytes, 0, Size); } if (Compare.AreEqual(outBytes, Output) == false) throw new Exception("HKDF: Values are not equal! Expected: " + HexConverter.ToString(Output) + " Received: " + HexConverter.ToString(outBytes)); using (HKDF gen = new HKDF(new SHA256HMAC())) { gen.Initialize(Salt, Key, Info); gen.Generate(outBytes, 0, Size); } if (Compare.AreEqual(outBytes, Output) == false) throw new Exception("HKDF: Values are not equal! Expected: " + HexConverter.ToString(Output) + " Received: " + HexConverter.ToString(outBytes)); }