[실습] 3DES(TDES)-CBC 사용하여 메시지를 암복호화 하는 프로그램 개발
사용시스템
kali
3DES(TDES, DES-3, DES3)사용하는 메세지를 암호화 또는 복호화 하는 프로그램 제작
프로그램 제작시 다음과 같은 사항에 대해서 참고하여야 한다.
3DES(Triple DES)
- 입력 : 8 bytes (64 bits) 평문 입력
- 출력 : 8 bytes (64 bits) 암호문 출력
- 블록 단위 : 8 bytes (64 bits)
- 키 길이 : 24bytes (K1(8) + K2(8) + K3(8))[참고] 3DES-EDE2, 3DES-EDE3
Block Cipher Mode : CBC
- IV : 8 bytes(64 bits)의 iv 필요
- Padding : 패딩(padding)에 대한 처리(암호화: pad, 복호화: unpad)
PyCryptodome 패키지에서 byte string(EX: b'hello world') 사용해야 한다.
- plaintext, keytext, ivtext는 encode('utf-8') 필요
DES3FromMsg.py
###!/usr/bin/python3
# DES3-CBC
#
# 1) DES3-EDE3
# * input : 8 bytes
# * key : 24 bytes(k1,k2,k3)
# * output : 8 bytes
# 2) Block Cipher : CBC Mode
# * IV : 8 bytes
# * padding
from Crypto.Cipher import DES3
from Crypto.Hash import SHA256 as SHA
def main():
# 1) Encryption Side
plaintext = 'We are no longer the knights who say ni!'
keytext = 'samsjang'
ivtext = '123456789'
msg = plaintext.encode()
hash = SHA.new()
hash.update(keytext.encode())
key = hash.digest()
key = key[:24]
hash.update(ivtext.encode())
iv = hash.digest()
iv = iv[:8]
cipher = DES3.new(key, DES3.MODE_CBC, iv)
encmsg = cipher.encrypt(msg)
print("Plaintext : ", plaintext)
print("Encrypted : ", encmsg)
send_msg = encmsg
send_key = key
send_iv = iv
# 2) Decryption Side
recv_msg = send_msg
recv_key = send_key
recv_iv = send_iv
cipher2 = DES3.new(recv_key, DES3.MODE_CBC, recv_iv)
decmsg = cipher2.decrypt(recv_msg)
print('Decrypted : ', decmsg)
if __name__ == '__main__':
main()
Plaintext : We are no longer the knights who say ni! Encrypted : b'\xf9G\x9a\x8d\xf3m~NX)kg\xb5\x8c\x93\xff\t\xec \x95\x0eW\xb6\xc9!\xa6N\x14\xa2\xb7\x11\x060\xca\xd5>\x13\xb1\x11\x9b' Decrypted : b'We are no longer the knights who say ni!' |
DES3FromMsg2.py
DES3From.py 파일을 class 로 변경하여 제작해 보자.
# DES3-CBC
#
# 1) DES3-EDE3
# * input : 8 bytes
# * key : 24 bytes(k1,k2,k3)
# * output : 8 bytes
# 2) Block Cipher : CBC Mode
# * IV : 8 bytes
# * padding
from Crypto.Cipher import DES3
from Crypto.Hash import SHA256 as SHA
class MyDES():
def __init__(self, keytext, ivtext):
myhash = SHA.new()
myhash.update(keytext.encode())
self.key = myhash.digest()
self.key = self.key[:24]
myhash.update(ivtext.encode())
self.iv = myhash.digest()
self.iv = self.iv[:8]
def enc(self, msg):
des3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
return des3.encrypt(msg.encode())
def dec(self, msg):
dec3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
return dec3.decrypt(msg)
def main():
message = 'We are no longer the knights who say ni!'
keytext = 'samsjang'
ivtext = '1234'
mycipher = MyDES(keytext, ivtext)
encrypted = mycipher.enc(message)
decrypted = mycipher.dec(encrypted)
print("Plaintext : ", message)
print("Encrypted : ", encrypted)
print("Decrypted : ", decrypted.decode())
if __name__ == '__main__':
main()
Plaintext : We are no longer the knights who say ni! Encypted : b'\xf9G\x9a\x8d\xf3m~NX)kg\xb5\x8c\x93\xff\t\xec \x95\x0eW\xb6\xc9!\xa6N\x14\xa2\xb7\x11\x060\xca\xd5>\x13\xb1\x11\x9b' Decrypted : We are no longer the knights who say ni! |
기능 추가(!!!! Padding 처리 문제 !!!!)
message가 8바이트 단위가 아니면(예: message='abcde') 다음과 같은 에러가 발생된다.
ValueError: Data must be padded to 8 byte boundary in CBC mode
패딩 처리가 되어 있지 않기 때문이다.
따라서, 8바이트 단위로 만들기 위해서 다음과 같은 함수를 선언한다.
def make8string(msg): # msg = 'abcde'
msglen = len(msg) # msglen = 5
filler = ''
if msglen % 8 != 0:
filler = '0' * (8 - msglen % 8)
msg += filler
return msg
그리고, 다음 파일의 내용을 조금 수정한다.
DES3FromMsg2.py
# DES3-CBC
#
# 1) DES3-EDE3
# * input : 8 bytes
# * key : 24 bytes(k1,k2,k3)
# * output : 8 bytes
# 2) Block Cipher : CBC Mode
# * IV : 8 bytes
# * padding
from Crypto.Cipher import DES3
from Crypto.Hash import SHA256 as SHA
class MyDES():
def __init__(self, keytext, ivtext):
myhash = SHA.new()
myhash.update(keytext.encode())
self.key = myhash.digest()
self.key = self.key[:24]
myhash.update(ivtext.encode())
self.iv = myhash.digest()
self.iv = self.iv[:8]
def enc(self, msg):
msg = make8string(msg)
des3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
return des3.encrypt(msg.encode())
def dec(self, msg):
dec3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
return dec3.decrypt(msg)
def make8string(msg):
msglen = len(msg)
filler = ''
if msglen % 8 != 0:
filler = '0' * (8 - msglen % 8)
msg += filler
return msg
def main():
# message = 'We are no longer the knights who say ni!'
message = 'abcde'
keytext = 'samsjang'
ivtext = '1234'
mycipher = MyDES(keytext, ivtext)
encrypted = mycipher.enc(message)
decrypted = mycipher.dec(encrypted)
print("Plaintext : ", message)
print("Encrypted : ", encrypted)
print("Decrypted : ", decrypted.decode())
if __name__ == '__main__':
main()
Plaintext : abcde Encrypted : b'ut\xe6b\xb4q\xc4-' Decrypted : abcde000 |
직접 pad, unpad 처리하기
(pad 처리 부분)
msg를 8 bytes 단위로 만들어서(pad 처리) MyDES.enc() Method에 넣고, MyDES.enc() Method의 출력은 암호문과 filler 개수를 return 한다.
- msg -> msg += fillter -> MyDES.enc(msg.encode())
- encmsg, fillternum = myDES.enc(msg.encode())
(unpad 처리 부분)
encmsg, fillernum를 MyDES.dec() Method의 인자값으로 사용해서 decmsg 생성할 때, encmsg를 복호화한 decmsg의 fillernum 개수만큼을 제거하는 작업을 한다.
- decmsg = myDES.dec(encmsg, fillternum)
- encmsg, fillernum -> decmsg -> decmsg[-fillernum]
# DES3-CBC
#
# 1) DES3-EDE3
# * input : 8 bytes
# * key : 24 bytes(k1,k2,k3)
# * output : 8 bytes
# 2) Block Cipher : CBC Mode
# * IV : 8 bytes
# * padding
from Crypto.Cipher import DES3
from Crypto.Hash import SHA256 as SHA
class MyDES():
def __init__(self, keytext, ivtext):
myhash = SHA.new()
myhash.update(keytext.encode())
self.key = myhash.digest()
self.key = self.key[:24]
myhash.update(ivtext.encode())
self.iv = myhash.digest()
self.iv = self.iv[:8]
def enc(self, msg):
msg, fillernum = make8string(msg)
des3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
return des3.encrypt(msg.encode()), fillernum
def dec(self, msg, fillernum):
dec3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)
decmsg = dec3.decrypt(msg)
decmsg = decmsg.decode()
if fillernum != 0:
decmsg = decmsg[:-fillernum]
return decmsg
def make8string(msg):
msglen = len(msg)
filler = ''
if msglen % 8 != 0:
filler = '0' * (8 - msglen % 8)
fillernum = len(filler)
msg += filler
return msg, fillernum
def main():
# message = 'We are no longer the knights who say ni!'
message = 'abcde'
keytext = 'samsjang'
ivtext = '1234'
mycipher = MyDES(keytext, ivtext)
encrypted, fillernum = mycipher.enc(message)
decrypted = mycipher.dec(encrypted, fillernum)
print("Plaintext : ", message)
print("Encrypted : ", encrypted)
print("Decrypted : ", decrypted)
if __name__ == '__main__':
main()
Plaintext : abcde Encrypted : b'ut\xe6b\xb4q\xc4-' Decrypted : abcde |
DES3FromMsg_CBC.py
다음 사항을 수정하였다.
key, iv 값을 Crypto.Random 모듈 사용
- from Crypto.Random import get_random_bytes
- key = get_random_bytes(24)
- iv = get_random_bytes(8)
직접 패딩 처리를 하지 않고 Crypto.Util.Padding 모듈 사용
- from Crypto.Util.Padding import pad, unpad
- c = AES.new(key, AES.MODE_CBC, iv)
- ct = c.encrypt(pad(data, 8))
- pt = unpad(c2.decrypt(ct), 8)
# DES3-CBC
#
# 1) DES3-EDE3
# * input : 8 bytes
# * key : 24 bytes(k1,k2,k3)
# * output : 8 bytes
# 2) Block Cipher : CBC Mode
# * IV : 8 bytes
# * padding
from Crypto.Cipher import DES3
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
mymsg = b'hello world'
key = get_random_bytes(24)
iv = get_random_bytes(8)
cipher = DES3.new(key, DES3.MODE_CBC, iv)
encrypted = cipher.encrypt(pad(mymsg, 8))
cipher2 = DES3.new(key, DES3.MODE_CBC, iv)
decrypted = unpad(cipher2.decrypt(encrypted), 8)
print("Plaintext : ", mymsg.decode())
print("Encrypted : ", encrypted)
print("Decrypted : ", decrypted.decode())
Plaintext : hello world Encrypted : b'`\xd3\xdb\xb8\xd4\x1d\x15\xdc\xd8\xb5V\x9f@\xf7\x81G' Decrypted : hello world |
'현대 암호학' 카테고리의 다른 글
[현대 암호학] 05. 실습(3) (0) | 2021.06.24 |
---|---|
[현대 암호학] 05. 실습(2) (0) | 2021.06.23 |
[현대 암호학] 05-5. CTR 모드 (0) | 2021.06.23 |
[현대 암호학] 05-4. CFB 모드 (0) | 2021.06.23 |
[현대 암호학] 05-3. CBC 모드 (0) | 2021.06.23 |