본문 바로가기
클라우드

🔑 키 교체(Key Rotation)하면 데이터를 전부 다시 암호화할까? — 클라우드 KMS의 진실

by gasbugs 2026. 3. 27.
반응형

"키를 주기적으로 교체하라"는 말, 듣기엔 간단한데… 테라바이트짜리 데이터를 전부 다시 암호화한다는 말인가요? 😱

 

 

🎯 이 글에서 다루는 것

  • 클라우드 KMS에서 "키 교체"가 실제로 의미하는 것
  • 봉투 암호화(Envelope Encryption) 개념 — 이걸 모르면 키 교체를 절대 이해 못 함
  • AWS KMS vs Azure Key Vault의 키 교체 동작 비교
  • 직접 구현한 키(BYOK/CMK)를 교체할 때 주의할 점
  • 서비스마다 동작이 다른 이유

 


📌 도입 / 배경

클라우드 보안 가이드를 보다 보면 꼭 나오는 문장이 있습니다.

"암호화 키는 1년마다 주기적으로 교체(Rotation)하세요."

 

처음 이 가이드를 보는 분들이 자연스럽게 드는 의문이 있습니다.

 

"그러면 기존에 암호화된 데이터를 전부 새 키로 다시 암호화해야 하나요? S3에 100TB 쌓여있는데 그걸 다 돌려야 한다는 뜻인가요?"

 

결론부터 말하면, 대부분의 경우 그렇지 않습니다. 이유는 클라우드 KMS가 봉투 암호화(Envelope Encryption) 라는 구조를 사용하기 때문입니다. 이 개념을 이해하면 키 교체가 왜 가볍고 빠른 작업인지 즉시 납득됩니다.


🔍 핵심 개념: 봉투 암호화(Envelope Encryption)

키가 두 계층이다.

클라우드 KMS는 키를 단 하나만 쓰는 구조가 아닙니다. 두 개의 계층으로 나뉩니다.

[ 실제 데이터 ]
       ↑ 암호화
[ DEK: Data Encryption Key ]   ← 실제 데이터를 암호화하는 키
       ↑ 암호화 (wrapping)
[ KEK: Key Encryption Key ]    ← DEK를 암호화하는 키 (KMS가 관리)

이를 도식으로 표현하면 이렇습니다.

  • DEK (Data Encryption Key): 실제 데이터를 암호화하는 키입니다. 보통 AES-256 대칭키입니다.
  • KEK (Key Encryption Key): DEK 자체를 암호화(wrap)해서 보호하는 키입니다. KMS, Key Vault 같은 서비스가 관리합니다.

스토리지에 저장되는 것은 암호화된 DEK + 암호화된 데이터입니다. KEK는 KMS 내부에만 존재하고 외부로 나오지 않습니다.

 

"봉투"라는 비유

편지를 쓴다고 생각해봅시다.

  1. 편지 내용(데이터)을 작성합니다.
  2. 편지를 봉투(DEK)에 넣어 밀봉합니다.
  3. 봉투를 또 다른 안전한 금고(KEK)에 넣어 잠급니다.

키 교체는 금고의 잠금장치(KEK)만 교체하는 것입니다. 봉투와 편지 내용은 그대로입니다.


🔍 키 교체 시 실제로 일어나는 일

AWS KMS — 자동 키 교체(Automatic Rotation)

AWS KMS에서 CMK(Customer Managed Key)의 자동 교체를 활성화하면 어떻게 될까요?

# AWS CLI로 키 자동 교체 활성화
aws kms enable-key-rotation \
  --key-id arn:aws:kms:ap-northeast-2:123456789012:key/abcd-1234-...

 

활성화하면 AWS는 1년마다 새로운 키 재료(key material)를 생성합니다. 이때 중요한 점:

  • 기존에 이 키로 암호화된 데이터는 자동으로 다시 암호화되지 않습니다.
  • 기존 데이터는 과거 버전의 키 재료로 계속 복호화할 수 있습니다. AWS가 이전 버전을 내부적으로 유지합니다.
  • 신규 암호화 요청부터 새 키 재료가 사용됩니다.
