암호학 강의

[암호학] 국산 블록 암호 LEA

crypsec 2023. 11. 2. 19:36
반응형

LEA(Lightweight Encryption Algorithm)는 이름 그대로 빅데이터, 클라우드 등 고속 환경 및 모바일기기 등 경량 환경에서 기밀성을 제공하기 위해 대한민국에서 개발한 128비트 블록암호 알고리즘입니다. 또한 2019년 ISO/IEC의 경량 블록 암호 분야 표준(ISO/IEC 29192-2:2019)으로 제정되었습니다.
 
국산 블록 암호 알고리즘에는 대표적으로 SEED, ARIA, LEA 등이 있습니다. 2021년에는 국내 여러 연구진들이 모여 만든 PIPO(Plug In, Plug Out)라는 블록 암호도 있습니다. 부채널 공격에도 대응할 수 있는 알고리즘이며 경량 암호 알고리즘입니다.
 
PIPO에 대해 흥미 있으신 분들은 한번 보셔도 좋을 것 같습니다.
 

PIPO 논문, SW코드

 
조금 다른 길로 세었는데 제가 보니 대부분 암호 강의들은 블록 암호 AES나 DES에 대해서만 설명하고 넘어가는 경우가 많습니다. 그리고 DES, AES에 대해서만 어느 정도 이해하고 있어도 SEED는 DES와 느낌이 비슷하고 ARIA는 AES랑 비슷하기 때문에 혼자서도 이해하는데 문제가 없습니다.
 
하지만 LEA는 앞의 두 암호를 몰라도 쉽게 구현할 수 있는 정말 쉬운 알고리즘이라 생각합니다.
 
심지어 블록 암호 LEA 규격서는 한글로 되어있고 의사 코드도 친절하게 잘 설명되어 있기 때문에 꼼꼼하게 읽기만 하여도 누구나 구현 가능합니다.
 
블록암호 LEA 규격서는 한국인터넷진흥원 사이트에서 다운로드 가능합니다.
https://seed.kisa.or.kr/kisa/algorithm/EgovLeaInfo.do

 

KISA 암호이용활성화  - 국산 암호기술 - LEA

국산 암호기술 정보보호의 기반 암호기술 및 정책에 대한 다양한 정보전달 HOME 국산 암호기술 소개 국산 암호기술 차세대 암호 암호모듈검증 암호 역기능 대응 자료실 알림마당 LEA SEED HIGHT ARIA L

seed.kisa.or.kr

 
쉬운 만큼 블록 암호 LEA의 SW 구현 코드를 제가 올리고 얼마나 문서가 쉽게 쓰였는지 비교해 보셔도 좋을 것 같습니다. 참고로 LEA는 ARX 구조라고 해서 간단한 연산인 덧셈(Addition), 회전(Rotation), 그리고 배타적 논리합(XOR, Exclusive OR)을 기반으로 합니다.
 
ARX 구조는 다음 그림에서 바로 확인 가능합니다.

LEA 암호화 라운드

 

\(X_i[]\) 들은 32-bit 크기이며 암호화 구조는 이를 계속 반복합니다. 즉, 32-bit 단위 연산을 진행하며 다양한 SW 환경에서 국제 표준암호 AES 대비 1.5배 ~ 2배 성능을 낸다고 합니다.
 
문서를 참고하여 그대로 옮긴 C언어 코드입니다. 제가 code를 만들었습니다.

 

#include <stdio.h>

typedef unsigned int word;

/*32 비트 열 x의 i비트 좌,우 순환이동*/
word ROL(word x, word i) {
	return ((x) << (i)) | ((x) >> (32 - (i)));
}
word ROR(word x, word i) {
	return ((x) >> (i)) | ((x) << (32 - (i)));
}
//#define ROL(x,i)  ((x)<<(i)) | ((x)>>(32 - (i)))
//#define ROR(x,i)  ((x)>>(i)) | ((x)<<(32 - (i)))

