[실습] AES-CBC 사용하여 메시지를 암복호화 하는 프로그램 개발
사용시스템
kali
AES 알고리즘을 사용하여 메시지를 암호화/복호화 하는 프로그램을 개발
프로그램 개발시 다음과 같은 사항을 참고 한다.
AES
- 입력 : 16 bytes(128 bits) 평문 입력
- 출력 : 16 bytes(128 bits) 암호문 출력
- 블록 단위 : 16 bytes(128 bites)
- 키 길이 : 16 bytes(128(16), 192(24), 256(32))
Block Cipher Mode : CBC
- IV : 16 bytes(128 bits)의 iv 필요
- Padding : 패딩(padding)에 대한 처리(암호화: pad, 복호화: unpad)
PyCryptodome 패키지에서 byte string 사용해야 한다.
- plaintext, keytext, ivtext는 encode('utf-8') 필요
직접 패딩(pad/unpad) 처리를 하지 않고 Crypto.Util.Padding 모듈 사용
- key = get_random_bytes(32)
- iv = get_random_bytes(16)
- ct = c1.encrypt(pad(msg, 16))
- unpad(c2.decrypt(msg), 16)
AESFromMsg.py
###!/usr/bin/python3
#
# AES-CBC
# 1) AES Cipher
# * input : 16 bytes
# * key : 16 bytes
# * output : 16 bytes
# 2) CBC Cipher Mode
# * iv : 16 bytes
# * pad, unpad
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
def main():
message = b'We are no longer the knights who say ni!'
key = get_random_bytes(16)
iv = get_random_bytes(16)
cipher1 = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher1.encrypt(pad(message, 16))
cipher2 = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher2.decrypt(encrypted), 16)
print("Plaintext : ", message.decode())
print("Encrypted : ", encrypted)
print("Decrypted : ", decrypted.decode())
if __name__ == '__main__':
main()
Plaintext : We are no longer the knights who say ni! Encrypted : b'Y}\xf0Bc\xf6\xdc\xc7\xab\x8e}`@e\xabf\xbf\xc6^\xc0]\xae<;Q\x0b[r\x8f%\x97\x16\xd3,a\x10Y\\\xacd\xb6J\xc1\xa5t\x07\xb3\xc2' Decrypted : We are no longer the knights who say ni! |
[실습] AES-CTR 사용하여 메시지 암복호화
AES-CTR
AES 알고리즘
- 입력 : 16 bytes(128 bits)
- 출력 : 16 bytes(128 bits)
- 키 : 16(128)/24(192)/32(256)
CTR 암호 모드
- IV 필요 없음
- Padding 처리할 필요 없음
- counter value(nonce + count)
AESFromMsg_CTR.py
##!/usr/bin/python3
#
# AES-CTR
# 1) AES Cipher
# * input : 16 bytes
# * key : 16 bytes
# * output : 16 bytes
# 2) CTR Cipher Mode
# * nonce
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def main():
mymsg = b'hello world. three.. two.. one..'
key = get_random_bytes(16)
cipher1 = AES.new(key, AES.MODE_CTR)
encrypted = cipher1.encrypt(mymsg)
nonce = cipher1.nonce
cipher2 = AES.new(key, AES.MODE_CTR, nonce=nonce)
decrypted = cipher2.decrypt(encrypted)
print("Plaintext : ", mymsg.decode())
print("Ciphertext: ", encrypted)
print("Decrypted : ", decrypted.decode())
if __name__ == "__main__":
main()
Plaintext : hello world. three.. two.. one.. Ciphertext: b'\xb1\xf7m\x00\xee\xa4\x05Nc?\xbbN\x14\xc5\xf3E\xceG\x04\tG\x06V\xe8\xb9\xc8(\x96]\xa9\x88u' Decrypted : hello world. three.. two.. one.. |
AESFromMsg_CTR2.py
JSON 포맷으로 변경하여 전송하고 그 정보를 받은 쪽에서 다시 복호화 하였다.
##!/usr/bin/python3
#
# AES-CTR
# 1) AES Cipher
# * input : 16 bytes
# * key : 16 bytes
# * output : 16 bytes
# 2) CTR Cipher Mode
# * nonce
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import json
from base64 import b64decode, b64encode
def main():
# Encryption Side
message = b'hello world!'
key = get_random_bytes(16)
print("Plaintext : ", message.decode())
cipher1 = AES.new(key, AES.MODE_CTR)
ciphertext = cipher1.encrypt(message)
nonce = cipher1.nonce
print("Encrypted : ", ciphertext)
ciphertext = b64encode(ciphertext).decode()
nonce = b64encode(cipher1.nonce).decode()
send_msg = json.dumps({'nonce': nonce, 'ciphertext': ciphertext})
print("Send MSG : ", send_msg)
# Decryption Side
recv_msg = send_msg
b64 = json.loads(recv_msg)
nonce = b64decode(b64['nonce'])
ciphertext = b64decode(b64['ciphertext'])
cipher2 = AES.new(key, AES.MODE_CTR, nonce=nonce)
decrypted = cipher2.decrypt(ciphertext)
print("Decrypted : ", decrypted.decode())
if __name__ == "__main__":
main()
Plaintext : hello world! Encrypted : b'\x88\xec\xb6gK^l\xe4\xc1\x97EW' Send MSG : {"nonce": "OcLq02VdT6o=", "ciphertext": "iOy2Z0tebOTBl0VX"} Decrypted : hello world! |
[실습] AES-EAX 사용하여 메시지 암복호화
- 암호화해서 전송할때 JSON 포맷으로 변경하여 전송하고, 받는 쪽에서 복호화한다.
- AES128 키를 생성하고 데이터를 파일로 암호화 한다.
- 수신자가 무단 수정을 감지할 수 있도록 EAX 모드를 사용한다.
AESFromMsg_EAX.py
###!/usr/bin/python3
#
# AES-CTR-EAX
# (1) AES Cipher
# * input : 16 bytes
# * key : 16 bytes
# * output : 16 bytes
# (2) CTR Cipher Mode
# * nonce
# (3) Cipher Authentication and Verify
# * tag
import json
from base64 import b64encode, b64decode
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
def main():
header = b'header'
data = b'hello world!'
key = get_random_bytes(16)
# Encryption Side
cipher1 = AES.new(key,AES.MODE_EAX)
cipher1.update(header)
ciphertext, tag = cipher1.encrypt_and_digest(data)
json_k = ['nonce', 'header', 'ciphertext', 'tag']
json_v = [b64encode(x).decode() for x in (cipher1.nonce, header, ciphertext, tag)]
send_data = json.dumps(dict(zip(json_k, json_v)))
print('Plaintext : ', data.decode())
print('Encrypted : ', ciphertext)
print('Send MSG : ', send_data)
# Decryption side
recv_data = send_data
b64 = json.loads(recv_data)
json_k = ['nonce', 'header', 'ciphertext', 'tag']
jv = ({k: b64decode(b64[k]) for k in json_k})
cipher2 = AES.new(key, AES.MODE_EAX, nonce=jv['nonce'])
cipher2.update(jv['header'])
plaintext = cipher2.decrypt_and_verify(jv['ciphertext'], jv['tag'])
print('Decrypted : ', plaintext.decode())
if __name__ == "__main__":
main()
Plaintext : hello world! Encrypted : b'\xf153\xab{\x1f\xdbW\xed<\xaa\xc8' Send MSG : {"nonce": "CBcBEXQI6ugDFZ+wAvZzhQ==", "header": "aGVhZGVy", "ciphertext": "8TUzq3sf21ftPKrI", "tag": "JYn/az/akUyA6BfSWfDAPg=="} Decrypted : hello world! |
[참고] HTTP
HTTP Request (Method : GET/POST, ....)
HTTP Response(Code : 200, 404, 301, 302, 500, ....)
HTTP Header
HTTP Body
'현대 암호학' 카테고리의 다른 글
[현대 암호학] 05. 실습(4) (0) | 2021.06.24 |
---|---|
[현대 암호학] 05. 실습(3) (0) | 2021.06.24 |
[현대 암호학] 05. 실습(1) (0) | 2021.06.23 |
[현대 암호학] 05-5. CTR 모드 (0) | 2021.06.23 |
[현대 암호학] 05-4. CFB 모드 (0) | 2021.06.23 |