AES-GCM 암복호화 (키·논스·AAD)
브라우저에서 AES-GCM으로 암복호화합니다. hex 키와 논스, 선택적 AAD, 태그 길이 선택, 그리고 암호문과 태그를 분리해 보여 줍니다.
사용법
- 암호화와 복호화 중 하나를 고르고 키를 hex로 넣으세요. AES-128은 16바이트, AES-256은 32바이트입니다. 버튼 두 개는 브라우저 CSPRNG에서 새 키를 뽑아 줍니다.
- 논스를 넣으세요. 암호화할 때마다 96비트 버튼을 눌러 새 값을 쓰는 것이 좋습니다. 96비트가 아닌 길이를 붙여 넣으면 경고가 뜨고, 같은 조합을 재사용하면 빨간 경고가 나옵니다.
- 반대편이 추가 인증 데이터를 쓴다면 함께 넣으세요. 인증은 되지만 암호화는 되지 않으며, 복호화 때 바이트 단위로 일치해야 태그 검사를 통과합니다.
- 실행하세요. 암호화는 암호문과 태그를 따로, 그리고 이어 붙인 형태를 hex와 base64로 줍니다. 복호화는 둘을 받거나, 태그 칸을 비워 두면 스스로 잘라 냅니다.
자세한 설명
펼치기접기
AES-GCM은 지금 거의 모든 곳이 쓰는 인증 암호 모드이고, 딱 한 가지 점에서 가차 없습니다. 같은 키와 같은 논스로 서로 다른 두 메시지를 절대 암호화하지 않는 한에서만 안전합니다. 한 번이라도 그러면 두 암호문의 XOR이 두 평문의 XOR이 되므로 한쪽 메시지를 알면 다른 쪽이 그대로 넘어갑니다. 더 나쁜 것은 인증 서브키가 새어 나가, 공격자가 보낸 적 없는 메시지에 유효한 태그를 붙일 수 있게 된다는 점입니다. 이 페이지는 암호화에 쓴 키·논스 조합을 기억해 두고 같은 조합이 반복되면 빨간 글씨로 알려 줍니다. 출력만 봐서는 아무것도 이상해 보이지 않기 때문입니다.
또 하나, Web Crypto API가 굳이 붙여 놓는 두 조각을 여기서는 떼어 줍니다. crypto.subtle.encrypt는 태그가 뒤에 붙은 하나의 버퍼를 돌려주지만, 문제의 반대편에 있는 거의 모든 라이브러리와 전송 형식은 암호문과 태그를 각각의 필드로 원합니다. 여기서는 둘 다 나오고, 이어 붙인 형태도 hex와 base64로 함께 나옵니다.
감추지 않고 드러내는 세부 세 가지. 논스는 96비트여야 합니다. GCM은 비어 있지 않은 어떤 길이든 받지만 그대로 쓰이는 것은 96비트뿐이고, 다른 길이는 먼저 96비트로 해시되므로 더 느리기만 합니다. 태그는 128, 120, 112, 104, 96, 64, 32비트 중 하나여야 하고 그 밖의 값은 안 됩니다. 48은 브라우저가 바로 거부합니다. 그리고 AES-192는 아예 동작하지 않습니다. Chromium은 24바이트 키에 OperationError: 192-bit AES keys are not supported로 답합니다. 이는 AES의 한계가 아니라 Chromium의 결정이고, 이 페이지는 조용히 대체하지 않고 브라우저가 말한 그대로 보고합니다.
페이지를 벗어나지 않고 알고리즘 명세와 대조할 수도 있습니다. 키를 0 서른두 개, 논스를 0 스물네 개로 두고 아무것도 암호화하지 마세요. 태그가 58e2fccefa7e3061367f1d57a4e7455a로 나오는데, 이는 최초 GCM 제안서의 테스트 케이스 1입니다. 같은 키와 논스로 0 바이트 열여섯 개를 암호화하면 암호문은 0388dace60b6a392f328c2b971b2fe78, 태그는 ab6e47d42cec13bdf53a67b21257bddf입니다. 256비트 0 키로 빈 메시지를 처리하면 530f8afbc74536b9a963b4f1c4cb738b이 나옵니다.
복호화 실패는 실패했다는 사실 외에 아무것도 알려 주지 않는데, 이는 이 페이지의 결함이 아니라 올바른 동작입니다. 틀린 태그와 틀린 추가 데이터를 구분해 주는 복호기는 공격자가 수천 번 물어볼 수 있는 오라클이 됩니다. 모든 계산은 Web Crypto API를 통해 브라우저에서 이뤄지고, 키·논스·메시지는 어디로도 전송되지 않습니다.
자주 묻는 질문
논스를 재사용하면 실제로 무슨 일이 벌어지나요?
두 가지가 벌어지고 두 번째가 더 나쁩니다. 키스트림이 반복되므로 C1 XOR C2가 P1 XOR P2와 같아집니다. 평문 하나를 알면 나머지가 바로 나오고, 하나도 몰라도 영문이나 JSON이라면 XOR만으로 복원되는 경우가 많습니다. 그다음, 반복은 GCM의 인증 서브키 H를 노출시켜 위조를 불가능에서 단순 계산으로 바꿔 놓습니다. 공격자가 당신이 쓴 적 없는 메시지에 유효한 태그를 만들어 낼 수 있습니다. GCM에서 조심해야 할 것이 키가 아니라 논스인 이유가 이것입니다.
여기서 암호문과 태그를 왜 따로 보여 주나요?
Web Crypto API는 둘을 붙이고 다른 대부분은 그렇지 않기 때문입니다. crypto.subtle.encrypt는 암호문 뒤에 태그를 붙여 돌려주므로, 21바이트 메시지에 128비트 태그를 쓰면 37바이트가 돌아옵니다. Go, Java, OpenSSL 명령줄, JWE, 그리고 대부분의 프로토콜 형식은 태그를 별도 필드로 다룹니다. 이 페이지는 두 조각과 이어 붙인 형태를 모두 보여 주므로 반대편 형식에 맞춰 쓸 수 있습니다.
논스는 난수가 좋나요, 카운터가 좋나요?
해당 키에서 절대 반복되지 않는다면 어느 쪽이든 됩니다. 암호화하는 주체를 전부 통제한다면 카운터가 더 안전합니다. 난수에는 생일 한계가 있기 때문입니다. 96비트 난수 논스라면 한 키로 2^32개 메시지를 처리했을 때 두 개가 충돌할 확률이 대략 86억 분의 1에 이르고, 개수의 제곱으로 커집니다. NIST SP 800-38D가 난수 논스를 한 키당 2^32개로 제한하는 이유입니다. 카운터에는 그런 한계가 없지만, 두 기계가 키를 공유하면서 둘 다 0에서 시작하는 순간 무너집니다.
AES-192를 쓸 수 있나요?
Chromium에서는 안 되고, 따라서 Chrome과 Edge에서도 안 됩니다. 24바이트 키는 OperationError: 192-bit AES keys are not supported를 냅니다. 제약은 알고리즘이 아니라 브라우저 구현에 있습니다. OpenSSL과 Java는 AES-192를 잘 처리하고, Firefox와 Safari는 시기에 따라 동작이 달랐습니다. 브라우저 간 상호 운용성이 필요하면 128이나 256을 쓰세요.
복호화가 왜 무엇이 틀렸는지 말해 주지 않나요?
의도된 것입니다. 태그 검사는 통과하거나 실패할 뿐이고, 어느 입력이 틀렸는지 알려 주는 복호기는 공격자가 계속 찔러 볼 수 있게 만듭니다. 패딩 오라클류 공격이 바로 실패를 구분해 주는 서버로 만들어집니다. 브라우저는 메시지가 빈 OperationError를 던집니다. 디버깅할 때는 입력을 하나씩만 바꿔 보세요. 대개 추가 인증 데이터가 범인인데, 빈 필드와 아무것도 담지 않은 필드가 라이브러리에 따라 늘 같은 것은 아니기 때문입니다.
관련 도구
ChaCha20-Poly1305 암호 (RFC 8439)
브라우저에서 AEAD_CHACHA20_POLY1305로 암·복호화하고, Poly1305 일회용 키와 카운터 분리를 함께 봅니다.
개발
TLS 암호 스위트 디코더
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 같은 IANA 등록 암호 스위트 이름을 붙여넣으면 키 교환·인증·대칭 암호·모드·MAC으로 분해해 보여주고, 순방향 비밀성·AEAD·해시 강도·이미 깨진 알고리즘까지 점검해 등급을 매깁니다.
네트워크
키쌍 생성기 (RSA·EC·Ed25519)
브라우저에서 RSA·ECDSA·ECDH·Ed25519·X25519 키쌍을 생성하고 PKCS#8/SPKI PEM 또는 JWK로 내보냅니다.
개발
HKDF 키 유도 (RFC 5869, 추출·확장)
HKDF로 키를 유도하고 두 단계를 모두 봅니다. 추출 단계의 PRK, 확장 단계의 T 블록, hex와 base64 OKM. RFC 5869 케이스 내장.
개발
DNSSEC 계산기 — DS 레코드와 NSEC3 해시
DNSKEY를 등록기관이 요구하는 DS 레코드로 바꿉니다. 키 태그와 세 가지 다이제스트 종류 전부, 또는 NSEC3 방식으로 이름을 해시합니다.
네트워크
BLAKE3·BLAKE2·Keccak-256 해시 생성기
텍스트, 16진, 파일을 BLAKE3(해시·키·키 유도), 키·솔트·개인화 BLAKE2b/2s, Keccak-256/512, SHAKE128/256으로 해시합니다.
개발