암호_
HIGHT
정지홍
2024. 9. 24. 16:53
KISA 암호이용활성화 - 국산 암호기술 - HIGHT
1. HIGHT
- HIGh security and light weigHT
- 저전력, 경량화를 요구하는 컴퓨팅 환경에서의 기밀성을 위한 64비트 블록암호 알고리즘.
- 전체적인 구조는 피어스텔이 변형된 구조다.
- 128비트의 마스터키 ( 16개의 바이트로 구성)
- 8개의 8비트 화이트닝 키 생성 ( 블록암호의 안전성을 높히기 위해, 초기 변환 혹은 최종변환에 사용)
- 128개의 8비트 서브키 생성 ( 라운드 함수에서 사용)
- 위의 키들을 가지고 총 32라운드를 거쳐서 64비트 암호문 출력
- 64비트 평문을 입력받아서 64비트 암호문을 출력함
- 제한적인 환경에서 구현하기 위해서 8비트 단위의 기본적 산술연산 xor,add,shift연산으로 동작
- SEED , AES 보다 간단한 알고리즘. 하지만 안전성과 효율성을 고려하였음.

2. HIGHT의 키 스케쥴
2-1. HIGHT의 화이트닝키 생성
if ( 0<= i && i<= 3 ){
WK[i] = MasterKey[ i + 12 ]
}
else if ( 4<= i <= 7 ){
WK[i] = MasterKey[ i - 4 ]
}
/** 즉, 초기 변환에는 MasterKey[ 12 ]부터 MasterKey[ 15 ] 사용
최종 변환에는 MasterKey[ 0 ]부터 MasterKey[ 3 ] 사용 **/
2-2. LFSR
- LFSR( left feedback shift register )을 이용한다.
- 여기에서는 x^7 + x^3 + 1을 사용할 것이다. 즉, h는 2^7 -1 = 127의 주기를 가진다.
- h는 아래와 같은 초기 내부 상태 값을 가진다.

- 그렇다면 i=1 , 2 , 3 ,...., 127에 대해서 아래와 같이 생성된다.

- 위에서 말했듯이 주기가 127이니 0번째와 127은 같다.
delta[0] = ( 1 , 0 , 1 , 1 , 0 , 1 , 0 )
if ( 1<=i && i<=127 ){
S[i+6] = S[i+2] XOR S[i-1],
delta[i] = ( S[i+6] , S[i+5] , S[i+4] , S[i+3] , S[i+2] , S[i+1] , S[i] )
}
2-3. 서브키 생성

⊞는 mod 256
delta는 위에서 본 LFSR의 h의 내부 상태의 값들임
for i in range ( 0 , 7 ):
for j in range ( 0 , 7 ):
SubKey[16*i+j] = MasterKey[ j-i mod 8 ] ⊞ delta[16*i+j+8]
for j in range ( 0 , 7 ):
SubKey[16*i+j+8] = MasterKey[(j-i mod 8)+8] ⊞ delta[16*i+j+8]
2-4. 암호화키 생성
- 8개의 화이트닝 키와 128개의 서브키를 생성한다. (1바이트 )
- WK0 , WK1 , ...., WK7
- SK0 , SK1 , ...., SK127
2-5. 복호화키 생성
- 암호화와 같은 키 들을 이용하지만, 순서가 다르다.
- WK4, WK5 , WK6 , WK7이 초기 변환에.... WK0, WK1 , WK2 , WK3이 최종 변환에 사용
- 서브키는 SK' [i] = SK[127-i]로 사용한다.

3. 암호화 과정
3-1. 암호화 초기반환
- HIGHT암호화의 첫번째는 초기반환이다.
- 입력을 받은 64비트의 평문 P를 화이트닝 키를 이용해서 라운드 함수의 입력으로 변환한다.

- 입력을 변환하는 방법은 아래와 같다.
- P가 홀수 블럭인 경우 그냥 흘러보냄
- P가 짝수번째인 경우....
- 0번째는 WK0 적용.
- 2번째는 WK1 , 4번째는 WK2 , 6번째는 WK3을 적용.