void round_func(word X[]/*input*/, word rk[]/*해당 라운드키*/, word state[]/*output*/) {
	state[0] = ROL(((X[0] ^ rk[0]) + (X[1] ^ rk[1])) & 0xffffffff, 9);
	state[1] = ROR(((X[1] ^ rk[2]) + (X[2] ^ rk[3])) & 0xffffffff, 5);
	state[2] = ROR(((X[2] ^ rk[4]) + (X[3] ^ rk[5])) & 0xffffffff, 3);
	state[3] = X[0];
}

void LEA_Key_Schedule(word Key[], word rk[][6]) {
	word T[4] = { 0, };
	//상수
	const word delta[8] = { 0xc3efe9db, 0x44626b02, 0x79e27c8a, 0x78df30ec, 0x715ea49e, 0xc785da0a, 0xe04ef22a,0xe5c40957 };

	T[0] = Key[0];
	T[1] = Key[1];
	T[2] = Key[2];
	T[3] = Key[3];
	for (int i = 0; i < 24; i++) {
		T[0] = ROL((T[0] + ROL(delta[i % 4], i)) & 0xffffffff, 1);
		T[1] = ROL((T[1] + ROL(delta[i % 4], i + 1))& 0xffffffff, 3);
		T[2] = ROL((T[2] + ROL(delta[i % 4], i + 2))& 0xffffffff, 6);
		T[3] = ROL((T[3] + ROL(delta[i % 4], i + 3))& 0xffffffff, 11);

		rk[i][0] = T[0];
		rk[i][1] = T[1];
		rk[i][2] = T[2];
		rk[i][3] = T[1];
		rk[i][4] = T[3];
		rk[i][5] = T[1];
	}
}
void LEA_Enc(word *plaintext, word *Key, word *ciphertext) {
	//라운드 키
	word rk[24][6] = { 0, };
	word state[4] = { 0, };
	word state2[4] = { 0, };

	LEA_Key_Schedule(Key, rk);


	round_func(plaintext, rk[0], state);
	round_func(state, rk[1], state2);
	round_func(state2, rk[2], state);
	round_func(state, rk[3], state2);
	round_func(state2, rk[4], state);
	round_func(state, rk[5], state2);
	round_func(state2, rk[6], state);
	round_func(state, rk[7], state2);
	round_func(state2, rk[8], state);
	round_func(state, rk[9], state2);
	round_func(state2, rk[10], state);
	round_func(state, rk[11], state2);
	round_func(state2, rk[12], state);
	round_func(state, rk[13], state2);
	round_func(state2, rk[14], state);
	round_func(state, rk[15], state2);
	round_func(state2, rk[16], state);
	round_func(state, rk[17], state2);
	round_func(state2, rk[18], state);
	round_func(state, rk[19], state2);
	round_func(state2, rk[20], state);
	round_func(state, rk[21], state2);
	round_func(state2, rk[22], state);
	round_func(state, rk[23], ciphertext);

}

int main() {

	/******************************Test Vector*******************************/
	word Plaintext[4] = { 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c};
	word Key[4] = { 0x3c2d1e0f, 0x78695a4b, 0xb4a59687, 0xf0e1d2c3 };
	word Ciphertext[4] = { 0, };
	/************************************************************************/

	LEA_Enc(Plaintext, Key, Ciphertext);
	printf("%08x ", Ciphertext[0]);
	printf("%08x ", Ciphertext[1]);
	printf("%08x ", Ciphertext[2]);
	printf("%08x ", Ciphertext[3]);


}

 
규격서의 부록 부분(21p)에서 맨 아래 있는 테스트 벡터 값 9f c8 4e 35 28 c6 c6 18 55 32 c7 a7 04 64 8b fd 과 제가 올린 LEA-128의 암호화 결과 값이 일치하는지 확인해 보세요!
Little endian인걸 생각하시고 보셔야 합니다.

반응형