티스토리 뷰

Intro. 대칭/비대칭 키와 해쉬 함수를 이용한 Digital Signiture 만드는 방법

Asymmetric

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
# 키 생성
key = RSA.generate(2048)

# 공개키(Pu)와 비공개키(Pr) 추출
Pu = key.publickey()
Pr = key

# 메시지 암호화
def rsa_encrypt(m, Pu):
    cipher = PKCS1_OAEP.new(Pu)
    ciphertext = cipher.encrypt(m)
    return ciphertext

# 암호문 복호화
def rsa_decrypt(ciphertext, Pr):
    cipher = PKCS1_OAEP.new(Pr)
    plaintext = cipher.decrypt(ciphertext)
    return plaintext

# 테스트
def start():
    message = bytes(input().encode())
    ciphertext = rsa_encrypt(message, Pu)
    plaintext = rsa_decrypt(ciphertext, Pr).decode()
    print(f"Ciphertext: {base64.b64encode(ciphertext).decode()}")
    print(f"Plaintext: {plaintext}")
  1. rsa_encrypt(m, Pu) 함수:
    • 입력: 평문 메시지(m)와 공개키(Pu)
    • 기능: 공개키(Pu)를 사용하여 평문 메시지(m)를 암호화합니다.
    • 출력: 암호화된 메시지(암호문)
  2. rsa_decrypt(ciphertext, Pr) 함수:
    • 입력: 암호문(ciphertext)과 비공개키(Pr)
    • 기능: 비공개키(Pr)를 사용하여 암호문(ciphertext)을 복호화합니다.
    • 출력: 복호화된 메시지(평문)
  3. start() 함수:
    • 입력: 사용자로부터 평문 메시지를 입력받습니다.
    • 기능: a. rsa_encrypt() 함수를 사용하여 평문 메시지를 암호화합니다. b. rsa_decrypt() 함수를 사용하여 암호문을 복호화하여 원래의 평문 메시지를 얻습니다. c. 암호화 및 복호화 과정을 확인하기 위해 암호문과 복호화된 평문을 출력합니다.
    • 출력: 암호화된 메시지(암호문)와 복호화된 메시지(평문)

Symmetric

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
import base64

def aes_encrypt(m, key, mode):
    iv = get_random_bytes(16)
    if mode == AES.MODE_ECB:
        cipher = AES.new(key, mode)
    else:    
        cipher = AES.new(key, mode, iv)
    ciphertext = cipher.encrypt(pad(m, AES.block_size))
    return iv + ciphertext

def aes_decrypt(ciphertext, key, mode):
    iv = ciphertext[:16]
    ciphertext = ciphertext[16:]
    if mode == AES.MODE_ECB:
        cipher = AES.new(key, mode)
    else:
        cipher = AES.new(key, mode, iv)
    return unpad(cipher.decrypt(ciphertext), AES.block_size).decode()

def start():
    m = bytes(input().encode())
    key = get_random_bytes(16)
    ecb_cipher = aes_encrypt(m, key, AES.MODE_ECB)
    cbc_cipher = aes_encrypt(m, key, AES.MODE_CBC)
    cfb_cipher = aes_encrypt(m, key, AES.MODE_CFB)
    ofb_cipher = aes_encrypt(m, key, AES.MODE_OFB)

    print("ECB ciphertext:", ecb_cipher)
    print("CBC ciphertext:", cbc_cipher)
    print("CFB ciphertext:", cfb_cipher)
    print("OFB ciphertext:", ofb_cipher)

    ecb_plaintext = aes_decrypt(ecb_cipher, key, AES.MODE_ECB)
    cbc_plaintext = aes_decrypt(cbc_cipher, key, AES.MODE_CBC)
    cfb_plaintext = aes_decrypt(cfb_cipher, key, AES.MODE_CFB)
    ofb_plaintext = aes_decrypt(ofb_cipher, key, AES.MODE_OFB)

    print("ECB plaintext:", ecb_plaintext)
    print("CBC plaintext:", cbc_plaintext)
    print("CFB plaintext:", cfb_plaintext)
    print("OFB plaintext:", ofb_plaintext)

