프롤로그
2024.01.17 - [보안 스터디/암호학] - [암호학] 암호화 해킹 #4 (대칭키 암호, Symmetric-key Cryptography)
이 글을 복습해보자면,
대칭키 암호란 암호화에 사용되는 암호키와 복호화에 사용되는 암호키가 서로 동일한 암호화 기법이라고 하였다. 이 대칭키 암호화 방식은 데이터를 변환하는 방식에 따라 블록암호화 스트림 암호로 구분된다.
이때, 지금 우리는 블록 암호화를 하고 있는데, 블록 암호화에는 블록을 좌우 두 개 블록으로 분할하고 좌측 블록에는 라운드 함수를 적용하여 출력된 결과를 우측 블록에 적용하는 파이스텔 구조와 그냥 전체 블록에 적용하는 SPN 블록 구조가 있다고 하였다.
대칭키 암호 - 스트림 구조
- 블록 구조
- 파이스텔 방식
- SPN
이렇게 정리할 수 있는데, 파이스텔까지는 아래 글 까지 전부다 끝냈고, 이제 SPN 구조에서 AES에 대해 공부하겠다.
2024.01.18 - [보안 스터디/암호학] - [암호학] 암호화 해킹 #5 (3DES 및 구현)
2024.01.18 - [스펙업/2024 winter-study] - [MATLAB] 매트랩에서 파이썬 코드 실행하기 (3DES)
AES(Rijndael 알고리즘)
AES(Advanced Encryption Standard)는 DES를 대체하기 위해 2001년 미국 표준 기술 연구소(NIST)에서 제정한 새로운 암호 표준이다.
SPN 블록 구조를 사용하는데, 키는 128비트, 192비트, 256비트를 지원하며 암호 블록 크기는 128비트 이다.
AES 알고리즘에 대한 공격 방법은 다양하게 알려져 있으나 아직까지 AES로 암호화된 정보가 완전히 해독된 사례가 없기 때문에 안전성이 보장된 알고리즘이라고 할 수 있다.
SPN 구조
(Subsitution Permutation Network)이라는 암호 구조를 사용하는데, 곱 암호의 일종으로 S-Box를 사용하는 치환과 P-box 를 사용한느 순열을 여러 라운드에 걸쳐 반복한다.
AES 구조
AES는 암호화할 때 가장 먼저 각 블록을 4행 4열의 상태 배열(State)로 재구성한다. STate의 각 칸에는 8비트(1바이트)가 저장된다.
1F3CF203B211C5AA6EB27A45E4D98130 입력은 다음과 같이 재구성된다.
1F | 3C | F2 | 03 |
B2 | 11 | C5 | AA |
6E | B2 | 7A | 45 |
E4 | D9 | 81 | 30 |
그 이후 addRoundKey함수 적용하고 마지막 라운드 전까지 SubBytes, ShiftRows, MixColumns, AddRoundKey 함수를 반복하여 적용하고, 마지막 라운드에는 MixColumns를 제외한 나머지 함수들만 적용한다.
(1) SubBytes
State의 각 바이트를 S-Box를 참조하여 치환하는 함수. 어떤 바이트가 2A라면, 해당 바이트는 S-box의 2행 A열을 참조
(2) ShiftRows
State 의 각 행을 구성하는 바이트들을 쉬프트 하는 함수. 순열의 역할을 수행한다. 2행은 왼쪽으로 1칸, 3행은 왼쪽으로 2칸, 4행은 왼쪽으로 3칸을 빈다. 복호화는 반대로 한다.
(3) MixColumns
열 단위로 치환을 수행하는 함수. 열의 State 가 4*4 다른 행렬과 곱해져서 해당 열이 치환됨.
(4) AddRoundKey
키 생성함수로 생성된 라운드 키의 State 를 각 바이트 별로 XOR 한다.
자세한 내용은
여기서 확인할 수 있다. AES의 대하여 구현방법들이 파이썬으로 잘 구현되어 있다.
AES 구현 및 코드
키 크기(128, 192, 256비트), 암호화 블록 크기(128비트)
from Crypto.Cipher import AES
from Crypto.Hash import SHA256 as SHA
class myAES():
def __init__(self, keytext, ivtext):
hash = SHA.new()
hash.update(keytext.encode('utf-8'))
key = hash.digest()
self.key = key[:16]
hash.update(ivtext.encode('utf-8'))
iv = hash.digest()
self.iv = iv[:16]
def makeEnabled(self, plaintext):
fillersize = 0
textsize = len(plaintext)
if textsize%16 !=0:
fillersize = 16 - textsize%16
filler = '0'*fillersize
header = "%d" % (fillersize)
gap = 16 - len(header)
header += "#"*gap;
return header + plaintext + filler;
def enc(self, plaintext):
plaintext = self.makeEnabled(plaintext)
aes = AES.new(self.key, AES.MODE_CBC, self.iv)
encmsg = aes.encrypt(plaintext.encode())
return encmsg
def dec(self, ciphertext):
aes = AES.new(self.key, AES.MODE_CBC, self.iv)
decmsg = aes.decrypt(ciphertext)
header = decmsg[:16].decode()
fillersize = int(header.split("#")[0])
if fillersize !=0:
decmsg = decmsg[16:-fillersize]
else:
decmsg = decmsg[16:]
return decmsg;
def main():
keytext = "samsjang"
ivtext = "12345678"
msg = 'python3x'
myCipher = myAES(keytext, ivtext)
ciphered = myCipher.enc(msg)
deciphered = myCipher.dec(ciphered)
print("Original : \t%s" % msg)
print("Ciphered : \t%s" % ciphered)
print("Deciphered : \t%s" % deciphered)
main()
실행결과
PS C:\github\cryp> & C:/anaconda/python.exe c:/github/cryp/AES.py
Original : python3x
Ciphered : b"\xb7\xae'\x17\x1a\te\x87B\xa0\xdc\xb2\xfc\xdd\xd3\xe4B4b\xc6\xf8\xb1\x14Sq\x0cw\x06@\x9d\xc0\x0f"
Deciphered : b'python3x'
PS C:\github\cryp>
잘 실행이 되는 것을 확인할 수 있다.
코드분석
class myAES():
def __init__(self, keytext, ivtext):
hash = SHA.new()
hash.update(keytext.encode('utf-8'))
key = hash.digest()
self.key = key[:16]
hash.update(ivtext.encode('utf-8'))
iv = hash.digest()
self.iv = iv[:16]
AES 128 을 가정하여 키 값은 128을 받도록 16까지, 초기화 벡터도 블록의 크기가 128이기에 16으로 만들어놓았다.
def makeEnabled(self, plaintext):
fillersize = 0
textsize = len(plaintext)
if textsize%16 !=0:
fillersize = 16 - textsize%16
filler = '0'*fillersize
header = "%d" % (fillersize)
gap = 16 - len(header)
header += "#"*gap;
return header + plaintext + filler;
평문 메시지 길이를 16의 배수로 바꿔주는 과정이고, header 라는 벼수가 추가되었는데, 그냥 똑같이 평문의 길이에 추가해준 0의 개수만큼 헤더도 똑같이 #으로 채워주는 과정이다.
AES로 암호화 하기 전에 헤더 + 원래 정보 + 0 문자열로 반환해야한다.
나머지는 기존에 DES랑 거의 일치한다.
에필로그
이제 이것도 매트랩에서 한 번 돌리는 글을 작성할 것이다.
최종적으로 원하는 것은 파일, 음성 등의 데이터를 AES 또는 DES 이용해서 암호화 하여 저장하는 것인데,
해봅시다.
'보안 스터디 > 암호학' 카테고리의 다른 글
[암호학] 암호화 해킹 #8 (3DES와 AES를 이용하여 암호파일 저장) (0) | 2024.01.19 |
---|---|
[암호학] 암호화 해킹 #7 (스트림 암호와 ARC4) (0) | 2024.01.18 |
[암호학] 암호화 해킹 #5 (3DES 및 구현) (1) | 2024.01.18 |
[암호학] 암호화 해킹 #4 (대칭키 암호, Symmetric-key Cryptography) (0) | 2024.01.17 |
[암호학] 암호화 해킹 #3 (전치 암호 도구 만들기) (5) | 2024.01.14 |