AEAD와 Nonce: AES-GCM·ChaCha20-Poly1305를 안전하게 쓰는 조건

1장 개념과 보호 목표#

AEAD는 암호화와 메시지 인증을 함께 제공하며 암호화하지 않는 부가 정보(AAD)까지 인증할 수 있습니다. AES-GCM과 ChaCha20-Poly1305가 대표적인 예입니다. 수신자는 인증 태그를 검증한 후에만 평문을 신뢰해야 합니다.


2장 원리와 구분#

Nonce는 비밀일 필요가 없지만 동일 키 아래에서 재사용되지 않도록 관리해야 합니다. ChaCha20은 키스트림을 만들고 Poly1305는 인증 태그를 계산하므로 두 역할을 구분합니다. GCM의 Nonce 재사용은 평문 관계 노출과 인증 위조 위험을 초래합니다. 재시작·복제·병렬 작업까지 포함한 생성 전략이 필요합니다.


3장 비교와 판단 기준#

항목 역할 관리 조건
키 암호화·인증의 비밀 접근 분리·사용 한도
Nonce 메시지별 연산 구분 알고리즘별 유일성 조건
AAD 암호화하지 않는 문맥 인증 양쪽에서 동일한 직렬화
태그 변조·잘못된 키 탐지 검증 성공 후 평문 사용

4장 암호화만으로 금액 변조를 막을 수 있을까#

문서의 내용을 숨기는 것과 그 문서가 바뀌지 않았는지를 확인하는 것은 다른 목표입니다. 어떤 암호 방식은 암호문을 읽지 못하는 상대도 암호문의 일부를 바꿔 복호화 결과에 영향을 줄 수 있습니다. 애플리케이션이 복호화에 성공했다는 이유만으로 금액·권한·파일 내용을 받아들이면 위험한 상태가 됩니다.

AEAD는 이런 요구를 함께 처리하는 인터페이스입니다. 허용한 키와 입력으로 만든 암호문인지 확인하고, 검증에 성공한 결과만 전달합니다. 이때 인증은 같은 비밀키를 아는 상대의 메시지를 검증하는 의미이며 사람의 실명이나 업무 승인까지 증명하는 것은 아닙니다.


5장 AES-GCM과 ChaCha20-Poly1305의 결합 구조#

AES-GCM은 AES 기반 암호화와 GCM의 인증 계산을 결합합니다. ChaCha20-Poly1305는 ChaCha20의 키스트림 암호화와 Poly1305 인증을 결합합니다. 내부 구조는 다르지만 사용자에게는 키·Nonce·평문·AAD를 받아 암호문·태그를 만드는 인증 암호화의 형태로 보입니다.

하드웨어 AES 지원, 소프트웨어 구현 성능, 프로토콜 호환성과 라이브러리의 안전한 API를 함께 비교합니다. 암호 알고리즘만 골라 두 구성 요소를 직접 조립하기보다 이미 검증된 AEAD 구현을 사용해야 입력 형식·태그 검증·실패 처리에서의 실수를 줄일 수 있습니다.

flowchart TB
 K["비밀키"] --> E["인증 암호화"]
 N["이번 메시지의 Nonce"] --> E
 P["숨길 평문"] --> E
 A["숨기지 않을 AAD"] --> E
 E --> C["암호문"]
 E --> T["인증 태그"]
 C --> S["암호문과 필요한 메타데이터 저장"]
 T --> S

6장 AAD는 왜 암호화하지 않고 인증할까#

파일 서버가 문서 ID와 형식 버전을 읽어 처리 경로를 결정한다고 가정합니다. 이 정보까지 숨기면 복호화 이전에 형식을 고르기 어렵습니다. 반대로 아무 보호 없이 두면 공격자가 다른 문서 ID로 바꾸거나 형식을 속일 수 있습니다. AAD는 읽을 수 있게 두면서 암호문과 함께 변경을 검출하는 방법입니다.

