AES 암호화 모드와 대칭 키 알고리즘 완벽 가이드
암호화는 현대 디지털 보안의 초석입니다. 은행 계좌에 접속하거나, 보안 메시지를 보내거나, 클라우드에 민감한 데이터를 저장할 때 암호화 알고리즘은 정보를 보호하기 위해 보이지 않는 곳에서 끊임없이 작동합니다. 그중에서도 고급 암호화 표준(AES)은 세계에서 가장 널리 사용되고 신뢰받는 대칭 키 암호화 알고리즘입니다.
하지만 AES는 단순히 하나의 "블랙박스"가 아닙니다. AES를 어떻게 사용하느냐, 특히 어떤 암호화 모드를 선택하느냐는 알고리즘 자체만큼이나 중요합니다. 이 가이드에서는 AES 암호화 모드를 깊이 있게 살펴보고, 비교 분석하며, 다른 대칭 키 알고리즘을 탐구하고 프로젝트를 위한 보안 권장 사항을 제공합니다.
대칭 키 암호화란 무엇인가요?
AES의 세부 사항을 살펴보기 전에 대칭 키 암호화의 개념을 이해하는 것이 중요합니다. 대칭 키 알고리즘에서는 암호화(평문을 암호문으로 변환)와 복호화(암호문을 다시 평문으로 변환)에 동일한 키를 사용합니다.
이는 암호화에 공개 키를, 복호화에 개인 키를 사용하는 비대칭 키 암호화(예: RSA, ECC)와 다릅니다. 대칭 키 암호화는 훨씬 빠르고 효율적이어서 대량의 데이터를 암호화하는 데 이상적입니다.
AES(Advanced Encryption Standard)의 이해
AES는 5년간의 공모 과정을 거쳐 2001년 미국 국립표준기술연구소(NIST)에 의해 제정되었습니다. 노후화된 데이터 암호화 표준(DES)을 대체하기 위해 설계되었습니다.
AES는 블록 암호로, 데이터를 고정된 크기(128비트)의 블록 단위로 처리합니다. 128, 192, 256비트의 키 길이를 지원합니다. 알고리즘 자체는 매우 안전하지만, 여러 데이터 블록을 처리하는 방식인 **운영 모드(Mode of Operation)**에 따라 보안 취약점이 발생할 수 있습니다.
AES 암호화 모드 상세 분석
1. 전자 코드북(ECB, Electronic Codebook)
ECB는 가장 단순한 운영 모드입니다. 각 128비트 평문 블록이 동일한 키를 사용하여 독립적으로 암호화됩니다.
- 장점: 단순하고 빠르며 병렬 처리가 가능합니다.
- 단점: 대부분의 경우 보안성이 매우 낮습니다. 동일한 평문 블록이 항상 동일한 암호문 블록으로 변환되므로 데이터의 패턴이 그대로 드러납니다.
- "펭귄" 문제: ECB의 취약성을 보여주는 고전적인 예시는 펭귄 이미지를 암호화하는 것입니다. 암호화 후에도 암호문 속에 펭귄의 윤곽이 뚜렷하게 남아 있습니다.
- 결론: 단일 데이터 블록을 암호화하는 경우를 제외하고 ECB는 절대로 사용하지 마세요.
2. 암호 블록 체이닝(CBC, Cipher Block Chaining)
CBC는 블록을 "체이닝(연결)"하여 ECB의 단점을 개선합니다. 각 평문 블록은 암호화되기 전에 이전 암호문 블록과 배타적 논리합(XOR) 연산을 수행합니다. 첫 번째 블록에는 초기화 벡터(IV)가 사용됩니다.
- 장점: 평문의 패턴을 숨길 수 있습니다. 오랫동안 업계 표준으로 사용되었습니다.
- 단점: 순차적 처만 가능하여 병렬화가 불가능합니다. 적절한 메시지 인증 코드(MAC)와 함께 사용하지 않으면 패딩 오라클 공격에 취약합니다.
- 결론: 고유하고 예측 불가능한 IV 및 MAC(Encrypt-then-MAC)을 올바르게 사용하면 안전하지만, 현재는 일반적으로 GCM으로 대체되었습니다.
3. 카운터(CTR, Counter)
CTR 모드는 블록 암호를 스트림 암호처럼 작동하게 합니다. 연속된 카운터를 암호화하여 키스트림을 생성하고, 이를 평문과 XOR 연산합니다.
- 장점: 매우 효율적이며 완전한 병렬화를 지원하고 패딩이 필요 없습니다.
- 단점: 동일한 (Nonce + Counter)가 동일한 키와 함께 재사용되면 보안이 완전히 무너집니다. 기밀성은 제공하지만 무결성은 제공하지 않습니다.
- 결론: 고속 애플리케이션에 적합하지만, 반드시 HMAC과 같은 인증 메커니즘과 결합해야 합니다.
4. 갈로아/카운터 모드(GCM, Galois/Counter Mode)
GCM은 인증된 암호화(AEAD) 모드입니다. 암호화를 위한 CTR 모드와 인증을 위한 갈로아 필드 곱셈을 결합합니다.
- 장점: 기밀성과 무결성(인증)을 동시에 제공합니다. 매우 효율적이고 병렬화를 지원하며 많은 일반적인 공격에 내성이 있습니다. 암호화되지 않은 "연관 데이터"를 암호문과 함께 인증할 수도 있습니다.
- 단점: 처음부터 구현하기 복잡합니다. CTR과 마찬가지로 Nonce 재사용은 치명적입니다.
- 결론: 현대 암호화의 황금 표준. TLS 1.2+, SSH 등 거의 모든 애플리케이션에 강력히 권장됩니다.
5. CBC-MAC 기반 카운터 모드(CCM, Counter with CBC-MAC)
CCM은 CTR 암호화와 CBC-MAC 인증을 결합한 또 다른 AEAD 모드입니다.
- 장점: 암호화와 인증을 모두 제공합니다. WPA2 Wi-Fi 보안 및 블루투스 저전력(BLE)에서 주로 사용됩니다.
- 단점: 각 데이터 블록에 대해 두 번의 블록 암호 처리가 필요하므로 GCM보다 느립니다. 병렬 처리가 불가능합니다.
- 결론: GCM을 사용하기에 리소스가 제한적인 환경에 적합하지만, 일반적인 성능 면에서는 GCM이 선호됩니다.
비교표: AES 운영 모드
| 모드 | 유형 | 병렬화 가능? | 인증 제공? | 패딩 필요? | 최적의 용도 |
|---|---|---|---|---|---|
| ECB | 블록 | 예 | 아니요 | 예 | 단일 블록 전용 |
| CBC | 블록 | 아니요(암호화)/예(복호화) | 아니요 | 예 | 레거시 시스템 |
| CTR | 스트림 | 예 | 아니요 | 아니요 | 고속 스트리밍 |
| GCM | AEAD | 예 | 예 | 아니요 | 현대 웹/API 보안 |
| CCM | AEAD | 아니요 | 예 | 아니요 | IoT / 블루투스 / Wi-Fi |
기타 주목할 만한 대칭 키 알고리즘
AES가 주류이지만 다른 대칭 키 알고리즘들도 알아둘 가치가 있습니다.
- Blowfish: 1993년 브루스 슈나이어가 설계한 빠르고 공개된 블록 암호입니다. 안전하지만 현재는 후속작인 Twofish나 AES로 대체되었습니다.
- Camellia: 일본(NTT 및 미쓰비시)에서 개발된 블록 암호입니다. 보안과 성능 면에서 AES와 대등하며 ISO/IEC 표준입니다.
- SM4: 중국 국가 표준 무선 네트워크 암호 알고리즘입니다. 128비트 블록 크기와 128비트 키를 사용합니다.
- 3DES (Triple DES): DES를 세 번 적용하는 레거시 알고리즘입니다. 현재는 속도가 느리고 보안성이 낮아 AES로 교체되고 있습니다.
- RC4: 과거 SSL/TLS 및 WEP에서 널리 사용되었던 스트림 암호입니다. 현재는 취약한 것으로 간주되어 사용이 금지되었습니다.
보안 권장 사항: 왜 GCM을 선호하는가
현대 보안 환경에서 **인증된 암호화(AEAD)**는 선택이 아닌 필수입니다. 많은 개발자가 CBC나 CTR을 사용하면서 메시지 인증 코드(MAC)를 추가하는 것을 잊는 실수를 범합니다. 이는 데이터가 비트 플립 공격이나 패딩 오라클 공격에 노출되게 만듭니다.
GCM(Galois/Counter Mode)이 선호되는 이유:
- 효율성: 매우 빠르며 하드웨어(예: Intel AES-NI) 가속이 가능합니다.
- 인증: 암호문이 변조되었는지 감지할 수 있습니다.
- 패딩 불필요: 패딩을 사용하지 않아 구현이 단순해지고 패딩 관련 취약점을 방지합니다.
- 표준화: 안전한 인터넷 통신의 중추인 TLS 1.3의 기본 선택지입니다.
코드 예시
Node.js (내장 crypto 모듈 사용)
Node.js에서 AES-256-GCM을 구현하는 방법은 다음과 같습니다.
const crypto = require('crypto');
function encrypt(text, key) {
const iv = crypto.randomBytes(12); // GCM 표준 IV 크기는 12바이트입니다.
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return {
iv: iv.toString('hex'),
content: encrypted,
tag: authTag
};
}
function decrypt(encryptedObj, key) {
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
Buffer.from(encryptedObj.iv, 'hex')
);
decipher.setAuthTag(Buffer.from(encryptedObj.tag, 'hex'));
let decrypted = decipher.update(encryptedObj.content, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// 사용 예시
const key = crypto.randomBytes(32); // 256비트 키
const data = encrypt("Hello Security World!", key);
console.log("암호화된 데이터:", data.content);
console.log("복호화된 데이터:", decrypt(data, key));
자주 묻는 질문(FAQ)
1. 초기화 벡터(IV)를 재사용해도 되나요?
아니요. CTR 또는 GCM 모드에서 동일한 키로 IV를 재사용하면 공격자가 두 암호문을 XOR 연산하여 평문을 복구할 수 있습니다. CBC에서는 메시지 시작 부분에 대한 정보가 누설될 수 있습니다. 암호화할 때마다 항상 고유한 IV를 생성하세요.
2. AES-256이 AES-128보다 훨씬 안전한가요?
둘 다 매우 안전합니다. AES-128은 현재 기술로 무차별 대입 공격이 거의 불가능합니다. AES-256은 양자 컴퓨팅과 같은 미래의 위협에 대해 더 높은 보안 마진을 제공하지만 속도가 약간 느립니다. 대부분의 상업적 용도에는 AES-128로도 충분합니다.
3. 왜 똑같은 입력값인데 암호화 결과가 항상 같나요?
ECB 모드를 사용 중이거나 고정된 IV를 사용하고 있을 가능성이 큽니다. 이는 심각한 보안 위험입니다. GCM 또는 CBC 모드를 사용하고 매번 새로운 랜덤 IV를 생성하는지 확인하세요.
4. GCM의 인증 태그(Auth Tag)를 분실하면 어떻게 되나요?
복호화에 실패합니다. 인증 태그는 데이터가 변조되지 않았음을 보장합니다. 태그가 없으면 데이터 무결성을 검증할 수 없으며, 대부분의 암호화 라이브러리는 final() 호출 시 오류를 발생시킵니다.
결론
적절한 AES 모드를 선택하는 것은 보안, 성능, 호환성 사이의 균형을 맞추는 일입니다. 현대적인 웹 애플리케이션의 경우 AES-GCM이 거의 항상 최선의 선택입니다. 기밀성, 무결성, 인증성이라는 암호학의 핵심 요소를 모두 제공하기 때문입니다.
ECB와 같은 구식 모드를 피하고 IV 관리에 주의를 기울임으로써 사용자 데이터를 안전하게 보호할 수 있습니다.