# boto3 예시: KMS로 데이터 암호화
import boto3

kms = boto3.client('kms', region_name='ap-northeast-2')

# 암호화: KMS가 DEK를 생성하고, KEK(CMK)로 DEK를 wrap
response = kms.generate_data_key(
    KeyId='arn:aws:kms:ap-northeast-2:123456789012:key/abcd-1234-...',
    KeySpec='AES_256'
)

plaintext_dek = response['Plaintext']      # 실제 암호화에 쓰는 DEK (메모리에서만 사용)
encrypted_dek = response['CiphertextBlob'] # 저장할 암호화된 DEK

# 이후 plaintext_dek로 실제 데이터를 AES 암호화
# plaintext_dek는 메모리에서 즉시 삭제
# encrypted_dek + 암호화된 데이터를 함께 저장

 

복호화할 때는:

# 복호화: 저장된 encrypted_dek를 KMS로 보내 plaintext_dek를 얻음
decrypt_response = kms.decrypt(
    CiphertextBlob=encrypted_dek
    # KeyId 명시 불필요: AWS가 어느 버전 키로 암호화됐는지 내부적으로 알고 있음
)
plaintext_dek = decrypt_response['Plaintext']
# plaintext_dek로 데이터를 복호화

 

AWS KMS는 CiphertextBlob 내부에 어느 키 버전으로 암호화됐는지 메타데이터가 담겨 있어서, 교체 후에도 이전 데이터를 문제없이 복호화할 수 있습니다.

Azure Key Vault — 키 버전(Key Version) 방식

Azure Key Vault는 AWS KMS와 달리 버전(Version) 으로 키를 관리합니다.

# Azure CLI로 새 버전의 키 생성 (= 키 교체)
az keyvault key create \
  --vault-name myVault \
  --name myEncryptionKey \
  --kty RSA \
  --size 2048
# 이 명령 실행 시 새 버전이 생성되고 자동으로 "current" 버전이 됨

# 현재 키의 모든 버전 확인
az keyvault key list-versions \
  --vault-name myVault \
  --name myEncryptionKey

 

버전이 교체되면:

  • 이전 버전 키: disabled 처리 가능하지만, 기존 데이터 복호화를 위해 보통 enabled 유지
  • 신규 암호화: 새 버전 키 사용
  • 기존 데이터: 재암호화 없음 (이전 버전으로 복호화 가능)
# 특정 버전으로 암호화
az keyvault key encrypt \
  --vault-name myVault \
  --name myEncryptionKey \
  --version <old-version-id> \  # 구버전으로도 복호화 가능
  --algorithm RSA-OAEP \
  --value "base64-encoded-data"

🔍 서비스마다 다른가요?

맞습니다. 키 교체 시 동작은 서비스와 구현 방식에 따라 세 가지 경우로 나뉩니다.

케이스 1: 완전 자동 — 데이터 재암호화 없음 (가장 일반적)

KMS/Key Vault에서 관리하는 봉투 암호화 기반 서비스들입니다.

서비스 키  교체 동작
AWS S3 SSE-KMS KEK만 교체, 데이터 재암호화 없음
AWS EBS 볼륨 암호화 KEK만 교체, 기존 볼륨 재암호화 없음
Azure Blob Storage (CMK) 새 키 버전 지정, 자동으로 DEK 재래핑
Azure SQL Database TDE 새 보호기 키 지정, 데이터 재암호화 없음

케이스 2: 자동 DEK 재래핑 — 데이터 재암호화 없음

Azure Storage, Azure Disk Encryption 등 일부 서비스는 KEK 교체 시 저장된 DEK를 새 KEK로 자동 재래핑합니다. DEK 자체는 바뀌지 않으므로 데이터 재암호화는 없습니다.

[이전] 데이터 ← DEK ← KEK(v1)
[이후] 데이터 ← DEK ← KEK(v2)  ← DEK가 새 KEK로 재래핑됨
       (데이터는 동일)

케이스 3: 완전 재암호화 — 드물지만 존재

