Claude가 NIST 곡선 시드를 1997년 클럭과 lrand48로 추적하다. P-256에서 돌릴 것이 없다
요약
Anthropic은 NIST의 ECDSA 곡선 시드가 1990년대 PRNG를 사용해 복구될 수 있음을 밝혀냈습니다. 이는 과거 NSA가 제공한 것으로 알려진 P-256 등의 곡선 시드들이 단순한 문장이 아닌, 특정 기간의 날짜와 관련된 패턴을 가지고 있음을 보여줍니다. 이 발견은 암호학적 보안에 대한 중요한 연구 결과를 제시합니다.
핵심 포인트
- NIST ECDSA 곡선의 시드가 1990년대 PRNG를 사용해 복구 가능함.
- P-256 등의 시드는 단순한 문장이 아닌, 특정 날짜 패턴을 가짐.
- Anthropic은 '교과서적인 격자 문제' 기법으로 내부 상태를 복구했음.
- 이 발견은 암호학적 백도어 및 보안 취약점에 대한 의문을 제기함.
- 책: System Design Pocket Guide: Interviews
- 시리즈: Pocket Guides for Developers — 에이전트, RAG, 프롬프트, 관측 가능성(observability), 이벤트, 데이터베이스 및 시스템 디자인에 대한 8권의 짧은 책 — 전체 시리즈
- 내 프로젝트: Hermes IDE | GitHub — Claude Code 및 기타 AI 코딩 도구와 함께 배포하는 개발자를 위한 IDE
- 나: xgabriel.com | GitHub
P-256의 시드는 JWT에 대한 모든 ES256 서명 아래에 있는 곡선인데, 비밀 NSA 문구의 해시가 아니었다. Anthropic이 10월 16일에 작성한 글에 따르면, 이 시드는 1997년 5월부터 1998년 4월 사이의 날짜를
NIST가 2000년에 ECDSA를 표준화하면서 P-192부터 P-521까지의 곡선들은 각각 시드(seed)로부터 파생되었습니다. Anthropic의 게시물에 따르면, 이 시드들은 "NSA가 어떠한 설명이나 정당성 없이 제공했다"고 합니다. 가장 잘 알려진 이야기는 이것들이 유머러스한 구문(passphrase)의 해시값이라는 것이었으며, 아무도 그 구문을 찾아낼 수 없었습니다.
이러한 공백은 의혹을 키웠습니다. 만약 곡선 제작자가 시드를 자유롭게 선택할 수 있다면, 이론적으로는 자신만이 알고 있는 속성을 가진 곡선이 나올 때까지 계속해서 시드를 시도해 볼 수 있기 때문입니다. Anthropic은 사람들이 오랫동안 이 시드들이 "의도적인 백도어(backdoor)를 가지고 선택되었을 가능성"에 대해 궁금해해 왔다고 언급했습니다. BleepingComputer가 2023년에 지적했듯이, 아무도 증거를 가지고 있지는 않았지만, 동시에 이를 배제할 수도 없었습니다.
그래서 2023년 Valsorda와 암호학자 그룹은 원문 기사에 $12,288의 현상금을 걸었으며, 우승자가 이 금액을 자선단체에 기부할 경우 3배인 $36,864로 증액되었습니다.
Anthropic이 밝힌 클로드의 발견 내용
정답은 문장이 아니었습니다. Anthropic에 따르면, "클로드는 소프트웨어가 1990년대 C 라이브러리와 함께 제공되는 의사 난수 생성기(PRNG: Pseudorandom Number Generator)를 사용했다고 추측했고," 그 후 게시물에서 '교과서적인 격자 문제(textbook lattice problem)'라고 부르는 방법으로 공개된 시드들로부터 해당 생성기의 내부 상태를 복구했습니다.
게시물에 담긴 세부 정보는 다음과 같습니다:
- P-192, P-224, P-256, P-384 및 P-521의 시드(seed)는
lrand48출력이며, 각 실행은 유닉스 타임스탬프(Unix timestamp)로 시딩되었습니다. P-256의 실행은 1997년 8월을 나타냅니다. - 네 개의 이진 곡선 시드(B-233, B-283, B-409, B-571)는 절반으로 나뉜 것처럼 보이는 클럭과 동일한 스킴에 부합합니다.
- "P-256의 경우, 공개된 시드는 후보 1842이지만, 같은 실행의 후보 876 역시 소수 차수 곡선(prime-order curve)을 제공합니다." 왜 876이 건너뛰어졌는지는 알려지지 않았습니다.
- P-192와 다섯 개의 ANSI X9.62 예시 곡선의 베이스 포인트(base point)는 작은 정수 시드를 사용한 다른 생성기인 FreeLIP의 출처였습니다.
Anthropic은 lrand48을 명명했고, Valsorda의 게시물에서는 drand48이라고 언급합니다. 둘 다 동일한 POSIX 계열에 속하며, 이는 "선형 합동 알고리즘(linear congruential algorithm)과 48비트 정수 산술을 사용하여" 숫자를 생성합니다. 엔진은 같지만 출력 형식이 다릅니다.

