private uint[] GenerateWorkingKey(bool isEncryption, byte[] key)
{
int KC = key.Length / 4; // key length in words
if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
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
//
int t = 0;
for (int i = 0; i < key.Length; t++)
{
W[(t >> 2) * 4 + (t & 3)] = LittleEndianToUInt32(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) * 4 + ((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) * 4 + (i & 3)] = W[((i - KC) >> 2) * 4 + ((i - KC) & 3)] ^ temp;
}
if (!isEncryption)
{
for (int j = 1; j < _rounds; j++)
{
for (int i = 0; i < 4; i++)
{
W[j * 4 + i] = InvMcol(W[j * 4 + i]);
}
}
}
return W;
}