public RijndaelTransform (Rijndael algo, bool encryption, byte[] key, byte[] iv) : base (algo, encryption, iv)
{
if (key == null)
throw new CryptographicException ("key is null");
if ((iv != null) && (iv.Length != (algo.BlockSize >> 3))) {
string msg = Locale.GetText ("IV length is invalid ({0} bytes), it should be {1} bytes long.",
iv.Length, (algo.BlockSize >> 3));
throw new CryptographicException (msg);
}
int keySize = key.Length;
if (keySize != 16 && keySize != 24 && keySize != 32) {
string msg = Locale.GetText ("Key is too small ({0} bytes), it should be {1}, {2} or {3} bytes long.",
keySize, 16, 24, 32);
throw new CryptographicException (msg);
}
keySize <<= 3; // bytes -> bits
int blockSize = algo.BlockSize;
this.Nb = (blockSize >> 5); // div 32
this.Nk = (keySize >> 5); // div 32
if (Nb == 8 || Nk == 8) {
Nr = 14;
} else if (Nb == 6 || Nk == 6) {
Nr = 12;
} else {
Nr = 10;
}
// Setup Expanded Key
int exKeySize = Nb * (Nr+1);
UInt32[] exKey = new UInt32[exKeySize];
int pos = 0;
for (int i=0; i < Nk; i++) {
UInt32 value = ((UInt32)key [pos++] << 24);
value |= ((UInt32)key[pos++] << 16);
value |= ((UInt32)key[pos++] << 8);
value |= ((UInt32)key[pos++]);
exKey [i] = value;
}
for (int i = Nk; i < exKeySize; i++) {
UInt32 temp = exKey [i-1];
if (i % Nk == 0) {
UInt32 rot = (UInt32) ((temp << 8) | ((temp >> 24) & 0xff));
temp = SubByte (rot) ^ Rcon [i / Nk];
} else if (Nk > 6 && (i % Nk) == 4) {
temp = SubByte (temp);
}
exKey [i] = exKey [i-Nk] ^ temp;
}
if (!encryption && (algo.Mode == CipherMode.ECB || algo.Mode == CipherMode.CBC)) {
for (int i = 0, k = exKeySize - Nb; i < k; i += Nb, k -= Nb) {
for (int j = 0; j < Nb; j ++) {
uint temp = exKey[i + j];
exKey[i + j] = exKey[k + j];
exKey[k + j] = temp;
}
}
for (int i = Nb; i < exKey.Length - Nb; i ++) {
exKey[i] =
iT0[SBox[(exKey[i] >> 24)]] ^
iT1[SBox[(byte)(exKey[i] >> 16)]] ^
iT2[SBox[(byte)(exKey[i] >> 8)]] ^
iT3[SBox[(byte)exKey[i]]];
}
}
expandedKey = exKey;
}