사용자로부터 입력받은 메시지를 AES 암호화 알고리즘을 사용하여 암호화하고 복호화합니다. 스크립트는 ECB, CBC, CFB, OFB 네 가지 작동 모드를 모두 지원합니다. 각 함수의 기능은 다음과 같습니다:

  1. aes_encrypt(m, key, mode) 함수:
    • 입력: 평문 메시지(m), 암호화 키(key), AES 작동 모드(mode)
    • 기능: 평문 메시지(m)를 주어진 작동 모드(mode)에 따라 암호화합니다.
    • 출력: 암호화된 메시지(암호문)
  2. aes_decrypt(ciphertext, key, mode) 함수:
    • 입력: 암호문(ciphertext), 복호화 키(key), AES 작동 모드(mode)
    • 기능: 암호문(ciphertext)을 주어진 작동 모드(mode)에 따라 복호화합니다.
    • 출력: 복호화된 메시지(평문)
  3. start() 함수:
    • 입력: 사용자로부터 평문 메시지를 입력받습니다.
    • 기능: a. aes_encrypt() 함수를 사용하여 평문 메시지를 네 가지 작동 모드(ECB, CBC, CFB, OFB)로 암호화합니다. b. aes_decrypt() 함수를 사용하여 각 작동 모드로 암호화된 암호문을 복호화하여 원래의 평문 메시지를 얻습니다. c. 암호화 및 복호화 과정을 확인하기 위해 암호문과 복호화된 평문을 출력합니다.
    • 출력: 각 작동 모드별 암호화된 메시지(암호문)와 복호화된 메시지(평문)

이 스크립트를 실행하면 사용자는 메시지를 입력하고, 각 작동 모드에 따른 암호화 및 복호화 과정을 통해 원래의 메시지가 복원되는 것을 확인할 수 있습니다.

Hash

import hashlib

m = input("암호화할 메시지를 입력하세요: ") # 메세지 m 입력 받음

# SHA-512 암호화
hash_object = hashlib.sha512(m.encode())
hash_value = hash_object.hexdigest()

print(hash_value)

이 Python 스크립트는 입력받은 메시지를 SHA-512 해시 알고리즘을 사용하여 암호화합니다.

  1. 사용자로부터 암호화할 메시지를 입력받습니다.
  2. hashlib 모듈을 사용하여 입력받은 메시지를 SHA-512 해시 알고리즘으로 암호화합니다.
    • hashlib.sha512(m.encode()): 입력받은 메시지(m)를 바이트로 변환한 후, SHA-512 해시 객체를 생성합니다.
    • hash_object.hexdigest(): 해시 객체에서 16진수 형태의 해시 값을 추출합니다.
  3. 암호화된 메시지인 해시 값을 출력합니다.

SHA-512는 안전한 해시 알고리즘 중 하나로, 데이터의 무결성을 확인하거나 비밀번호 저장 등에 사용됩니다.
이 스크립트는 입력된 메시지를 바탕으로 해시 값을 생성하고 출력합니다

Digital Signiture

from Crypto.Cipher import AES
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad  # 패딩 모듈을 import합니다.

# Generate a new private/public key pair
key = RSA.generate(2048)
priv_key = key.export_key()
pub_key = key.publickey().export_key()

# Generate a random IV and key for AES encryption
iv = get_random_bytes(16)
key_aes = get_random_bytes(32)

# Message to be encrypted
# message = b'This is a 3333secret message'
message = bytes(input().encode())

# Encrypt the message using AES-CBC
cipher = AES.new(key_aes, AES.MODE_CBC, iv=iv)
# 암호화된 메시지의 길이가 16의 배수가 되도록 패딩합니다.
enc = cipher.encrypt(pad(message, AES.block_size))

# Sign the encrypted message using RSA
hash_obj = SHA256.new(enc)
cipher_rsa = PKCS1_OAEP.new(RSA.import_key(priv_key))
sig = cipher_rsa.encrypt(hash_obj.digest())

# Combine the encrypted message and signature
digital_sig = enc + sig

