현대 암호학

[현대 암호학] 05. 실습(2)

Uggjjini 2021. 6. 23. 18:22

[실습] 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