Theory/Cipher protocol

3DES를 이용한 암호화

D4tai1 2019. 4. 11.

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) 시연

 

 

댓글