Применение этой операции ко всем четырем столбцам состояния обозначено как MixColumn(State). Рис.2.5 демонстрирует применение MixColumn к состоянию.
Рис. 2.5. MixColumn действует на столбцы состояния.
2.5.6.Добавление циклового ключа
Вданной операции цикловой ключ добавляется к состоянию посредством простого EXOR. Цикловой ключ вырабатывается из ключа шифрования посредством алгоритма выработки ключей (key schedule). Длина циклового ключа равна длине блока Nb.
Преобразование, содержащее добавление посредством EXOR циклового ключа к состоянию, обозначено как
AddRoundKey(State, RoundKey). Оно проиллюстрировано на рис.2.6.
25
Рис 2.6. При добавлении ключа цикловой ключ складывается посредством EXOR с состоянием
26
2.5.7 Алгоритм выработки ключей (Key Schedule)
Цикловые ключи получаются из ключа шифрования посредством алгоритма выработки ключей. Он содержит два компонента: расширение ключа (Key Expansion) и выбор циклового ключа (Round Key Selection). Основополагающие принципы алгоритма выглядят следующим образом:
Общее число бит цикловых ключей равно длине блока, умноженной на число циклов плюс 1 (например, для длины блока 128 бит и 10 циклов требуется 1408 бит циклового ключа).
Ключ шифрования расширяется в Расши-
ренный Ключ (Expanded Key).
Цикловые ключи берутся из Расширенного ключа следующим образом: первый цикловой ключ содержит первые Nb слов, второй - следующие Nb слов и т.д.
2.5.8 Расширение ключа (Key Expansion)
Расширенный ключ представляет собой линейный массив 4-ех байтовых слов и обозначен как W[Nb*(Nr+1)]. Первые Nk слов содержат ключ шифрования. Все остальные слова определяются рекурсивно из слов с меньшими индексами. Алгоритм выработки ключей зависит от величины Nk: ниже приведена версия для Nk равного или меньшего 6 и версия для Nk большего 6.
Для Nk<6 или Nk=6 мы имеем:
KeyExpansion(CipherKey,W)
{
for (i = 0; i < Nk; i++) W[i] = CipherKey[i];
for (j = Nk; j < Nb*(Nk+1); j+=Nk)
{
27
W[j] = W[j-Nk] ^ SubByte( Rotl( W[j-1] ) ) ^ Rcon[j/Nk];
for (i = 1; i < Nk && i+j < Nb*(Nr+1); i++)
W[i+j] = W[i+j- Nk] ^ W[i+j-1];
}
}
Как можно заметить, первые Nk слов заполняются ключом шифрования. Каждое последующее слово W[i] получается посредством EXOR предыдущего слова W[i-1] и слова на Nk позиций ранее W[i-Nk]. Для слов, позиция которых кратна Nk, перед EXOR применяется преобразование к W[i-1], а затем еще прибавляется цикловая константа. Преобразование содержит циклический сдвиг байтов в слове, обозначенный как Rotl, затем следует SubByte - применение замены байт.
Для Nk>6 мы имеем:
KeyExpansion(CipherKey,W)
{
for (i=0; i<Nk; i++) W[i]=CipherKey[i];
for (j=Nk; j<Nb*(Nk+1); j+=Nk)
{
W[j] = W[j-Nk] ^ Sub- Byte(Rotl(W[j-1])) ^ Rcon[j/Nk];
for (i=1; i<4; i++) W[i+j] = W[i+j-Nk] ^ W[i+j-1];
W[j+4] = W[j+4-Nk] ^ SubByte(W[j+3]);
for (i=5; i<Nk; i++) W[i+j] = W[i+j-Nk] ^ W[i+j-1];
}
}
Отличие для схемы при Nk>6 состоит в применении SubByte для каждого 4-го байта из Nk.
28
Цикловая константа независит от Nk и определяется следующим образом:
Rcon[i] = ( RC[i], '00' , '00' , '00' ),
где
RC[0]='01' RC[i]=xtime(Rcon[i-1])
2.5.9 Выбор циклового ключа
i-ый цикловой ключ получается из слов массива циклового ключа от W[Nb*i] и доW[Nb(i+1)]. Это показано на рис.2.7.
Рис. 2.7. Расширение ключа и выбор циклового ключа для Nb=6 и Nk=4
Замечание: Алгоритм выработки ключей можно осуществлять и без использования массива W[Nb*(Nr+1)]. Для реализаций, в которых существенно требование к занимаемой памяти, цикловые ключи могут вычисляться на лету посредством использования буфера из Nk слов.
2.5.10. Шифр.
Шифр Rijndael состоит из:
Начального добавления циклового ключа;
Nr-1 циклов; заключительного цикла.
29