시드는 숨겨진 문장이 아니라 클럭과 48비트 생성기에서 나왔습니다.
Anthropic은 시드와 선택된 베이스 포인트를 재현하는 두 개의 Python 스크립트를 CC0 하의 퍼블릭 도메인으로 공개했습니다. 이 팀은 바운티를 주장했고, 이를 Let's Encrypt의 비영리 단체인 Internet Security Research Group에 기부하기로 결정했으며, Valsorda에 따르면 그 금액은 36,864달러로 세 배가 되었습니다.
"백도어 없음"이 현재 강력한 해석인 이유
Valsorda의 게시물은 수치로 주장을 펼칩니다. Bernstein과 Lange가 2017년에 제시한 아이디어는 약한 곡선(weak curves) 클래스를 목표로 하기 위해 시드(seeds)를 선택하는 데 대략 70비트의 자유도를 필요로 했습니다. Valsorda는 타임스탬프와 생성기(generator)를 이용해, 설령 NSA가 1997~98년 사이의 임의 타임스탬프와 처음 16개의 소수 차수 후보 중 하나를 선택했다 하더라도 "그들은 겨우 30비트의 자유도만을 가졌을 것"이라고 씁니다. 그는 이러한 발견이 "Bernstein과 Lange가 설명한 기술을 완전히 무효화한다(completely rule out)"고 말합니다.
Anthropic의 표현은 더 신중합니다: 이 발견들이 백도어(backdoor)를 "훨씬 덜 개연성 있게 만든다"는 것입니다. 그리고 해당 게시물은 범위에 대해 명확히 밝힙니다: "이것은 암호학적 돌파, 새로운 공격 또는 ECDSA 곡선에서의 취약점이 아니다."
Valsorda는 더 나아갑니다. 그는 이것이 "NIST 타원곡선 암호(elliptic curve cryptography)의 '재활성화 과정'을 깔끔하게 완성한다"고 말하며, 현대적인 결정론적 서명(deterministic signing) 및 검증된 구현(verified implementations)을 고려할 때, NIST 곡선들이 Curve25519/Ed25519/X25519보다 "내가 개인적으로 추천하는 것"이라고 언급합니다.
코드에서 변경되는 사항
P-256 자체에 대해서는: 아무것도 없습니다. 이것 때문에 키를 회전시키거나 곡선을 교체할 필요가 없습니다. Anthropic은 이 점을 수많은 단어로 말하고 있습니다.
유용한 교훈은 생성기입니다. 1997년의 프로그램이 클럭(clock)으로 비암호학적 PRNG(Pseudo-Random Number Generator)를 시딩(seeding)했고, 수십 년 후 그 출력값이 작동했던 초 단위까지 추적될 수 있었습니다. POSIX는 drand48 계열 함수가 "비자명한 요구사항(안전성을 포함하여)이 충족되어야 할 때 피해야 한다"고 말합니다. Python의 random 문서와 MDN의 Math.random() 페이지 역시 동일한 경고를 담고 있습니다: 보안 목적으로 사용해서는 안 됩니다.
세션 ID, 리셋 토큰, API 키 또는 초대 코드를 생성하는 경우, 무엇이 그것들을 만들어내는지 알아내야 합니다. git grep을 사용하면 읽어봐야 할 장소 목록을 얻을 수 있습니다:
git grep -nE \
-e 'srand(48)?\(' -e '[dlm]rand48' \
-e 'Math\.random' -e '"math/rand' \
...
마지막 두 패턴은 아무도 시드 함수를 호출하지 않더라도 math/rand를 임포트하는 Go 파일과 random을 임포트하는 Python 파일을 포착합니다. 히트(hit)가 버그는 아닙니다. Math.random()으로 테스트 피처를 섞는 것은 괜찮습니다. 하지만 토큰, 비밀번호 또는 누군가가 추측해서는 안 되는 URL에 포함된 히트는 수정해야 할 대상입니다.

