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}")
- rsa_encrypt(m, Pu) 함수:
- 입력: 평문 메시지(m)와 공개키(Pu)
- 기능: 공개키(Pu)를 사용하여 평문 메시지(m)를 암호화합니다.
- 출력: 암호화된 메시지(암호문)
- rsa_decrypt(ciphertext, Pr) 함수:
- 입력: 암호문(ciphertext)과 비공개키(Pr)
- 기능: 비공개키(Pr)를 사용하여 암호문(ciphertext)을 복호화합니다.
- 출력: 복호화된 메시지(평문)
- 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 네 가지 작동 모드를 모두 지원합니다. 각 함수의 기능은 다음과 같습니다:
- aes_encrypt(m, key, mode) 함수:
- 입력: 평문 메시지(m), 암호화 키(key), AES 작동 모드(mode)
- 기능: 평문 메시지(m)를 주어진 작동 모드(mode)에 따라 암호화합니다.
- 출력: 암호화된 메시지(암호문)
- aes_decrypt(ciphertext, key, mode) 함수:
- 입력: 암호문(ciphertext), 복호화 키(key), AES 작동 모드(mode)
- 기능: 암호문(ciphertext)을 주어진 작동 모드(mode)에 따라 복호화합니다.
- 출력: 복호화된 메시지(평문)
- 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 해시 알고리즘을 사용하여 암호화합니다.
- 사용자로부터 암호화할 메시지를 입력받습니다.
- hashlib 모듈을 사용하여 입력받은 메시지를 SHA-512 해시 알고리즘으로 암호화합니다.
hashlib.sha512(m.encode())
: 입력받은 메시지(m)를 바이트로 변환한 후, SHA-512 해시 객체를 생성합니다.hash_object.hexdigest()
: 해시 객체에서 16진수 형태의 해시 값을 추출합니다.
- 암호화된 메시지인 해시 값을 출력합니다.
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를 사용하여 디지털 서명을 생성한 후 복호화 및 서명 검증을 수행합니다.
각 단계는 다음과 같습니다:
- RSA 키 생성: 2048비트 RSA 키를 생성하고, 공개키(pub_key)와 개인키(priv_key)를 추출합니다.
- AES 암호화 키 및 IV 생성: 32바이트 AES 키(key_aes)와 16바이트 초기화 벡터(IV)를 생성합니다.
- 사용자로부터 암호화할 메시지를 입력받습니다.
- AES 암호화: 입력받은 메시지를 AES.MODE_CBC 모드로 암호화합니다.
- RSA 디지털 서명 생성: 암호화된 메시지에 SHA-256 해시를 적용한 후, 개인키(priv_key)를 사용하여 디지털 서명을 생성합니다.
- 디지털 서명 결합: 암호화된 메시지와 디지털 서명을 결합하여 digital_sig 변수에 저장합니다.
- 복호화 및 서명 검증: a. 디지털 서명을 복호화하여 해시 값을 추출하고(hash1), 암호화된 메시지에 대한 해시 값을 계산합니다(hash2). b. 두 해시 값이 일치하면, AES 암호화된 메시지를 복호화하고 평문을 출력합니다. c. 두 해시 값이 일치하지 않으면, 메시지를 복호화하지 않고 실패 메시지를 출력합니다.
이 스크립트는 입력된 메시지를 바탕으로 디지털 서명을 생성하고, 복호화 및 서명 검증을 수행하여 메시지의 무결성을 보장합니다.
각 변수 별 역할
- key: RSA 키 쌍을 생성하는데 사용되는 변수입니다. 2048 비트 키 쌍을 생성합니다.
- priv_key: RSA 개인키를 저장하는 변수입니다.
- pub_key: RSA 공개키를 저장하는 변수입니다.
- iv: AES 암호화에 사용되는 16바이트 초기화 벡터(IV)를 저장하는 변수입니다.
- key_aes: AES 암호화에 사용되는 32바이트 비밀 키를 저장하는 변수입니다.
- message: 사용자로부터 입력받은 암호화할 메시지를 저장하는 변수입니다.
- enc: AES 암호화를 사용하여 암호화된 메시지를 저장하는 변수입니다.
- hash_obj: 암호화된 메시지에 적용된 SHA-256 해시 객체를 저장하는 변수입니다.
- cipher_rsa: RSA 개인키로 초기화된 PKCS1_OAEP 암호 객체를 저장하는 변수입니다.
- sig: 암호화된 메시지에 대한 RSA 디지털 서명을 저장하는 변수입니다.
- digital_sig: 암호화된 메시지와 디지털 서명을 결합한 결과를 저장하는 변수입니다.
- hash1: 디지털 서명을 복호화하여 얻은 해시 값을 저장하는 변수입니다.
- hash2: 암호화된 메시지에 대해 계산된 해시 값을 저장하는 변수입니다.
- 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 |