482 / 736CSPRNG

CSPRNG

암호학적으로 안전한 의사난수 생성기

지갑에 새로운 비밀값이 필요할 때, 무작위처럼 보이는 숫자만으로는 충분하지 않습니다. CSPRNG는 공격자가 출력의 일부를 알아도 다음 값을 현실적인 계산으로 예측하기 어렵게 만드는 역할을 합니다.

CSPRNG는 암호학적으로 안전한 의사난수 생성기입니다. 비밀 내부 상태를 바탕으로 정해진 절차에 따라 새로운 값을 계산합니다. ‘의사난수’라는 말은 품질이 낮다는 뜻이 아닙니다. 계산을 재현할 수는 있지만, 비밀 상태를 모르는 사람에게는 결과를 실질적으로 예측할 수 없어야 합니다. 그러려면 공격자가 입력에 대해 알지 못하는 불확실성인 엔트로피가 충분해야 하고, 앱도 생성기를 올바르게 사용해야 합니다.

지갑의 비밀값을 만드는 프로그램을 떠올려 보세요. 공격자가 이전 출력 중 일부를 알아냈습니다. 안전한 생성기라면 그 정보가 나머지 값을 추측하는 데 도움이 되어서는 안 됩니다. 이는 그래프에 숫자가 고르게 분포하는 것보다 더 까다로운 요구입니다. RFC 4086은 그래서 암호학적으로 강한 수열과 일반 시뮬레이션용 생성기를 구분합니다. 통계 검정 결과가 좋아도 생성의 출발값인 seed를 추측할 수 있다면 충분하지 않습니다. [1]

기술 문서에는 결정론적 난수 비트 생성기를 뜻하는 DRBG도 등장합니다. ‘결정론적’이란 상태와 입력이 같으면 결과도 같다는 뜻입니다. 그래서 상태를 비밀로 지켜야 합니다. NIST SP 800-90A Rev. 1은 Hash_DRBG, HMAC_DRBG, CTR_DRBG라는 구체적인 방식을 설명합니다. 이는 기술적 절차이지, 그 이름을 쓰는 모든 프로그램의 품질 인증이 아닙니다. 설정, 엔트로피의 출처, 실제 코드 구현도 함께 살펴야 합니다. [2]

상태 유출은 두 가지 질문을 낳습니다. 공격자가 이전의 비밀 출력을 재구성할 수 있을까요? 다음 출력도 예측할 수 있을까요? 이전 출력을 보호하는 성질은 Backtracking resistance, 이후 출력을 보호하는 성질은 Prediction resistance라고 합니다. 후자에 대해 NIST SP 800-90A는 새로운 엔트로피를 효과적으로 넣어, 새 결과가 유출된 상태와 분리되도록 요구합니다. 계산을 한 번 더 실행하는 것만으로는 안전성이 회복되지 않을 수 있습니다. 한 보호 기능이 있다고 다른 기능까지 자동으로 입증되는 것도 아닙니다. [2]

라이브러리는 지갑이 활용할 수 있는 미리 만들어진 소프트웨어 부품입니다. 하지만 호출이 실패할 수 있습니다. OpenSSL 3.5에서 RAND_bytes()와 RAND_priv_bytes()는 성공하면 1, 다른 실패에는 0, 현재 방식이 지원되지 않으면 -1을 반환합니다. 엔트로피 원천에 문제가 생기면 생성을 거부할 수 있습니다. 프로그램은 버퍼라고 부르는 예약된 메모리 공간을 사용하기 전에 이 반환값을 확인해야 합니다. 그렇지 않으면 안전하게 생성된 적이 없는 데이터를 사용할 수 있습니다. [3]

재현성은 테스트에 유용합니다. 개발자는 결과를 예상값과 비교하고 싶기 때문입니다. libsodium의 randombytes_buf_deterministic()은 그래서 같은 seed에서 같은 수열을 만듭니다. 그러나 실제 운영에서 의도치 않은 반복은 문제가 됩니다. 가상 머신 스냅샷은 메모리를 포함한 컴퓨터 상태를 저장한 것으로, 이를 복원하면 생성기의 상태와 출력도 반복될 수 있습니다. 환경을 복사했다고 해서 서로 독립적인 비밀이 만들어지는 것은 아닙니다. [4]

생성기가 좋은 난수 데이터를 제공해도 앱이 그다음 처리를 잘못할 수 있습니다. 허용된 작은 범위로 변환하려고 단순히 나눗셈의 나머지를 쓰면 일부 결과가 다른 결과보다 더 자주 나올 수 있습니다. libsodium의 randombytes_uniform()은 지정한 상한 미만에서 균등하게 선택해 이런 편향을 피합니다. 키는 해당 알고리즘의 규칙도 따라야 합니다. 무작위 바이트를 얻는 것으로 끝나는 것이 아니라, 이후 어떻게 쓰느냐도 안전성을 좌우합니다. [4]

Nonce는 암호 절차에서 개별 사용을 위해 마련한 값이지만, 지켜야 할 규칙은 프로토콜이 정합니다. RFC 8439는 같은 키로 nonce를 반복하지 못하도록 요구합니다. 무작위처럼 보인다는 사실만으로 유일성이 보장되지는 않습니다. 반면 RFC 6979는 비밀키와 서명할 메시지로부터 전자서명에 필요한 값 k를 결정론적으로 계산하는 방법을 설명합니다. 이는 모순이 아니라 서로 다른 설계입니다. ‘어디에나 난수를 추가하라’는 지침은 올바른 절차를 대신할 수 없습니다. [5] [6]

CSPRNG라는 표시만으로 지갑이 전체 시스템을 올바르게 사용하는지 알 수는 없습니다. 기술 검토에서는 구체적인 라이브러리 버전, 생성기 시작 과정, 오류 처리, 상태 복원이나 복제 후의 동작을 확인합니다. OpenSSL과 libsodium 문서는 각 함수의 성질을 설명할 뿐, 이를 호출하는 모든 앱의 안전성을 보증하지 않습니다. 사용자에게는 그 이후도 중요합니다. 완벽하게 생성한 비밀이라도 접근 권한을 복원할 수 있는 백업이 나중에 유출되면 자금을 보호하지 못합니다. [3] [4]

더 정확히 이해하려면 이 항목과 함께 다음도 읽어 보세요 Cryptographic Entropy, Random Number Generator, Deterministic RNG, Seed Generation. 다음 항목에서도 이 글을 참조합니다 Dice Roll Entropy, Cryptographic Entropy, Random Number Generator, Deterministic RNG.

DOC · 001RFC 4086 — Cryptographically strong sequences명세 DOC · 002NIST SP 800-90A Rev. 1 — DRBG mechanisms and compromise resistance명세 DOC · 003OpenSSL 3.5 — RAND_bytes return values and errors문서 DOC · 004libsodium — Random data and deterministic testing문서 DOC · 005RFC 8439 — Nonce uniqueness명세 DOC · 006RFC 6979 — Deterministic signing명세
개정일: 1차 출처 우선 · 투자 조언이 아닙니다