직접 키를 앱에서 관리하거나, 특정 데이터베이스에서 마스터 키를 교체하는 경우입니다.

# 앱에서 직접 키 관리 시 재암호화가 필요한 패턴
def rotate_dek(data_store, old_key, new_key):
    """
    앱이 직접 DEK를 관리할 경우, 기존 데이터를 모두 재암호화해야 함
    → 봉투 암호화를 쓰지 않는 경우의 안티패턴
    """
    for record in data_store.all():
        plaintext = aes_decrypt(record.ciphertext, old_key)  # 구 키로 복호화
        record.ciphertext = aes_encrypt(plaintext, new_key)  # 신 키로 재암호화
        data_store.save(record)

이런 경우는 봉투 암호화를 사용하지 않는 잘못된 설계이거나, 의도적으로 데이터 자체의 암호화 키를 바꿔야 하는 경우입니다. 클라우드 매니지드 서비스를 올바르게 쓰면 이 상황은 거의 발생하지 않습니다.


⚠️ 주의사항 / 흔한 실수

🚨 BYOK(Bring Your Own Key) 교체 시 이전 버전 키를 너무 빨리 삭제하면 안 됩니다.

가장 많이 발생하는 실수입니다. 새 키로 교체했다고 이전 키를 삭제하면, 이전 키로 암호화된 DEK를 복호화할 수 없어서 기존 데이터에 영구 접근 불가 상태가 됩니다.

# AWS KMS: 키 삭제는 7~30일 대기 기간 존재 (의도적 안전장치)
aws kms schedule-key-deletion \
  --key-id <old-key-id> \
  --pending-window-in-days 30  # 최소 7일, 최대 30일

# Azure Key Vault: soft-delete + purge protection 활성화 권장
az keyvault update \
  --name myVault \
  --enable-soft-delete true \
  --enable-purge-protection true

 

🚨 키 교체 ≠ 데이터 보안 수준 즉각 향상

키 교체는 키가 유출됐을 경우의 피해 범위를 줄이는 것이지, 이미 유출된 키로 복호화된 데이터를 다시 보호하진 않습니다. 유출이 의심되면 키 교체만으로는 부족하고, 해당 키로 접근 가능했던 데이터 범위 자체를 점검해야 합니다.

 

🚨 앱 측에서 키 버전을 하드코딩하지 마세요.

# 나쁜 예: 특정 버전 하드코딩
KEY_ID = "arn:aws:kms:...:key/abcd-1234"
KEY_VERSION = "version-2023-01"  # 교체 후 앱 코드 수정 필요 → 위험

# 좋은 예: alias 사용 (AWS), latest version 자동 참조 (Azure)
KEY_ID = "arn:aws:kms:ap-northeast-2:123456789012:alias/my-app-key"
# alias는 항상 current key를 가리킴

✅ 정리 / 마무리

질문
키 교체 시 기존 데이터 전부 재암호화? ❌ 대부분 불필요
교체 후 기존 데이터 복호화 가능? ✅ 구 키 버전이 유지되므로 가능
교체 후 신규 데이터는? ✅ 새 KEK 사용
서비스마다 다른가? ✅ 동작 방식 차이 있음 (재래핑 여부 등)
앱이 직접 키 관리 시? ⚠️ 재암호화 필요할 수 있음

핵심을 한 줄로 정리하면 이렇습니다.

봉투 암호화 구조에서 키 교체는 DEK를 감싼 KEK만 교체하는 것이며, 실제 데이터 암호화에 쓰인 DEK와 데이터 자체는 건드리지 않는다.

 

클라우드 관리형 서비스(S3, EBS, Azure Blob 등)를 올바르게 사용하고 있다면 키 교체는 가볍고 안전한 작업입니다. 데이터를 전부 다시 암호화해야 한다는 두려움은 봉투 암호화를 이해하면 사라집니다.

 

심화 학습 방향으로는 HSM(Hardware Security Module), FIPS 140-2/3 준수 키 스토어, 그리고 멀티 리전 키 복제 전략을 추천합니다.

 

반응형