private uint[,] GenerateWorkingKey(
byte[] key,
bool forEncryption)
{
int KC = key.Length / 4; // key length in words
int t;
if ((KC != 4) && (KC != 6) && (KC != 8))
throw new ArgumentException("Key length not 128/192/256 bits.");
ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
uint[,] W = new uint[ROUNDS+1,4]; // 4 words in a block
//
// copy the key into the round key array
//
t = 0;
for (int i = 0; i < key.Length; t++)
{
W[t >> 2,t & 3] = Pack.LE_To_UInt32(key, i);
i+=4;
}
//
// while not enough round key material calculated
// calculate new values
//
int k = (ROUNDS + 1) << 2;
for (int i = KC; (i < k); i++)
{
uint temp = W[(i-1)>>2,(i-1)&3];
if ((i % KC) == 0) {
temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
} else if ((KC > 6) && ((i % KC) == 4)) {
temp = SubWord(temp);
}
W[i>>2,i&3] = W[(i - KC)>>2,(i-KC)&3] ^ temp;
}
if (!forEncryption) {
for (int j = 1; j < ROUNDS; j++) {
for (int i = 0; i < 4; i++){
W[j,i] = Inv_Mcol(W[j,i]);
}
}
}
return W;
}