AAD가 사용자에게 보인다는 사실을 전제로 개인정보나 비밀을 넣을지 판단합니다. 같은 내용을 JSON으로 만들더라도 필드 순서·공백·숫자 표현이 달라지면 인증 입력이 달라질 수 있으므로 바이트 구성 규칙을 고정해야 합니다.


7장 태그가 틀리면 평문도 폐기해야 하는 이유#

복호화 라이브러리는 최종 검증 전에 내부적으로 일부 평문을 계산할 수 있습니다. 그러나 태그가 실패한 데이터는 공격자가 바꾸었거나 키·문맥이 맞지 않는 데이터일 수 있습니다. 계산된 값이 그럴듯하다고 일부 문장을 반환하거나 금액 처리를 진행하면 인증의 경계를 넘어선 것입니다.

안전한 상위 API는 인증 성공과 결과 전달을 하나의 작업으로 취급하도록 구성합니다. 실패 응답은 정상 빈 문서와도 구분해야 합니다. 내부에는 조사 가능한 사건 식별자를 남기되 사용자에게 키나 암호문 내부 상태를 그대로 노출하지 않습니다.

좋은 흐름
암호문 읽기 → 메타데이터 확인 → 인증 복호화 → 성공 → 전체 평문 전달

위험한 흐름
일부 평문 계산 → 미리 업무 처리 → 나중에 태그 실패 → 이미 처리한 행위가 남음

8장 Nonce 재사용을 XOR 관계로 이해하기#

키스트림 암호화 부분을 단순화하면 C1=P1 XOR S1입니다. 동일 키와 동일 Nonce 때문에 같은 키스트림 S를 두 번 사용하면 C1=P1 XOR S, C2=P2 XOR S가 됩니다. 두 암호문을 XOR한 값은 P1 XOR P2가 되어 평문 간의 관계가 드러납니다. 이는 내용을 알아야만 암호문을 공격할 수 있다는 생각이 틀릴 수 있음을 보여 줍니다.

GCM에서는 기밀성의 문제 외에 인증 구조에도 위험이 생길 수 있습니다. 따라서 재사용이 확인되면 단지 다음 Nonce를 바꾸고 끝내기보다 해당 키의 사용 중단·교체와 이미 처리한 메시지의 영향을 조사해야 합니다. 이 수식은 키스트림 관계를 설명하는 예시이며 실제 인증 계산 전체를 대신하지 않습니다.


9장 랜덤 Nonce와 카운터 Nonce의 선택#

무작위 생성은 노드 간 조정이 적지만 충돌 확률과 키별 사용량을 관리해야 합니다. 카운터는 중복을 피하기 쉬울 수 있지만 저장 상태·동시 증가·재시작·백업 복원의 문제를 해결해야 합니다. 어느 방식을 선택하든 해당 알고리즘이 요구하는 길이·형식·사용 한도를 먼저 맞춥니다.

방식 편리한 점 운영에서 실패할 수 있는 조건
안전한 무작위 생성 여러 요청에서 생성하기 쉬움 생성기 결함·충돌·사용량 초과
지속적인 카운터 중복 여부를 관리하기 쉬움 재시작·복원·증가 경쟁
노드 구간과 카운터 결합 노드별 생성 영역 분리 노드 ID 중복·구간 변경

10장 재시작과 백업 복원이 위험해지는 순간#

서버 A가 키 K로 카운터 1000까지 사용한 뒤 백업 상태 800으로 복원되면 이미 사용한 번호를 다시 생성할 수 있습니다. 키는 그대로인데 카운터만 되돌아가므로 정상적으로 암호화가 완료되어도 암호 사용 조건은 깨집니다. 가상머신 복제나 장애 전환에서도 같은 상황을 확인해야 합니다.

