이제 AES를 직접 구현해보겠습니다.
순서는 SubBytes, ShiftRows, MixColumns, AddRoundKey로 진행해보도록 하겠습니다.
1) SubBytes
=> Sbox에 치환합니다.
Sbox는 w = x^-1라고 할 때, y = S(x) = Aw + b의 함숫값들을 모아둔 테이블입니다.
1-1. Sbox 구하기
void Get_AES_Sbox(byte sbox[256]) {
byte temp;
sbox[0] = AES_Affine(0);
for (int i = 1; i < 256; i++) {
temp = GF_Inv(i);
sbox[i] = AES_Affine(temp);
}
}
=> y = S(x)인 형태에서 x값에 대한 y를 테이블로 구해야 합니다. 지금 이 함수에서는 x의 역원을 w로 부르기로 합니다.
그래서 함수 인자로 들어오는 x를 GF_Inv라는 역원(x^-1 = w)을 구하는 함수에 넣어 역원(w)을 얻습니다.
여기에서 0은 역원이 없기 때문에 먼저 구해줍니다.
역원(w)을 AES_Affine(S)이란 함수에 인자로 넣으면 y(= S(x))가 나옵니다. 그래서 이 y들을 모아 테이블을 만들면 Sbox가 나옵니다.
그럼 AESS_Affine 함수에 대해 더 자세히 알아보겠습니다.
byte AES_Affine(byte w) {
byte A[8][8] = {
{1,0,0,0,1,1,1,1},
{1,1,0,0,0,1,1,1},
{1,1,1,0,0,0,1,1},
{1,1,1,1,0,0,0,1},
{1,1,1,1,1,0,0,0},
{0,1,1,1,1,1,0,0},
{0,0,1,1,1,1,1,0},
{0,0,0,1,1,1,1,1}
};
byte b_vec[8] = { 1,1,0,0,0,1,1,0 };
byte w_vec[8], y_vec[8], y;
for (int i = 0; i < 8; i++) {
w_vec[i] = (w >> i) & 0x01;
}
for (int i = 0; i < 8; i++) {
y_vec[i] = b_vec[i];
for (int j = 0; j < 8;j++) {
y_vec[i] ^= A[i][j] * w_vec[j];
}
}
y = 0;
byte temp_bit;
for (int i = 0; i < 8; i++) {
temp_bit = y_vec[i] << i;
y ^= temp_bit;
}
return y;
}
=> x^-1 = w일 때, y = S(x) = Aw + b에서 A, b의 값은 정해진 값이고 w만 주어진 값입니다.
이 함수는 A와 w를 먼저 곱한 후 b의 값을 xor 시켜 y의 값을 얻을 수 있습니다.
y_vec[i] ^= A[i][j] * w_vec[j];
여기서 i와 j가 이해가 안 되면 아래의 사진을 보면 더 잘 이해할 수 있습니다.
y = Aw + b
이렇게 y를 구할 수 있습니다. 이 y들을 0~255까지 모두 모으면 아래와 같은 결과가 나옵니다.
=> 아래의 AES 표준 문서에 나와있는 Sbox랑 비교해봅시다.
=> 비교해보면 값이 같다는 걸 알 수 있습니다.
그 말은 Sbox를 제대로 구했다는 뜻입니다!
1-2) SubBytes
void AES_SubBytes(byte state[16]) {
for (int i = 0; i < 16; i++) {
state[i] = Sbox[state[i]];
}
}
=> SubBytes는 인자로 들어온 값을 Sbox에 넣어서 나온 값으로 치환합니다.
'암호학 > 대칭키암호' 카테고리의 다른 글
1.3 [C++] AES 구현 (0) | 2022.01.07 |
---|---|
1.2 [C++] AES 구현 (0) | 2022.01.06 |
1. AES (0) | 2021.12.27 |
0. 대칭키암호 (0) | 2021.12.23 |