AES256 암호화 - 안전한 암호화를 위한 Salt와 IV(Initialization Vector)
AES256 암호화 - 안전한 암호화를 위한 Salt와 IV(Initialization Vector)
안전한 암호화를 위해서 암호와 키의 보관과 암호를 유도하는 Salt 키와 IV(초기화 백터값)을 이용한 보안을 강화하는 방법을 정리하여 봅니다.
ㅁ AES (Advanced Encryption Standard) 암호화
AES (Advanced Encryption Standard)는 미국 국립표준기술연구소(NIST)가 선정한 암호화 표준으로, 다양한 보안 애플리케이션에서 널리 사용됩니다. AES는 대칭 키 블록 암호화 방식으로, 동일한 키를 사용하여 데이터를 암호화하고 복호화합니다. AES는 128비트, 192비트, 256비트 키 길이를 지원하며, AES-256은 256비트 길이의 키를 사용하는 가장 강력한 버전입니다.
AES256의 주요 특징
- 블록 암호화 방식: 데이터를 128비트 블록 단위
- AES는 고정된 크기(128비트)의 블록 단위로 데이터를 암호화합니다.
- 다양한 블록 암호화 모드(CBC, ECB, CFB, OFB, CTR 등)에서 사용될 수 있습니다. AES-256에서는 보통 CBC(Cipher Block Chaining) 모드가 많이 사용됩니다.
- 대칭 키 암호화: 동일한 키를 사용하여 데이터를 암호화하고 복호화
- 암호화와 복호화에 동일한 키를 사용합니다.
- 키의 길이는 256비트로, 매우 높은 보안을 제공합니다.
- 암호화 과정: 높은 보안성, 무차별 대입 공격에 매우 강합니다
- AES 암호화는 여러 라운드로 구성됩니다. AES-256의 경우 14라운드의 암호화 과정을 거칩니다.
- 각 라운드마다 SubBytes, ShiftRows, MixColumns, AddRoundKey 등의 변환을 수행하여 보안을 강화합니다.
ㅁ AES는 다양한 블록 암호화 모드에서 사용될 수 있으며, 각각의 모드는 서로 다른 보안 속성을 제공합니다.
* CBC 모드: 이전 블록의 암호문을 현재 블록에 XOR 연산하여 암호화하는 방식으로, 동일한 평문이 주어지더라도 서로 다른 암호문을 생성합니다.
* CTR 모드: 블록 번호와 nonce(일회용 값)를 사용하여 암호문을 생성하는 방식으로, 병렬 처리가 가능하고 고속 성능을 제공합니다.
ㅁ Salt와 IV의 요약
- Salt 사용: 패스워드 해싱 및 키 유도 함수에서 사용. 해시 값의 고유성 보장 및 레인보우 테이블 공격 방지.
- IV 사용: 암호화 알고리즘에서 사용. 블록 암호의 첫 번째 블록을 무작위화하여 패턴 분석 방지 및 암호화 보안 강화.
ㅁ Salt 값
Salt는 주로 패스워드 해싱 및 키 유도 함수에서 사용되는 무작위 값입니다. Salt 값의 주요 목적은 동일한 입력 값(예: 동일한 패스워드)이 주어지더라도 항상 다른 해시나 키를 생성하도록 하는 것입니다.
Salt의 역할 및 중요성:
- 고유성 보장: 동일한 패스워드가 여러 번 해시되더라도 항상 다른 해시 값을 생성하여 데이터베이스에서 패스워드 해시의 중복을 방지합니다.
- 무작위성: 공격자가 미리 계산된 해시 테이블(레인보우 테이블)을 사용하여 해시 값을 역추적하지 못하도록 합니다.
- 브루트 포스 공격 방지: Salt 값이 추가되면 공격자가 각 패스워드를 개별적으로 해시해야 하므로 브루트 포스 공격이 더욱 어려워집니다.
ㅁ IV(Initialization Vector)
IV 값은 암호화의 첫 번째 블록을 무작위화하여 동일한 데이터를 여러 번 암호화하더라도 다른 암호문을 생성하도록 합니다. IV는 암호화 알고리즘에서 사용되는 초기화 값으로, 특히 블록 암호 모드(예: CBC, CFB, OFB)에서 사용됩니다.
IV의 역할 및 중요성:
- 무작위화: 동일한 평문이 동일한 키로 여러 번 암호화되더라도 서로 다른 암호문을 생성하여 패턴 분석을 어렵게 합니다.
- 보안 강화: 초기화 벡터는 암호화 작업의 시작을 임의로 만들어 공격자가 동일한 패턴을 찾기 어렵게 합니다.
- 예측 불가능성: IV는 일반적으로 무작위로 생성되어야 하며, 예측 불가능해야 합니다. 이를 통해 공격자가 암호화된 메시지를 역추적하는 것을 방지합니다.
* Salt 값은 비밀번호 해싱 또는 키 유도 함수에서 사용되어 각 사용자의 패스워드가 고유한 해시 값을 가지도록 합니다.
* IV는 블록 암호의 첫 번째 블록을 무작위화하여 패턴 분석을 방지합니다.
# Salt 생성 함수 예시
def generate_salt(length=16):
salt = secrets.token_bytes(length)
return salt
# AES256 암호화 함수
def encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
padder = PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(data) + padder.finalize()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
return encrypted_data
ㅁ AES256을 기반으로한 암호화 예제
다음은 cryptography 모듈을 사용하여 AES-256 암호화 알고리즘으로 암호화 키와 Salt 값을 생성 및 저장하는 예제입니다.
pip install cryptography
import os
import base64
import secrets
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.padding import PKCS7
# AES256 키 길이
KEY_LENGTH = 32 # 256 bits
IV_LENGTH = 16 # 128 bits (AES block size)
# 암호화 키 생성 함수
def generate_encryption_key(length=KEY_LENGTH):
key = secrets.token_bytes(length)
return key
# Salt 생성 함수
def generate_salt(length=16):
salt = secrets.token_bytes(length)
return salt
# PBKDF2를 사용하여 암호와 salt로부터 키를 생성하는 함수
def derive_key(password: str, salt: bytes, iterations=100000, length=KEY_LENGTH):
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=length,
salt=salt,
iterations=iterations,
backend=default_backend()
)
key = kdf.derive(password.encode())
return key
# AES256 암호화 함수
def encrypt(data: bytes, key: bytes, iv: bytes) -> bytes:
padder = PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(data) + padder.finalize()
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
encrypted_data = encryptor.update(padded_data) + encryptor.finalize()
return encrypted_data
# AES256 복호화 함수
def decrypt(encrypted_data: bytes, key: bytes, iv: bytes) -> bytes:
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_data = decryptor.update(encrypted_data) + decryptor.finalize()
unpadder = PKCS7(algorithms.AES.block_size).unpadder()
data = unpadder.update(padded_data) + unpadder.finalize()
return data
# 키와 Salt를 파일에 저장하는 함수
def save_to_file(data: bytes, filename: str):
with open(filename, 'wb') as file:
file.write(data)
# 파일에서 키와 Salt를 불러오는 함수
def load_from_file(filename: str) -> bytes:
with open(filename, 'rb') as file:
data = file.read()
return data
# 예제 실행
password = "my_secure_password" # 사용자 비밀번호
salt = generate_salt()
key = derive_key(password, salt)
iv = secrets.token_bytes(IV_LENGTH) # IV 생성
# 암호화할 데이터
data_to_encrypt = b"Sensitive data that needs encryption"
# 데이터 암호화
encrypted_data = encrypt(data_to_encrypt, key, iv)
# 키, Salt, IV 및 암호화된 데이터를 파일에 저장
save_to_file(key, 'encryption_key.bin')
save_to_file(salt, 'salt.bin')
save_to_file(iv, 'iv.bin')
save_to_file(encrypted_data, 'encrypted_data.bin')
# 파일에서 키, Salt, IV 및 암호화된 데이터를 불러오기
loaded_key = load_from_file('encryption_key.bin')
loaded_salt = load_from_file('salt.bin')
loaded_iv = load_from_file('iv.bin')
loaded_encrypted_data = load_from_file('encrypted_data.bin')
# 데이터 복호화
decrypted_data = decrypt(loaded_encrypted_data, loaded_key, loaded_iv)
# 출력 확인
print("Generated Key:", base64.urlsafe_b64encode(key).decode())
print("Generated Salt:", base64.urlsafe_b64encode(salt).decode())
print("Generated IV:", base64.urlsafe_b64encode(iv).decode())
print("Encrypted Data:", base64.urlsafe_b64encode(encrypted_data).decode())
print("Decrypted Data:", decrypted_data.decode())
예시 설명
- 키 생성 및 유도:
- generate_encryption_key 함수는 암호학적으로 안전한 AES-256 키를 생성합니다.
- generate_salt 함수는 예측 불가능한 Salt 값을 생성합니다.
- derive_key 함수는 사용자의 비밀번호와 Salt를 사용하여 PBKDF2 알고리즘으로부터 키를 유도합니다.
- AES256 암호화 및 복호화:
- encrypt 함수는 AES-256 암호화를 수행합니다. CBC 모드와 PKCS7 패딩을 사용합니다.
- decrypt 함수는 AES-256 복호화를 수행합니다.
- 파일 저장 및 로드:
- save_to_file 함수는 키, Salt, IV 및 암호화된 데이터를 파일에 저장합니다.
- load_from_file 함수는 저장된 파일에서 데이터를 불러옵니다.
- 데이터 암호화 및 복호화:
- 주어진 데이터를 AES-256으로 암호화하고, 파일에 저장한 후, 다시 불러와 복호화하여 원본 데이터를 확인합니다.