idx=0
for i in range ( 0 , 7 ):
if i%2==1:
X[0,i] = P[i]
else:
if idx%2==0:
X[0,i] = P[i] ⊞ WK[idx]
else:
X[0,i] = p [i] ⊕ WK[idx]
idx+=1
3-2. 암호화 라운드 함수
- 라운드 함수는 아래의 두개의 보조 함수를 가진다.

- 라운드는 총 32라운드까지 존재한다.
- 입력에 대해서 아래와 같은 과정을 거친다.


/***** pseudo 느낌으로 그냥 해본 코드임! *****/
/***** 넣어도 동작 안함! *****/
uint8_t xor( uint8_t a , uint8_t b){
return a^b;
}
uint8_t left_shift ( uint8_t x , uint8_t move_positions ){
return x << move_positions;
}
uint8_t right_shift ( uint8_t x , uint8_t move_positions){
return x >> positions;
}
void F0( uint8_t *x ){
*x = left_shift( x , 1 ) xor left_shift( x , 2 ) xor left_shift( x , 7)
}
void F1( uint8_t *x ){
*x = left_shift( x , 3 ) xor left_shift( x , 4 ) xor left_shift( x , 6)
}
int i,j;
for( i=1 ; i<32 ; i++ ){
// i번째 라운드 진입
for ( j=0 ; j<8 ; j++ ){
if ( (j-1)%2==0 ){ // P블럭 번호가 짝수인 경우(=j가 홀수) 앞으로 보내서, 다음 라운드때 처리한다.
X[i][j] = X[i-1][j-1]
}
else{
if ( j==0 )
X[i][0] = X[i-1][7] xor ( F0( X[i-1][6] ) ⊞ SK[4*i-1] )
else if ( j==2 )
X[i][2] = X[i-1][1] ⊞ ( F0( X[i-1][0] ) xor SK[4*i-4] )
else if ( j==4 )
X[i][4] = X[i-1][3] xor ( F0( X[i-1][2] ) ⊞ SK[4*i-3] )
else if ( j==6 )
X[i][6] = X[i-1][5] ⊞ ( F0( X[i-1][4] ) xor SK[4*i-2] )
}
}
}
// 마지막 라운드인 32번째
X[32][0] = X[31][0]
X[32][1] = X[31][1] ⊞ ( F1( X[31][0] ) xor SK[124] )
X[32][2] = X[31][2]
X[32][3] = X[31][3] xor ( F1( X[31][2] ) ⊞ SK[125] )
X[32][4] = X[31][4]
X[32][5] = X[31][5] ⊞ ( F1( X[31][4] ) xor SK[126] )
X[32][6] = X[31][6]
X[32][7] = X[31][7] xor ( F1( X[31][6] ) ⊞ SK[127] )
3-3. 암호화 최종변환
- 화이트닝 키를 WK4, WK5, WK6 ,WK7을 이용하여 32라운드 출력을 변환한다.
- 과정은 아래와 같다.

3-4. 전체적인 구조
- 1.서브키와 화이트닝 키 생성
- 2. 평문 블록을 초기 변환
- 3. 라운드 함수 32회
- 4. 최종변환

4. 복호화
- 암호화 최종변환의 역변환 , 라운드 함수 32회 반복, 암호화 초기변환의 역변환 순서로 시행한다.

4-1. 복호화의 초기변환
- WK4, WK5, WK6 ,WK7을 사용하여 복호화 한다.
- 과정은 아래와 같다.
- 암호화된 블럭의 C가 홀수번째 블록이면 그냥 흘려보낸다.
- 0과 4째인 경우는 각각 WK4 , WK6과 -연산 후 mod 256를 적용
- 2 , 6 번째는 xor연산을 수행

4-2. 복호화 라운드 함수
- 아래의 과정을 거친다.

- 그리고 암호화와 마찬가지로 마지막 라운드에서는 바이트들은 안섞는다.

4-3. 복호화의 최종변환
- 화이트닝키 WK0, WK1 , WK2 , WK3를 이용해서 평문으로 변환