상태 저장과 키 버전의 관계, 복구 시 새 키 전환, 노드별 할당을 설계하고 실제 복원 시험에서 반복이 없는지 봅니다. 보안 검토는 정상 운영의 생성 코드뿐 아니라 복구 절차의 상태 이동까지 포함합니다.

flowchart LR
 A["키 K와 카운터 1000"] --> B["옛 상태 800으로 복원"]
 B --> C["키 K로 801부터 다시 사용"]
 C --> D["이미 사용한 Nonce와 중복"]
 D --> E["키 교체와 영향 조사 필요"]

11장 암호문 저장 형식을 먼저 정의하기#

복호화하려면 암호문 외에 필요한 Nonce·태그·AAD 구성·키 식별자가 있어야 합니다. 키 재료 자체를 암호문 옆에 평문으로 저장하는 일과 키 ID를 저장하는 일은 다릅니다. 형식 버전을 두면 이후 알고리즘 전환과 읽기 호환성을 설명할 수 있습니다.

형식 버전 | 허용된 알고리즘 ID | 키 ID
Nonce | AAD 구성에 필요한 공개 메타데이터
암호문 | 인증 태그

입력의 알고리즘 ID가 임의의 약한 모드를 선택하게 해서는 안 됩니다. 서버가 허용 정책과 길이 상한을 검증한 뒤 정해진 구현으로 처리합니다. 지원하지 않는 형식은 추측해 복원하기보다 명시적으로 실패시키는 편이 안전합니다.


12장 대용량 파일은 청크 순서까지 보호한다#

파일을 여러 청크로 나누면 청크마다 다른 Nonce를 사용하고 파일 ID·청크 번호·전체 구조를 인증하는 규약이 필요합니다. 각 청크의 태그가 맞아도 청크를 바꾸거나 마지막 부분을 잘라 내는 행위를 전체 파일의 완결성 검증 없이 놓칠 수 있습니다.

검증된 스트리밍 암호 형식을 사용하고 청크 재배열·중복·누락·잘린 파일을 시험합니다. 직접 만든 분할 규칙으로 단순히 GCM을 반복 호출하는 것과 완결성을 포함한 파일 보호 형식은 다릅니다.


13장 키 교체에서 새 쓰기와 옛 읽기를 분리한다#

새 키를 사용하기 시작해도 기존 데이터는 이전 키와 메타데이터로 읽어야 할 수 있습니다. 새 데이터의 키 ID, 옛 키의 복호화 권한, 데이터 재암호화와 백업 보존을 각각 정합니다. 키 교체가 기존 암호문의 Nonce 재사용 문제를 자동으로 되돌리는 것은 아닙니다.

폐기 전에는 필요한 과거 데이터를 실제로 복원하고 기존 키에 의존하는 사본을 조사합니다. 사고에 따른 긴급 교체와 계획된 정기 교체의 검증 범위도 나누어 기록합니다.


14장 변조 검증 시나리오를 준비하기#

시험 입력 기대 결과 확인할 부가 조건
암호문 한 바이트 변경 인증 실패 부분 평문 사용 없음
다른 문서 ID의 AAD 인증 실패 문맥을 임의로 보정하지 않음
다른 키 버전 복호화 거부 내부 비밀의 외부 노출 없음
태그 누락·길이 변경 입력 거부 기본 태그로 대체하지 않음
파일 청크 누락 완결성 검증 실패 성공 파일로 등록하지 않음

정상 복호화 시험과 실패 시험을 같은 데이터 형식으로 수행합니다. 재시작·동시 요청·키 교체·백업 복원은 Nonce 관리 시험에 포함합니다. 검증 결과에는 데이터 내용보다 사용 조건과 상태의 일치 여부를 남깁니다.


15장 적용 사례와 운영 방법#

