3DES를 이용한 암호화
1. 3DES를 이용한 메세지 암호화
(1) 암호운용모드 중 CBC(Cipher-Block Chaining)를 사용
(2) 시나리오
[1] 메세지를 입력한다.
[2] 초기벡터를 입력한다.
[3] 키를 입력한다.
(3) 소스
from Crypto.Cipher import DES3 def basic_des(): msg = b'12345678' # 8byte IV = b'abcdefgh' # 8byte, 첫 블록을 암호화할 떄 사용하는 값 key = b'001234567891234567890123' # 24byte des3 = DES3.new(key, DES3.MODE_CBC, IV) # 키, 암호운용모드, 초기벡터를 넣고 des3객체 생성 e_msg = des3.encrypt(msg) # 메세지를 넣고 암호화 des3 = DES3.new(key, DES3.MODE_CBC, IV) # des3객체 새로 생성(새로 하지 않으면 기존에 있던 것에서 이어서 암호화) d_msg = des3.decrypt(e_msg) # 암호문을 넣고 복호화 print(msg) print(e_msg) print(d_msg) if __name__ == '__main__': basic_des()
(4) 시연
(3) 문제점
[1] 블록단위(8의배수)로 암호화하기 때문에 평문이나 초기벡터가 8바이트로 끊어지지 않거나 키가 24비트로 끊어지지 않으면 암호화할 수 없다.
(4) 해결방법
[1] 평문이 7바이트면 1바이트를 패딩한다.
[2] 즉, 데이터 블록 8바이트의 배수만큼 쓰고 마지막에 패딩을 하면 된다.
[3] 그러나 복호화 시에 패딩한 단어의 개수를 알 수 없으므로 데이터블록 맨 앞에 8바이트의 헤더를 만든다.
[4] 맨 앞의 8바이트 헤더 중 가장 앞 1비트에 패딩한 단어의 개수를 적고 나머지 7바이트는 패딩한다.
[5] 암호화 시 8바이트의 헤더를 떼어내고 24개만 암호화 한다.
[6] 복호화 시 8바이트의 헤더에서 맨 앞 1바이트의 숫자를 확인해서 패딩한 바이트 수를 알아낸다.
[7] 복호화 후 [6]에서 알아낸 바이트 수만큼 떼어낸다.
[8] 그러면 원문의 바이트만큼만 확인할 수 있다.
(5) 메세지 암호화(패딩)
from Crypto.Hash import SHA256 from Crypto.Cipher import DES3 class MyDES3(): def __init__(self, key, IV): sha = SHA256.new() sha.update(key) h = sha.digest() self.key = h[:24] sha.update(IV) h = sha.digest() self.IV = h[:8] def enc(self, msg): padding = b'' m_len = len(msg) if m_len % 8 != 0: pad_len = 8 - m_len % 8 padding = b'#'*pad_len msg += padding # 헤더생성 head_str = str(8 - m_len % 8).encode('utf-8') + b'#' * m_len des3 = DES3.new(self.key, DES3.MODE_CBC, self.IV) e_msg = des3.encrypt(msg) return e_msg, head_str def dec(self, e_msg, head_str): des3 = DES3.new(self.key, DES3.MODE_CBC, self.IV) d_msg = des3.decrypt(e_msg) d_len = len(d_msg) result = d_msg[:d_len - int(head_str[:1].decode())] return result def input_data(): print('3DES를 구현한 프로그램 입니다.') print('--------------------------------') IV = input('1. 초기벡터 입력 >> ') key = input('2. 키 입력 >> ') msg = input('3. 메세지 입력 >> ') return IV.encode('utf-8'), key.encode('utf-8'), msg.encode('utf-8') def modify_des(): IV, key, msg = input_data() mydes3 = MyDES3(key, IV) e_msg, head_str = mydes3.enc(msg) mydes3 = MyDES3(key, IV) d_msg = mydes3.dec(e_msg, head_str) print('--------------결과--------------') print(' [+] 원문 ', msg.decode(), sep=' >> ') print(' [+] 암호문', e_msg.decode('utf-8', 'ignore'), sep=' >> ') print(' [+] 해독문', d_msg.decode(), sep=' >> ') if __name__ == '__main__': modify_des()
(6) 시연
(7) 파일 암호화 후 비교
[1] 파일을 읽고 내용을 암호화(패딩) 후 암호화 결과를 파일로 저장
[2] 복호화 후 복호화 결과를 파일로 저장
[3] 원본파일과 복호화한 파일의 해시값 비교
import sys import subprocess from Crypto.Hash import SHA256 from Crypto.Cipher import DES3 class MyDES3(): def __init__(self, key, IV): # self.key = key # self.IV = IV sha = SHA256.new() sha.update(key) h = sha.digest() self.key = h[:24] sha.update(IV) h = sha.digest() self.IV = h[:8] def enc(self, msg): padding = b'' m_len = len(msg) if m_len % 8 != 0: pad_len = 8 - m_len % 8 padding = b'#'*pad_len msg += padding # 헤더생성 head_str = str(8 - m_len % 8).encode('utf-8') + b'#' * m_len des3 = DES3.new(self.key, DES3.MODE_CBC, self.IV) e_msg = des3.encrypt(msg) return e_msg, head_str def dec(self, e_msg, head_str): des3 = DES3.new(self.key, DES3.MODE_CBC, self.IV) d_msg = des3.decrypt(e_msg) d_len = len(d_msg) result = d_msg[:d_len - int(head_str[:1].decode())] return result def usage(): print(' [-] Usage : python3 {} <filename>'.format(sys.argv[0])) exit(1) def modify_des(): if len(sys.argv) != 2: usage() filename = sys.argv[1] try: with open(filename, 'r', encoding='utf-8') as fd: msg = fd.read().encode('utf-8') except FileNotFoundError: usage() print('3DES를 구현한 프로그램 입니다.') print('--------------------------------') IV = input('1. 초기벡터 입력 >> ').encode('utf-8') key = input('2. 키 입력 >> ').encode('utf-8') print('\n--------------결과--------------') mydes3 = MyDES3(key, IV) e_msg, head_str = mydes3.enc(msg) mydes3 = MyDES3(key, IV) d_msg = mydes3.dec(e_msg, head_str) pwd = subprocess.check_output('pwd').decode().split('\n')[0] with open('encrypt.txt', 'w', encoding='utf-8') as fd: fd.write(e_msg.decode('utf-8', 'ignore')) print(' [+] 암호문이 "{}"에 "encrypt.txt"로 생성되었습니다.'.format(pwd)) with open('decrypt.txt', 'w', encoding='utf-8') as fd: fd.write(d_msg.decode()) print(' [+] 해독문이 "{}"에 "decrypt.txt"로 생성되었습니다.'.format(pwd)) print('\n----------원문과 해독문 비교----------') sha = SHA256.new() sha.update(key) h_msg = sha.digest() sha = SHA256.new() sha.update(key) h_dmsg = sha.digest() if h_msg == h_dmsg: print(' [+] 원문과 해독문의 동일합니다.') else: print(' [-] 원문과 해독문이 동일하지 않습니다.') print(' 원문 해시', h_msg, sep=' = ') print(' 해독문 해시', h_dmsg, sep=' = ') if __name__ == '__main__': modify_des()
(8) 시연
'Theory > Cipher protocol' 카테고리의 다른 글
Ciphertext Only Attack(암호문 단독 공격) 구현 (0) | 2019.05.31 |
---|---|
Known Plaintext Attack(기지 평문 공격) 구현 (0) | 2019.05.31 |
RSA를 이용한 전자서명(디지털서명) 구현 (0) | 2019.05.31 |
RSA공개키를 이용한 암호화 구현 (0) | 2019.05.30 |
시저암호 (0) | 2019.03.19 |
댓글