# Decrypt the message
hash1 = PKCS1_OAEP.new(RSA.import_key(priv_key)).decrypt(digital_sig[len(enc):])
hash2 = SHA256.new(enc).digest()
if hash1 == hash2:
    print('Hashes match. Decryption successful.')
    cipher = AES.new(key_aes, AES.MODE_CBC, iv=iv)
    decrypted_message = unpad(cipher.decrypt(enc), AES.block_size)
    print('Decrypted message:', decrypted_message.decode())
else:
    print('Hashes do not match. Decryption unsuccessful.')

입력받은 메시지를 AES 암호화 알고리즘을 사용하여 암호화하고, RSA를 사용하여 디지털 서명을 생성한 후 복호화 및 서명 검증을 수행합니다.
각 단계는 다음과 같습니다:

  1. RSA 키 생성: 2048비트 RSA 키를 생성하고, 공개키(pub_key)와 개인키(priv_key)를 추출합니다.
  2. AES 암호화 키 및 IV 생성: 32바이트 AES 키(key_aes)와 16바이트 초기화 벡터(IV)를 생성합니다.
  3. 사용자로부터 암호화할 메시지를 입력받습니다.
  4. AES 암호화: 입력받은 메시지를 AES.MODE_CBC 모드로 암호화합니다.
  5. RSA 디지털 서명 생성: 암호화된 메시지에 SHA-256 해시를 적용한 후, 개인키(priv_key)를 사용하여 디지털 서명을 생성합니다.
  6. 디지털 서명 결합: 암호화된 메시지와 디지털 서명을 결합하여 digital_sig 변수에 저장합니다.
  7. 복호화 및 서명 검증: a. 디지털 서명을 복호화하여 해시 값을 추출하고(hash1), 암호화된 메시지에 대한 해시 값을 계산합니다(hash2). b. 두 해시 값이 일치하면, AES 암호화된 메시지를 복호화하고 평문을 출력합니다. c. 두 해시 값이 일치하지 않으면, 메시지를 복호화하지 않고 실패 메시지를 출력합니다.

이 스크립트는 입력된 메시지를 바탕으로 디지털 서명을 생성하고, 복호화 및 서명 검증을 수행하여 메시지의 무결성을 보장합니다.

각 변수 별 역할

  1. key: RSA 키 쌍을 생성하는데 사용되는 변수입니다. 2048 비트 키 쌍을 생성합니다.
  2. priv_key: RSA 개인키를 저장하는 변수입니다.
  3. pub_key: RSA 공개키를 저장하는 변수입니다.
  4. iv: AES 암호화에 사용되는 16바이트 초기화 벡터(IV)를 저장하는 변수입니다.
  5. key_aes: AES 암호화에 사용되는 32바이트 비밀 키를 저장하는 변수입니다.
  6. message: 사용자로부터 입력받은 암호화할 메시지를 저장하는 변수입니다.
  7. enc: AES 암호화를 사용하여 암호화된 메시지를 저장하는 변수입니다.
  8. hash_obj: 암호화된 메시지에 적용된 SHA-256 해시 객체를 저장하는 변수입니다.
  9. cipher_rsa: RSA 개인키로 초기화된 PKCS1_OAEP 암호 객체를 저장하는 변수입니다.
  10. sig: 암호화된 메시지에 대한 RSA 디지털 서명을 저장하는 변수입니다.
  11. digital_sig: 암호화된 메시지와 디지털 서명을 결합한 결과를 저장하는 변수입니다.
  12. hash1: 디지털 서명을 복호화하여 얻은 해시 값을 저장하는 변수입니다.
  13. hash2: 암호화된 메시지에 대해 계산된 해시 값을 저장하는 변수입니다.
  14. decrypted_message: 복호화된 평문 메시지를 저장하는 변수입니다.
728x90

'Computer Science > Security' 카테고리의 다른 글

DES Overview  (0) 2023.03.29
페이스텔 암호 구조 with 대칭 블록 암호  (1) 2023.03.28
대칭 암호 원리 기초  (0) 2023.03.27
보안 서비스란 무엇인가  (0) 2023.03.27
보안 공격  (0) 2023.03.27