비트코인 개인키 및 시드 문구 생성에 주사위를 사용하는 것에 대한 고찰

암호학적으로 안전한 난수


최근 비트코인 지갑과 관련해 개인키 및 시드 문구를 생성할 때 동전이나 주사위를 사용하면 안전하게 생성할 수 있다는 인식이 확산하고 있는 것 같다. 과연 안전한 방법일까?

먼저 무작위 수인 난수에 대해 생각해볼 필요가 있다. 사실 난수라는 것은 이상적인 개념이다. 완전한 난수는 현실에서 구현하기 불가능에 가깝기 때문이다. 마치 완전한 원이 현실에 존재할 수 없는 것과 비슷하다.

컴퓨터도 이상적인 난수를 생성할 수 없다. 어떤 초깃값을 입력하면 무작위 값처럼 보이는 숫자들을 출력하는 알고리즘만 존재할 뿐이다. 이것을 의사난수라고 부른다. 초깃값이 동일하면 생성되는 난수도 똑같기 때문에 의사난수 생성기는 난수의 생성을 위해 난수가 필요하다는 모순이 발생한다.

의사난수 생성기의 초깃값은 다른 사람이 재현할 수 없어야 하므로 다양한 소스를 활용한다. 예를 들어 일정 시간 동안 사용자의 마우스 좌표 흔적, 현재 시각, 하드웨어 부품의 온도, 주파수, 전압 등을 사용한다.

다양한 소스를 사용해 재현 불가능한 초깃값으로 난수 생성기를 사용한다고 해도 그 난수 생성기가 안전한지 통계적으로 검증해야 한다. 검증이 완료된 난수 생성기를 '암호학적으로 안전한 의사난수 생성기(CSPRNG)'라고 부른다.

'암호학적으로 안전하다'라는 말은 통계적 무작위성 테스트를 통과했으며 난수열 중 일부가 노출되더라도 전체를 예측하기 힘들다는 뜻이다. 즉, 통계적으로 내가 생성한 난수열을 다른 사람이 재현할 수 없다는 것을 말한다.

당연히 비트코인 개인키 및 시드 문구 생성에는 '암호학적으로 안전한 의사난수 생성기'를 이용해야 한다. Bitcoin Core에선 CPU에서 제공하는 난수 명령어, OS에서 제공하는 난수 소스, 시간 관련 값, 운영되는 환경 값 등을 활용해 암호학적으로 안전한 난수를 생성한다.

Bitcoin Core - random.cpp

그렇다면 주사위는 '암호학적으로 안전한 난수 생성기'일까? 아니다. 주사위, 동전과 같은 현실의 물리적 도구는 생성되는 숫자에 편향이 생길 수밖에 없기 때문이다. 현실에서 완전한 정육면체에 무게중심이 정 가운데 위치한 주사위는 존재할 수 없다는 것을 떠올려보면 이는 어쩌면 당연하다.

작은 편향이 누적되면 결과에 큰 영향을 미치게 되므로 주사위를 시드 문구 생성에 직접 이용하는 것은 위험할 수 있다. 편향에서 오는 왜곡을 보정해주는 알고리즘(Von Neumann skew-correction algorithm 등)이 있긴 하지만 복잡할뿐더러 주사위를 더 많이 던져야 한다.

Von Neumann skew-correction algorithm

개인적으론 주사위를 사용하는 것보단 잘 알려진 오픈소스 월렛을 이용해 시드 문구를 생성하고 BIP39에 포함된 선택적 암호문(passphrase) 기능을 이용하는 것이 합리적인 선택이 아닐까 생각한다. 더불어 하드월렛을 사용한다면 해당 기기가 암호학적으로 안전한 난수를 생성하는지 확인해보자.