Programming

AES256 암호화 - 안전한 암호화를 위한 Salt와 IV(Initialization Vector)

IT오이시이 2024. 7. 3. 15:46
728x90

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의 주요 특징

  1. 블록 암호화 방식: 데이터를 128비트 블록 단위
    • AES는 고정된 크기(128비트)의 블록 단위로 데이터를 암호화합니다.
    • 다양한 블록 암호화 모드(CBC, ECB, CFB, OFB, CTR 등)에서 사용될 수 있습니다. AES-256에서는 보통 CBC(Cipher Block Chaining) 모드가 많이 사용됩니다.
  2. 대칭 키 암호화: 동일한 키를 사용하여 데이터를 암호화하고 복호화
    • 암호화와 복호화에 동일한 키를 사용합니다.
    • 키의 길이는 256비트로, 매우 높은 보안을 제공합니다.
  3. 암호화 과정: 높은 보안성, 무차별 대입 공격에 매우 강합니다
    • AES 암호화는 여러 라운드로 구성됩니다. AES-256의 경우 14라운드의 암호화 과정을 거칩니다.
    • 각 라운드마다 SubBytes, ShiftRows, MixColumns, AddRoundKey 등의 변환을 수행하여 보안을 강화합니다.

 

ㅁ AES는 다양한 블록 암호화 모드에서 사용될 수 있으며, 각각의 모드는 서로 다른 보안 속성을 제공합니다.
* CBC 모드: 이전 블록의 암호문을 현재 블록에 XOR 연산하여 암호화하는 방식으로, 동일한 평문이 주어지더라도 서로 다른 암호문을 생성합니다.
* CTR 모드: 블록 번호와 nonce(일회용 값)를 사용하여 암호문을 생성하는 방식으로, 병렬 처리가 가능하고 고속 성능을 제공합니다.

 

 

ㅁ Salt와 IV의  요약

  • Salt 사용: 패스워드 해싱 및 키 유도 함수에서 사용. 해시 값의 고유성 보장 및 레인보우 테이블 공격 방지.
  • IV 사용: 암호화 알고리즘에서 사용. 블록 암호의 첫 번째 블록을 무작위화하여 패턴 분석 방지 및 암호화 보안 강화.
 

 


ㅁ Salt 값

Salt는 주로 패스워드 해싱 및 키 유도 함수에서 사용되는 무작위 값입니다. Salt 값의 주요 목적은 동일한 입력 값(예: 동일한 패스워드)이 주어지더라도 항상 다른 해시나 키를 생성하도록 하는 것입니다.

Salt의 역할 및 중요성:

  1. 고유성 보장: 동일한 패스워드가 여러 번 해시되더라도 항상 다른 해시 값을 생성하여 데이터베이스에서 패스워드 해시의 중복을 방지합니다.
  2. 무작위성: 공격자가 미리 계산된 해시 테이블(레인보우 테이블)을 사용하여 해시 값을 역추적하지 못하도록 합니다.
  3. 브루트 포스 공격 방지: Salt 값이 추가되면 공격자가 각 패스워드를 개별적으로 해시해야 하므로 브루트 포스 공격이 더욱 어려워집니다.

 

ㅁ IV(Initialization Vector)

 IV 값은 암호화의 첫 번째 블록을 무작위화하여 동일한 데이터를 여러 번 암호화하더라도 다른 암호문을 생성하도록 합니다.  IV는 암호화 알고리즘에서 사용되는 초기화 값으로, 특히 블록 암호 모드(예: CBC, CFB, OFB)에서 사용됩니다.

IV의 역할 및 중요성:

  1. 무작위화: 동일한 평문이 동일한 키로 여러 번 암호화되더라도 서로 다른 암호문을 생성하여 패턴 분석을 어렵게 합니다.
  2. 보안 강화: 초기화 벡터는 암호화 작업의 시작을 임의로 만들어 공격자가 동일한 패턴을 찾기 어렵게 합니다.
  3. 예측 불가능성: 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())

 

 

예시 설명

  1. 키 생성 및 유도:
    • generate_encryption_key 함수는 암호학적으로 안전한 AES-256 키를 생성합니다.
    • generate_salt 함수는 예측 불가능한 Salt 값을 생성합니다.
    • derive_key 함수는 사용자의 비밀번호와 Salt를 사용하여 PBKDF2 알고리즘으로부터 키를 유도합니다.
  2. AES256 암호화 및 복호화:
    • encrypt 함수는 AES-256 암호화를 수행합니다. CBC 모드와 PKCS7 패딩을 사용합니다.
    • decrypt 함수는 AES-256 복호화를 수행합니다.
  3. 파일 저장 및 로드:
    • save_to_file 함수는 키, Salt, IV 및 암호화된 데이터를 파일에 저장합니다.
    • load_from_file 함수는 저장된 파일에서 데이터를 불러옵니다.
  4. 데이터 암호화 및 복호화:
    • 주어진 데이터를 AES-256으로 암호화하고, 파일에 저장한 후, 다시 불러와 복호화하여 원본 데이터를 확인합니다.
728x90
반응형