History
기존 DES의 한계점이 부각됨에 따라 NIST에서 신규 블록 암호(Advanced Encryption Standard) 제안을 공고
Requirements
- 128 bit block length
- 3 types of key : 128, 192, 256 bits
- Superior stability comapred to known algorithms
- Effecient S/W & H/W application
→ Rijndael Algorithm(2001) was selected
Features
- Iterations
- not Feistel cipher
- Block size : 128 bits
- Key length : 128, 192, or 256 btis
- Number of rounds vary by key length
- 10 if K == 128 bits
- 12 if K == 192 bits
- 14 if K == 256 bits
- Key Expansion
- 16 bytes 의 key를 176 bytes(16*11)호 확장해 11개의 subkey를 만든다.
- take a 16 bytes subkey($key_r$) each round
Encryption&Decryption Algorithm Overview
전체적인 흐름
char State = createState(block); // block : 16 byte block
char key = expandKey(orgkey); // expand key 16 * 11
addRoundKey(State, key[0]);
for(int i = 0; i<(r-1); i++){
SubBytes(State, S-Box);
ShiftRows(State);
MixColumns(State);
addRoundKey(State, key[i]);
// last iteration
SubBytes(State, S-Box);
ShiftRows(State);
addRoundKey(State, key[i]);
return State;
위 과정에 대해 하나하나 알아보자.
char State = createState(block);
AES128 암호화에서는 데이터를 128bits(16bytes)의 블록으로 분할하고 각 16byte block을 4x4 행렬로 변환한다. 위 State는 4x4 행렬이다.
char key = expandKey(orgkey); // expand key 16 * 11
addRoundKey(State, key[0]);
암호화 키를 가져와서 연산이 가능한 형태로 정렬괸 추가 키를 $r+1$ 개 생성한다. Iteration 시작 전에 1개가 필요하므로 총 $r+1$개가 필요하다. 이를 Round Key라 부른다.
AddRoundKey 연산에서는 State 행렬과 Round Key 행렬 간의 XOR 연산을 수행한다.
초기 1회의 AddRoundKey 이후 round iteration이 진행된다.
// a single iteration is called a 'round'
for(int i = 0; i<(r-1); i++){
SubBytes(State, S-Box);
ShiftRows(State);
MixColumns(State);
addRoundKey(State, key[i]);
SubBytes 과정은 현재 State Matrix를 S-Box Matrix의 값으로 치환하는 과정이다.
위와 같은 과정을 통해 좌측 Matrix는 우측과 같이 변한다.
ShiftRows 과정은 각 row의 row index만큼 왼쪽으로 shift하는 과정이다. 1행은 그대로 두고 2행은 1칸, 3행은 2칸.. 이런 식으로 이동한다.
MixColumns 과정에서는 State Matrix의 각 column에 대해 아래 fized matrix를 곱하여 새로운 matrix로 변환한다.
bit 단위에서 2와 3을 곱하는 것은 각각 좌로 1칸 shift, 좌로 1칸 shitf하고 기존 값과 XOR하는 것과 같다.
위와 같은 연산을 모든 열에 적용한다.
매 Round마다 위 연산들의 조합을 반복하여 최종 State가 암호화된 데이터가 된다. 복호화(decryption)의 경우 위 연산을 전체적으로 역산하는 것이다. 흐름은 아래와 같다.
char State = createState(block); // block : 16 byte block
char key = expandKey(orgkey); // expand key 16 * 11
InvaddRoundKey(State, key[0]);
for(int i = 0; i<(r-1); i++){
InvShiftRows(State);
InvSubBytes(State, S-Box);
InvaddRoundKey(State, key[i]);
InvMixColumns(State);
InvShiftRows(State);
InvSubBytes(State, S-Box);
InvaddRoundKey(State, key[i]);
return State;
댓글