private void ProcessWord(byte[] Input, int Offset) { m_wordBuffer[m_wordOffset] = IntUtils.BytesToBe32(Input, Offset); if (++m_wordOffset == 16) { ProcessBlock(); } }
/// <remarks> /// Convert to big endian integers, increment and convert back /// </remarks> private void Rotate(byte[] Counter) { // rotate the counter at 32 or 64 bit intervals if (RotationalAlignment == CounterAlignmentSizes.RAP32) { for (int i = 0; i < Counter.Length; i += 4) { IntUtils.Be32ToBytes(IntUtils.BytesToBe32(Counter, i) + 1, Counter, i); } } else { for (int i = 0; i < Counter.Length; i += 8) { IntUtils.Be64ToBytes(IntUtils.BytesToBe64(Counter, i) + 1, Counter, i); } } }
private void Compress(byte[] Block, int Offset) { _M[0] = IntUtils.BytesToBe32(Block, Offset); _M[1] = IntUtils.BytesToBe32(Block, Offset + 4); _M[2] = IntUtils.BytesToBe32(Block, Offset + 8); _M[3] = IntUtils.BytesToBe32(Block, Offset + 12); _M[4] = IntUtils.BytesToBe32(Block, Offset + 16); _M[5] = IntUtils.BytesToBe32(Block, Offset + 20); _M[6] = IntUtils.BytesToBe32(Block, Offset + 24); _M[7] = IntUtils.BytesToBe32(Block, Offset + 28); _M[8] = IntUtils.BytesToBe32(Block, Offset + 32); _M[9] = IntUtils.BytesToBe32(Block, Offset + 36); _M[10] = IntUtils.BytesToBe32(Block, Offset + 40); _M[11] = IntUtils.BytesToBe32(Block, Offset + 44); _M[12] = IntUtils.BytesToBe32(Block, Offset + 48); _M[13] = IntUtils.BytesToBe32(Block, Offset + 52); _M[14] = IntUtils.BytesToBe32(Block, Offset + 56); _M[15] = IntUtils.BytesToBe32(Block, Offset + 60); _V[0] = _hashVal[0]; _V[1] = _hashVal[1]; _V[2] = _hashVal[2]; _V[3] = _hashVal[3]; _V[4] = _hashVal[4]; _V[5] = _hashVal[5]; _V[6] = _hashVal[6]; _V[7] = _hashVal[7]; _V[8] = _salt32[0] ^ 0x243F6A88U; _V[9] = _salt32[1] ^ 0x85A308D3U; _V[10] = _salt32[2] ^ 0x13198A2EU; _V[11] = _salt32[3] ^ 0x03707344U; _V[12] = 0xA4093822U; _V[13] = 0x299F31D0U; _V[14] = 0x082EFA98U; _V[15] = 0xEC4E6C89U; if (!_isNullT) { uint uLen = (uint)(_T & 0xFFFFFFFFU); _V[12] ^= uLen; _V[13] ^= uLen; uLen = (uint)((_T >> 32) & 0xFFFFFFFFU); _V[14] ^= uLen; _V[15] ^= uLen; } uint index = 0; do { MixBlock(index); index++; } while (index != ROUNDS); _hashVal[0] ^= _V[0]; _hashVal[1] ^= _V[1]; _hashVal[2] ^= _V[2]; _hashVal[3] ^= _V[3]; _hashVal[4] ^= _V[4]; _hashVal[5] ^= _V[5]; _hashVal[6] ^= _V[6]; _hashVal[7] ^= _V[7]; _hashVal[0] ^= _V[8]; _hashVal[1] ^= _V[9]; _hashVal[2] ^= _V[10]; _hashVal[3] ^= _V[11]; _hashVal[4] ^= _V[12]; _hashVal[5] ^= _V[13]; _hashVal[6] ^= _V[14]; _hashVal[7] ^= _V[15]; _hashVal[0] ^= _salt32[0]; _hashVal[1] ^= _salt32[1]; _hashVal[2] ^= _salt32[2]; _hashVal[3] ^= _salt32[3]; _hashVal[4] ^= _salt32[0]; _hashVal[5] ^= _salt32[1]; _hashVal[6] ^= _salt32[2]; _hashVal[7] ^= _salt32[3]; }
private uint[] StandardExpand(byte[] Key) { int cnt = 0; int index = 0; int padSize = Key.Length < 32 ? 16 : Key.Length / 2; uint[] tmpKey = new uint[padSize]; int offset = 0; // CHANGE: 512 key gets 8 extra rounds m_rndCount = (Key.Length == 64) ? 40 : ROUNDS32; int keySize = 4 * (m_rndCount + 1); // step 1: reverse copy key to temp array for (offset = Key.Length; offset > 0; offset -= 4) { tmpKey[index++] = IntUtils.BytesToBe32(Key, offset - 4); } // pad small key if (index < 8) { tmpKey[index] = 1; } // initialize the key uint[] expKey = new uint[keySize]; if (padSize == 16) { // 32 byte key // step 2: rotate k into w(k) ints for (int i = 8; i < 16; i++) { tmpKey[i] = IntUtils.RotateLeft((uint)(tmpKey[i - 8] ^ tmpKey[i - 5] ^ tmpKey[i - 3] ^ tmpKey[i - 1] ^ PHI ^ (i - 8)), 11); } // copy to expanded key Array.Copy(tmpKey, 8, expKey, 0, 8); // step 3: calculate remainder of rounds with rotating primitive for (int i = 8; i < keySize; i++) { expKey[i] = IntUtils.RotateLeft((uint)(expKey[i - 8] ^ expKey[i - 5] ^ expKey[i - 3] ^ expKey[i - 1] ^ PHI ^ i), 11); } } else { // *extended*: 64 byte key // step 3: rotate k into w(k) ints, with extended polynominal // Wp := (Wp-16 ^ Wp-13 ^ Wp-11 ^ Wp-10 ^ Wp-8 ^ Wp-5 ^ Wp-3 ^ Wp-1 ^ PHI ^ i) <<< 11 for (int i = 16; i < 32; i++) { tmpKey[i] = IntUtils.RotateLeft((uint)(tmpKey[i - 16] ^ tmpKey[i - 13] ^ tmpKey[i - 11] ^ tmpKey[i - 10] ^ tmpKey[i - 8] ^ tmpKey[i - 5] ^ tmpKey[i - 3] ^ tmpKey[i - 1] ^ PHI ^ (i - 16)), 11); } // copy to expanded key Array.Copy(tmpKey, 16, expKey, 0, 16); // step 3: calculate remainder of rounds with rotating primitive for (int i = 16; i < keySize; i++) { expKey[i] = IntUtils.RotateLeft((uint)(expKey[i - 16] ^ expKey[i - 13] ^ expKey[i - 11] ^ expKey[i - 10] ^ expKey[i - 8] ^ expKey[i - 5] ^ expKey[i - 3] ^ expKey[i - 1] ^ PHI ^ i), 11); } } // step 4: create the working keys by processing with the Sbox and IP while (cnt < keySize - 4) { Sb3(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb2(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb1(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb0(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb7(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb6(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb5(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; Sb4(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); cnt += 4; } // last round Sb3(ref expKey[cnt], ref expKey[cnt + 1], ref expKey[cnt + 2], ref expKey[cnt + 3]); return(expKey); }
private void Encrypt16(byte[] Input, int InOffset, byte[] Output, int OutOffset) { int LRD = _expKey.Length - 5; int keyCtr = -1; // input round uint R0 = IntUtils.BytesToBe32(Input, InOffset + 12); uint R1 = IntUtils.BytesToBe32(Input, InOffset + 8); uint R2 = IntUtils.BytesToBe32(Input, InOffset + 4); uint R3 = IntUtils.BytesToBe32(Input, InOffset); // process 8 round blocks do { R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb0(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb1(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb2(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3);; R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb3(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb4(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb5(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb6(ref R0, ref R1, ref R2, ref R3); LinearTransform(ref R0, ref R1, ref R2, ref R3); R0 ^= _expKey[++keyCtr]; R1 ^= _expKey[++keyCtr]; R2 ^= _expKey[++keyCtr]; R3 ^= _expKey[++keyCtr]; Sb7(ref R0, ref R1, ref R2, ref R3); // skip on last block if (keyCtr != LRD) { LinearTransform(ref R0, ref R1, ref R2, ref R3); } }while (keyCtr != LRD); // last round IntUtils.Be32ToBytes(_expKey[++keyCtr] ^ R0, Output, OutOffset + 12); IntUtils.Be32ToBytes(_expKey[++keyCtr] ^ R1, Output, OutOffset + 8); IntUtils.Be32ToBytes(_expKey[++keyCtr] ^ R2, Output, OutOffset + 4); IntUtils.Be32ToBytes(_expKey[++keyCtr] ^ R3, Output, OutOffset); }
private void Decrypt16(byte[] Input, int InOffset, byte[] Output, int OutOffset) { int LRD = 4; int keyCtr = _expKey.Length; // input round uint R3 = _expKey[--keyCtr] ^ IntUtils.BytesToBe32(Input, InOffset); uint R2 = _expKey[--keyCtr] ^ IntUtils.BytesToBe32(Input, InOffset + 4); uint R1 = _expKey[--keyCtr] ^ IntUtils.BytesToBe32(Input, InOffset + 8); uint R0 = _expKey[--keyCtr] ^ IntUtils.BytesToBe32(Input, InOffset + 12); // process 8 round blocks do { Ib7(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib6(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib5(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib4(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib3(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib2(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib1(ref R0, ref R1, ref R2, ref R3); R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); Ib0(ref R0, ref R1, ref R2, ref R3); // skip on last block if (keyCtr != LRD) { R3 ^= _expKey[--keyCtr]; R2 ^= _expKey[--keyCtr]; R1 ^= _expKey[--keyCtr]; R0 ^= _expKey[--keyCtr]; InverseTransform(ref R0, ref R1, ref R2, ref R3); } }while (keyCtr != LRD); // last round IntUtils.Be32ToBytes(R3 ^ _expKey[--keyCtr], Output, OutOffset); IntUtils.Be32ToBytes(R2 ^ _expKey[--keyCtr], Output, OutOffset + 4); IntUtils.Be32ToBytes(R1 ^ _expKey[--keyCtr], Output, OutOffset + 8); IntUtils.Be32ToBytes(R0 ^ _expKey[--keyCtr], Output, OutOffset + 12); }
private UInt32[] ExpandKey(byte[] Key) { int cnt = 0; int index = 0; int padSize = Key.Length < 32 ? 16 : Key.Length / 2; UInt32[] Wp = new UInt32[padSize]; int offset = 0; // less than 512 is default rounds if (Key.Length < 64) { _dfnRounds = ROUNDS32; } int keySize = 4 * (_dfnRounds + 1); // step 1: reverse copy key to temp array for (offset = Key.Length; offset > 0; offset -= 4) { Wp[index++] = IntUtils.BytesToBe32(Key, offset - 4); } // pad small key if (index < 8) { Wp[index] = 1; } // initialize the key UInt32[] Wk = new UInt32[keySize]; if (padSize == 16) { // 32 byte key // step 2: rotate k into w(k) ints for (int i = 8; i < 16; i++) { Wp[i] = IntUtils.RotateLeft((UInt32)(Wp[i - 8] ^ Wp[i - 5] ^ Wp[i - 3] ^ Wp[i - 1] ^ PHI ^ (i - 8)), 11); } // copy to expanded key Array.Copy(Wp, 8, Wk, 0, 8); // step 3: calculate remainder of rounds with rotating primitive for (int i = 8; i < keySize; i++) { Wk[i] = IntUtils.RotateLeft((UInt32)(Wk[i - 8] ^ Wk[i - 5] ^ Wk[i - 3] ^ Wk[i - 1] ^ PHI ^ i), 11); } } else { // *extended*: 64 byte key // step 3: rotate k into w(k) ints, with extended polynominal // Wp := (Wp-16 ^ Wp-13 ^ Wp-11 ^ Wp-10 ^ Wp-8 ^ Wp-5 ^ Wp-3 ^ Wp-1 ^ PHI ^ i) <<< 11 for (int i = 16; i < 32; i++) { Wp[i] = IntUtils.RotateLeft((UInt32)(Wp[i - 16] ^ Wp[i - 13] ^ Wp[i - 11] ^ Wp[i - 10] ^ Wp[i - 8] ^ Wp[i - 5] ^ Wp[i - 3] ^ Wp[i - 1] ^ PHI ^ (i - 16)), 11); } // copy to expanded key Array.Copy(Wp, 16, Wk, 0, 16); // step 3: calculate remainder of rounds with rotating primitive for (int i = 16; i < keySize; i++) { Wk[i] = IntUtils.RotateLeft((UInt32)(Wk[i - 16] ^ Wk[i - 13] ^ Wk[i - 11] ^ Wk[i - 10] ^ Wk[i - 8] ^ Wk[i - 5] ^ Wk[i - 3] ^ Wk[i - 1] ^ PHI ^ i), 11); } } // step 4: create the working keys by processing with the Sbox and IP while (cnt < keySize - 4) { Sb3(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb2(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb1(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb0(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb7(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb6(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb5(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; Sb4(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); cnt += 4; } // last round Sb3(ref Wk[cnt], ref Wk[cnt + 1], ref Wk[cnt + 2], ref Wk[cnt + 3]); return(Wk); }