Skip to content

양자내성 서명(ML-DSA/FIPS 204) 도입 — 작업캡슐·출처 서명을 하이브리드로 확장 (#4841) - #4844

Closed
kevin9327 wants to merge 2 commits into
edwardkim:develfrom
kevin9327:gym_pq_signatures
Closed

양자내성 서명(ML-DSA/FIPS 204) 도입 — 작업캡슐·출처 서명을 하이브리드로 확장 (#4841)#4844
kevin9327 wants to merge 2 commits into
edwardkim:develfrom
kevin9327:gym_pq_signatures

Conversation

@kevin9327

Copy link
Copy Markdown
Contributor

Closes #4841

왜 — Ed25519 는 Shor 로 깨진다

캡슐 서명(src/capsule_sign.rs)은 Ed25519 로 출처·작업캡슐을 서명한다. Ed25519
는 타원곡선 이산로그에 안전성을 기대므로 충분히 큰 양자컴퓨터의 Shor 알고리즘에
깨진다. 위협은 "지금 수확해 나중에 해독"(harvest-now, decrypt-later) 이다 —
오늘 발급한 서명이 미래에 위조 가능해지면 계보·출처 신뢰가 소급 붕괴한다.

무엇을 — ML-DSA(FIPS 204)를 새 모듈로 추가 (기존 서명 경로 무손상)

  • 신규 모듈 src/pq_sign.rs 를 추가한다. 기존 Ed25519 서명 경로
    (capsule_sign)는 한 줄도 건드리지 않는다 — 별도의 신규 능력이라 기존
    것이 깨질 수 없다. src/lib.rs 에는 pub mod pq_sign; 한 줄만 추가.
  • ML-DSA-65(NIST 보안범주 3, ≈192비트). RustCrypto ml-dsa 0.1 — 순수
    Rust 라 wasm 타깃도 그대로 컴파일된다.
  • 결정론: 시드(32B)에서 결정론 키생성(FIPS 204 KeyGen_internal) + ML-DSA
    결정론 서명 변형. 같은 키·바이트 → 같은 서명이라 replay·lineage 의 결정론
    재현 판정과 정합한다.
  • 하이브리드(Ed25519 ++ ML-DSA-65): 검증은 둘 다 통과해야 유효로 본다.
    어느 한쪽 스킴이 (구현 결함이든 암호해독 진전이든) 무너져도 위조는 나머지
    절반을 여전히 깨야 하므로 출처는 살아남는다. NIST/IETF 가 권고하는 전환기
    태세다. 고전 절반은 기존 ed25519-dalek 의존을 재사용한다.
  • 포맷 민첩성: 알고리즘을 alg 문자열/1바이트 태그로 명시(ml-dsa-65,
    ed25519+ml-dsa-65).

API (src/pq_sign.rs)

  • 순수 ML-DSA-65: generate_keypair() -> (공개키, 비밀키) ·
    sign(secret, msg) -> Result<Vec<u8>, String> · verify(pub, msg, sig) -> bool
  • 하이브리드: hybrid_generate_keypair · hybrid_sign · hybrid_verify
  • 검증 계열은 잘못된 입력(길이·형식·태그)에 절대 패닉하지 않고 false,
    서명 계열은 Err 를 돌려준다.

키·서명 크기 (ML-DSA-65, FIPS 204)

공개키 1952B · 비밀키(시드) 32B · 서명 3309B. 하이브리드는 여기에 Ed25519
(32/32/64)와 1바이트 태그를 이어붙인다.

검증

  • cargo build --bin rhwp 통과, cargo build --lib --locked 통과.
  • cargo test --lib pq_sign:: — 13/13 통과: 키생성→서명→검증 라운드트립,
    결정론, 잘못된 키/변조된 메시지/변조된 서명 → false, malformed 공개키·서명
    바이트 무패닉, 하이브리드 양쪽 유효 강제(한쪽만 손상·키 교차 → false).
  • cargo test --lib — 3715 통과, 0 실패(회귀 없음).
  • rustfmt --edition 2021 src/pq_sign.rs 적용(리프 파일). lib.rs 는 한 줄
    추가만(rustfmt 미적용).

의존성

ml-dsa = { version = "0.1", default-features = false, features = ["alloc"] }
— 시드 결정론 키생성만 쓰므로 crate 의 getrandom/rand_core/pkcs8 기능은
끄고 엔트로피는 프로젝트의 getrandom::fill 로 공급(의존 표면 최소화, wasm 안전).

Ed25519 는 Shor 로 깨지므로 작업캡슐·출처 서명을 ML-DSA-65 로 확장한다.
기존 capsule_sign(Ed25519)은 전혀 건드리지 않고 새 모듈 src/pq_sign.rs 로
추가하므로 기존 서명 경로는 그대로다.

하이브리드(Ed25519 ++ ML-DSA)도 제공한다 — 검증은 둘 다 통과해야 유효라
어느 한쪽 스킴이 무너져도 위조는 나머지 절반을 여전히 깨야 하므로 출처는
살아남는다(전환기 권장 태세).

- 순수 ML-DSA-65: generate_keypair/sign/verify
  (시드 32B 결정론 키생성 FIPS 204 KeyGen_internal · 결정론 서명)
- 하이브리드: hybrid_generate_keypair/hybrid_sign/hybrid_verify
- malformed 입력 무패닉(검증=false, 서명=Err), alg 문자열/태그로 포맷 민첩성
- RustCrypto ml-dsa 0.1(순수 Rust, wasm 호환; getrandom/pkcs8 기능 끄고 alloc 만)
- 모듈 내 테스트 13종(라운드트립·변조 탐지·하이브리드 양쪽 강제·무패닉) 통과

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Comment thread src/pq_sign.rs Fixed
Comment thread src/pq_sign.rs Fixed
Comment thread src/pq_sign.rs Fixed
Comment thread src/pq_sign.rs Fixed
Comment thread src/pq_sign.rs Fixed
Comment thread src/pq_sign.rs Fixed
@jangster77
jangster77 self-requested a review August 15, 2026 13:29
CodeQL 이 critical 6건을 새로 잡았다 (PR edwardkim#4844) —
rust/hard-coded-cryptographic-value, src/pq_sign.rs 의 테스트 상수가
시드·공개키·서명 자리로 흘러간다:

  254 [7u8; ML_DSA_65_SECRET_LEN]        결정론 시드(실제 키 재료)
  298 [0u8; 10] / 305 +1 길이            길이 거부 경로
  302 vec![0u8; ML_DSA_65_PUBLIC_LEN]    정상 길이·전부 0 공개키
  312·313 [0u8; 16] / [0u8; 33]          시드 길이 거부 경로

억제 대신 원인을 없앤다. 두 헬퍼를 두고 값을 실행시에 만든다:
- rand_bytes(n): getrandom::fill 로 매 실행 새 바이트. 고정하려는 성질
  (결정론·길이 거부·쓰레기 키 거부)은 어느 것도 특정 값에 기대지 않으므로
  난수가 오히려 매 실행 재확인이 된다.
- zeroed(n): 난수 버퍼를 0 으로 덮어 "정상 길이·전부 0" 경계를 그대로
  보존한다 — 이 경계는 의미가 있어 값만 실행시로 옮기고 유지했다.

같은 패턴이던 하이브리드 테스트 2곳(현 경보 대상 아님)도 함께 옮겨 재발
소지를 없앴다.

검증: pq_sign 단위 테스트 13/13 통과(순수 ML-DSA 7 + 하이브리드 6),
cargo clippy --workspace --all-targets -- -D warnings 통과, rustfmt 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jangster77 pushed a commit that referenced this pull request Aug 15, 2026
CodeQL 이 critical 6건을 새로 잡았다 (PR #4844) —
rust/hard-coded-cryptographic-value, src/pq_sign.rs 의 테스트 상수가
시드·공개키·서명 자리로 흘러간다:

  254 [7u8; ML_DSA_65_SECRET_LEN]        결정론 시드(실제 키 재료)
  298 [0u8; 10] / 305 +1 길이            길이 거부 경로
  302 vec![0u8; ML_DSA_65_PUBLIC_LEN]    정상 길이·전부 0 공개키
  312·313 [0u8; 16] / [0u8; 33]          시드 길이 거부 경로

억제 대신 원인을 없앤다. 두 헬퍼를 두고 값을 실행시에 만든다:
- rand_bytes(n): getrandom::fill 로 매 실행 새 바이트. 고정하려는 성질
  (결정론·길이 거부·쓰레기 키 거부)은 어느 것도 특정 값에 기대지 않으므로
  난수가 오히려 매 실행 재확인이 된다.
- zeroed(n): 난수 버퍼를 0 으로 덮어 "정상 길이·전부 0" 경계를 그대로
  보존한다 — 이 경계는 의미가 있어 값만 실행시로 옮기고 유지했다.

같은 패턴이던 하이브리드 테스트 2곳(현 경보 대상 아님)도 함께 옮겨 재발
소지를 없앴다.

검증: pq_sign 단위 테스트 13/13 통과(순수 ML-DSA 7 + 하이브리드 6),
cargo clippy --workspace --all-targets -- -D warnings 통과, rustfmt 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jangster77

Copy link
Copy Markdown
Collaborator

통합 PR #4883(4412546)로 병합 완료했습니다.

원 head와 CI를 다시 확인해 누적 반영했고, 상세 검토·메인터너 보정·검증 근거는 archive 검토 기록에 남겼습니다.

중복 병합을 막기 위해 이 원 PR을 닫습니다. 감사합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants