Programming
블록 암호화 모드 종류외 사용법
IT오이시이
2024. 12. 19. 08:11
728x90
블록 암호화 모드 종류와 사용법
블록 암호 알고리즘을 다양한 방식으로 운용하여 더욱 안전하고 효율적인 암호 시스템을 구축하는 데 적절한 방식을 선정하여 사용합니다.
파이썬 예시를 통해 사용법을 알아 봅니다.
블록 암호 운영 모드 종류
■ ECB (Electronic Codebook) 모드:
각 블록을 독립적으로 암호화하는 가장 간단한 모드입니다.
- 장점: 병렬 처리가 가능하고 구현이 간단합니다.
- 단점: 동일한 평문 블록은 항상 동일한 암호문 블록으로 변환되므로 패턴 분석 공격에 취약합니다.
- 사용 예: 이미지 압축 등 데이터의 무결성이 중요하지 않은 경우
ECB를 이용한 암호화 예시
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
# 평문 데이터
plaintext = b'This is a secret message that we want to encrypt.'
# 16 바이트 키 생성 (AES-128)
key = os.urandom(16)
# ECB 모드에 맞게 암호화 함수 정의
def encrypt_ecb(plaintext, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
return ciphertext
# ECB 모드에 맞게 복호화 함수 정의
def decrypt_ecb(ciphertext, key):
cipher = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_text = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted_text
# 패딩: AES 블록 크기에 맞게 16바이트 배수로 맞춰야함
def pad(data):
padding_length = 16 - (len(data) % 16)
return data + bytes([padding_length] * padding_length)
def unpad(data):
padding_length = data[-1]
return data[:-padding_length]
# 평문 패딩
padded_plaintext = pad(plaintext)
# 암호화
ciphertext = encrypt_ecb(padded_plaintext, key)
print('Ciphertext:', ciphertext)
# 복호화
decrypted_padded_plaintext = decrypt_ecb(ciphertext, key)
decrypted_plaintext = unpad(decrypted_padded_plaintext)
print('Decrypted plaintext:', decrypted_plaintext)
■ CBC (Cipher Block Chaining) 모드:
각 블록을 이전 암호문 블록과 현재 평문 블록을 XOR 연산한 후 암호화합니다.
- 장점: 동일한 평문 블록이 다른 암호문 블록으로 암호화되어 패턴이 드러나지 않습니다. 즉 ECB 모드보다 훨씬 안전하며, 오류 전파 특성이 있어 데이터 무결성을 보장합니다.
- 단점: 순차 처리해야 하므로 병렬 처리가 어렵습니다.
- 사용 예: 파일 암호화, 통신 보안 등
CBC 를 이용한 암호화 예시
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
# 평문 데이터
plaintext = b'This is a secret message that we want to encrypt.'
# 16 바이트 키 생성 (AES-128)
key = os.urandom(16)
# 초기화 벡터 (IV) 생성
iv = os.urandom(16)
# CBC 모드에 맞게 암호화 함수 정의
def encrypt_cbc(plaintext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
return ciphertext
# CBC 모드에 맞게 복호화 함수 정의
def decrypt_cbc(ciphertext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_text = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted_text
# 패딩: AES 블록 크기에 맞게 16바이트 배수로 맞춰야 함
def pad(data):
padding_length = 16 - (len(data) % 16)
return data + bytes([padding_length] * padding_length)
def unpad(data):
padding_length = data[-1]
return data[:-padding_length]
# 평문 패딩
padded_plaintext = pad(plaintext)
# 암호화
ciphertext = encrypt_cbc(padded_plaintext, key, iv)
print('Ciphertext:', ciphertext)
# 복호화
decrypted_padded_plaintext = decrypt_cbc(ciphertext, key, iv)
decrypted_plaintext = unpad(decrypted_padded_plaintext)
print('Decrypted plaintext:', decrypted_plaintext)
■ CFB (Cipher Feedback) 모드:
이전 암호문 블록을 암호화한 결과와 현재 평문 블록을 XOR 연산한 후 다음 암호문 블록을 생성합니다.
- 장점: 평문과 암호문의 길이가 같아 패딩이 필요 없습니다. 스트림 암호처럼 사용할 수 있으며, 오류 전파: 초기화 벡터(IV) 또는 이전 암호문 블록에서 발생한 오류가 이후 블록에 영향을 미칩니다. 즉, 오류 전파 특성이 있어 데이터 무결성을 보장합니다.
- 단점: CBC 모드와 마찬가지로 각 블록이 이전 블록의 결과에 의존하기 때문에 병렬 처리가 어렵습니다.
- 사용 예: 통신 보안, 스트림 암호화
CFB 를 이용한 암호화 예시
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
# 평문 데이터
plaintext = b'This is a secret message that we want to encrypt.'
# 16 바이트 키 생성 (AES-128)
key = os.urandom(16)
# 초기화 벡터 (IV) 생성
iv = os.urandom(16)
# CFB 모드에 맞게 암호화 함수 정의
def encrypt_cfb(plaintext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
return ciphertext
# CFB 모드에 맞게 복호화 함수 정의
def decrypt_cfb(ciphertext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_text = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted_text
# 암호화
ciphertext = encrypt_cfb(plaintext, key, iv)
print('Ciphertext:', ciphertext)
# 복호화
decrypted_plaintext = decrypt_cfb(ciphertext, key, iv)
print('Decrypted plaintext:', decrypted_plaintext)
■ OFB (Output Feedback) 모드:
OFB 모드는 초기화 벡터(IV)를 암호화하여 생성된 값을 평문 블록과 XOR하여 암호화하는 방식입니다.
이 방식은 각 블록이 독립적으로 처리될 수 있기 때문에, 블록 단위로 순차적으로 암호화할 필요 없이 병렬 처리가 가능합니다.
- 장점: 스트림 암호: 스트림 암호처럼 사용할 수 있으며, 평문과 암호문의 길이가 같아 패딩이 필요 없습니다. 오류 전파가 없습니다. 이는 데이터 무결성에 좋습니다.
- 단점:
CBC, CFB 모드와 마찬가지로 초기화 벡터(IV)를 암호화 알고리즘에 반복적으로 적용하여 암호화 값을 생성하기 때문에 순차 처리해야 합니다.
주기성 문제: OFB 모드는 초기화 벡터(IV)를 암호화 알고리즘에 반복적으로 적용하여 암호화 값을 생성합니다. 이 과정에서 주기성이 발견될 경우, 암호화의 안전성이 저하될 수 있습니다.
비트 반전 공격: 공격자가 암호문 블록을 비트 반전시키면, 대응하는 평문 블록도 비트 반전됩니다. 이는 암호문의 무결성을 해칠 수 있습니다. - 사용 예: 통신 보안, 스트림 암호화
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
# 평문 데이터
plaintext = b'This is a secret message that we want to encrypt.'
# 16 바이트 키 생성 (AES-128)
key = os.urandom(16)
# 초기화 벡터 (IV) 생성
iv = os.urandom(16)
# OFB 모드에 맞게 암호화 함수 정의
def encrypt_ofb(plaintext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.OFB(iv), backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
return ciphertext
# OFB 모드에 맞게 복호화 함수 정의
def decrypt_ofb(ciphertext, key, iv):
cipher = Cipher(algorithms.AES(key), modes.OFB(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_text = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted_text
# 암호화
ciphertext = encrypt_ofb(plaintext, key, iv)
print('Ciphertext:', ciphertext)
# 복호화
decrypted_plaintext = decrypt_ofb(ciphertext, key, iv)
print('Decrypted plaintext:', decrypted_plaintext)
- 키 생성: os.urandom(16)을 사용하여 16 바이트의 AES-128 키를 생성합니다.
- 초기화 벡터(IV) 생성: os.urandom(16)을 사용하여 16 바이트의 IV를 생성합니다. IV는 각 메시지마다 새롭게 생성되어야 합니다.
- 암호화 함수 정의: Cipher와 encryptor를 사용하여 평문을 OFB 모드로 암호화합니다.
■ CTR (Counter) 모드:
카운터 값을 암호화하여 키 스트림을 생성하고, 이를 평문 블록과 XOR 연산합니다.
- 장점: 병렬 처리가 가능하며, 스트림 암호처럼 사용할 수 있습니다.
- 단점: 카운터 값 관리가 필요합니다.
- 사용 예: 디스크 암호화, 통신 보안
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
# 평문 데이터
plaintext = b'This is a secret message that we want to encrypt.'
# 16 바이트 키 생성 (AES-128)
key = os.urandom(16)
# 16 바이트의 초기 카운터 값 생성
nonce = os.urandom(16)
# CTR 모드에 맞게 암호화 함수 정의
def encrypt_ctr(plaintext, key, nonce):
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend())
encryptor = cipher.encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
return ciphertext
# CTR 모드에 맞게 복호화 함수 정의
def decrypt_ctr(ciphertext, key, nonce):
cipher = Cipher(algorithms.AES(key), modes.CTR(nonce), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_text = decryptor.update(ciphertext) + decryptor.finalize()
return decrypted_text
# 암호화
ciphertext = encrypt_ctr(plaintext, key, nonce)
print('Ciphertext:', ciphertext)
# 복호화
decrypted_plaintext = decrypt_ctr(ciphertext, key, nonce)
print('Decrypted plaintext:', decrypted_plaintext)
- 키 생성: os.urandom(16)을 사용하여 16 바이트의 AES-128 키를 생성합니다.
- 초기 카운터 값(Nonce) 생성: os.urandom(16)을 사용하여 16 바이트의 초기 카운터 값을 생성합니다. Nonce는 각 메시지마다 새롭게 생성되어야 합니다.
- 암호화 함수 정의: Cipher와 encryptor를 사용하여 평문을 CTR 모드로 암호화합니다.
- 복호화 함수 정의: Cipher와 decryptor를 사용하여 암호문을 복호화합니다.
■ 암호화 모드 비교
.
구분 | 장점 | 단점 | 사용 예 |
ECB | 간단, 병렬 처리 | 패턴 분석 취약 | 이미지 압축 |
CBC | 안전, 오류 전파 | 순차 처리 | 파일 암호화, 통신 보안 |
CFB | 스트림 암호, 오류 없음 | 순차 처리 | 통신 보안 |
OFB | 스트림 암호, 오류 없음 | 순차 처리 | 통신 보안 |
CTR | 병렬 처리, 스트림 암호 | 카운터 관리 | 디스크 암호화, 통신 보안 |
728x90
반응형