여러 서버가 같은 키를 공유한다면 노드별 공간 분리나 중앙 할당 등 충돌을 방지하는 설계를 검토합니다. 랜덤 Nonce도 무제한 사용하면 충돌 확률이 누적되므로 키별 사용 한도를 정해야 합니다. 파일 ID나 버전을 AAD에 넣으면 암호문을 다른 문맥으로 옮기는 공격을 탐지하는 데 도움이 됩니다.


16장 AEAD 암호화와 검증#

flowchart LR
 P["평문"] --> E["AEAD 암호화"]
 K["비밀키·Nonce·AAD"] --> E
 E --> C["암호문·태그"]
 C --> V["AEAD 복호화·검증"]
 K --> V
 V -->|"검증 성공"| R["평문 사용"]
 V -->|"검증 실패"| X["처리 중단"]

17장 AEAD가 보호하는 세 가지 입력#

AEAD에 들어가는 값은 평문, Nonce, AAD입니다. 평문은 암호화되지만 AAD(Associated Authenticated Data)는 숨겨지지 않고 인증만 받습니다. 파일 버전이나 레코드 ID를 AAD에 넣으면 암호문을 다른 문맥으로 옮기는 행위를 검출하는 데 활용할 수 있습니다. 다만 읽는 쪽도 동일한 AAD를 구성해야 하며, 권한 검사는 별도로 수행해야 합니다.

복호화는 태그 검증에 성공한 경우에만 평문을 업무 처리에 넘겨야 합니다. 태그가 틀린 데이터를 일부 복원해 미리 사용하거나, 실패를 빈 문자열로 바꿔 정상 값처럼 처리하면 인증의 의미가 사라집니다. 암호문과 AAD를 각각 한 바이트 바꾼 시험에서 모두 처리가 거부되는지 확인하는 것이 좋은 출발점입니다.


18장 분산 서버에서 Nonce를 관리하는 사례#

서버마다 카운터를 0부터 시작하면 같은 키를 쓰는 여러 서버가 같은 Nonce를 만들 수 있습니다. 재시작·백업 복원·가상머신 복제로 카운터가 되돌아가는 경우도 조사해야 합니다. 키별 유일성을 보장하는 분배 구조 또는 검증된 라이브러리의 생성·사용량 관리 방식을 선택하고, Nonce 길이와 메시지 한도는 해당 알고리즘 사양에 맞춥니다. AES-GCM과 ChaCha20-Poly1305에서 동일 키의 Nonce 재사용은 심각한 위험입니다.

키 ID, Nonce, 암호문, 태그, AAD 구성 버전을 저장 형식에 명시하면 키 교체와 장애 복구가 쉬워집니다. Nonce 자체를 숨기는 것보다 재사용을 방지하고 형식을 정확히 복원하는 일이 우선입니다.


19장 적용 전 확인할 사항#

  • 키별 Nonce 사용량과 재시작 동작을 점검한다
  • AAD의 직렬화와 버전 규칙을 명확히 한다
  • 태그 검증 실패를 정상 오류 경로로 처리한다

20장 자주 묻는 질문#

Nonce 재사용 방지형 모드면 관리를 생략해도 되나요?#

AES-GCM-SIV처럼 오용 저항성을 높이는 방식도 사용 한도와 반복 정보 노출 등의 조건이 있습니다. 라이브러리와 프로토콜이 요구하는 Nonce 정책을 따라야 합니다.

AAD에 사용자 ID를 넣으면 접근통제도 해결되나요?#

AAD는 암호문과 문맥의 변조를 검출합니다. 현재 사용자가 해당 데이터를 읽을 권한이 있는지는 서버가 별도로 판단해야 합니다. 사용자 ID를 신뢰할 수 있는 값에서 구성하는지도 확인해야 합니다.

Nonce를 무작위로 만들면 중복은 절대로 없나요?#

무작위 생성에도 충돌 확률이 있습니다. 길이·키별 사용량·생성기 품질을 함께 고려하고 알고리즘과 라이브러리가 요구하는 사용 한도를 지켜야 합니다.


함께 읽기#