PRNG(의사 난수 생성기)가 시간으로 시드된 것은 실행된 시간에만 비밀하다.
해결책은 운영체제의 암호화 생성기이며, 모든 주류 런타임이 노출하고 있습니다. Python에서는 secrets 모듈을 사용합니다:
import secrets
token = secrets.token_urlsafe(32)
Node.js에서는 crypto.randomBytes를 사용합니다:
import { randomBytes } from "node:crypto";
const token = randomBytes(32).toString("base64url");
Go에서는 math/rand가 아닌 crypto/rand를 사용합니다:
import (
"crypto/rand"
"encoding/hex"
...
브라우저에서는 MDN이 crypto.getRandomValues()를 가리킵니다.
아직 해결되지 않은 문제와 AI 부분이 의미하는 바
수수께끼는 완전히 풀리지 않았다. [Anthropic]은 “다섯 번째 이진 시드인 B-163은 Claude가 시도한 어떤 것에도 맞지 않으며 여전히 설명되지 않는다”고 언급했고, 또한 “P-224, P-256, P-384, P-521의 베이스 포인트(base points)가 어떻게 생성되었는지 알지 못한다”고 밝혔다. [Valsorda]는 추가적인 두 가지 선택 기준이 있어 그중 하나는 “아직 우리를 벗어나 있다”고 덧붙였다.
AI 측면에서는 공개된 정보에 대해 정확하게 알아야 한다. Anthropic은 모델을 “내부 연구 모델(an internal research model)” 이상으로 명시하지 않았으며, 반 시간이라는 수치 역시 내부 실행에 대한 자체적인 설명이다. 외부인이 확인할 수 있는 것은 결과이며, 이는 이미 확인되었다: 스크립트는 공개되었고, Valsorda의 Go 재구현은 GitHub에 올라와 있다. 1990년대 후반부터 제기된 질문이 오래된 C 라이브러리와 표준 격자(lattice) 기법에 대한 추측으로 마무리되었고, 인간 전문가가 하루 만에 코드로 이를 확인했다.
나 자신도 이 두 스크립트를 실행해 보지는 않았다. 만약 당신이 실행했거나, 이것을 읽은 후 자신의 레포지토리에서 Math.random() 토큰을 찾아보았다면, 댓글로 어떤 내용이 나왔는지 알려달라.
유용했다면
나는 macOS, Windows 및 Linux를 위한 무료 오픈소스 IDE인 Hermes IDE(BSL 1.1)를 구축했으며, 이를 통해 Claude Code, Codex 및 기타 코딩 에이전트들을 나란히 실행할 수 있다. 각 작업은 자체 브랜치와 워크트리에서 처리된다. 만약 메인 체크아웃을 건드리지 않고 해당 git grep 목록에 대한 작업을 수행하는 에이전트가 필요하다면, [다운로드]하거나 GitHub에서 소스 코드를 읽어볼 수 있다. 이는 Anthropic이나 어떠한 에이전트 벤더와도 제휴 관계가 아니다.
시스템 디자인 인터뷰에서는 항상 같은 몇 가지 사소한 결정들로 돌아옵니다. 바로 짧은 링크(short links), ID, 세션 토큰을 어떻게 생성하는지, 그리고 누군가 이를 예측할 수 있을 때 무엇이 망가지는지에 대한 것입니다. System Design Pocket Guide: Interviews는 15가지 실제 디자인 사례를 단계별로 설명하며 트레이드오프(trade-offs)까지 포함하고 있어, 이러한 선택들에 대해 논리적으로 설명하는 연습을 할 수 있게 해줍니다. 이 책은 Pocket Guides for Developers 시리즈의 8권 중 하나로, 에이전트(agents), RAG, 프롬프트(prompts), 관측 가능성(observability), 이벤트(events), 데이터베이스(databases), 그리고 시스템 디자인을 다루고 있습니다.

AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기