비트코인 코어 소스코드를 통해 보는 HD wallet

Park Juhyung
코드체인
Published in
4 min readFeb 24, 2018
Photo by Lukas from Pexels

비트코인에서, 하나의 주소로 돈을 계속 넣고 빼는 것은 권장되지 않습니다. 돈을 한 번 이라도 빼면, 보안적인 측면에서, 더 약해집니다. 비트코인의 주소는 퍼블릭 키의 해시 값입니다. 따라서 해커가 주소를 통해서 프라이빗 키를 알아내려면, 두번의 매우 힘든 과정을 거쳐야합니다. 첫째로 해시함수의 역을 구해야합니다. 그 뒤 퍼블릭키로 프라이빗 키를 찾아야 하죠.

하지만 돈을 한번이라도 빼게되면 첫 번째 과정이 사라집니다. 돈을 사용하기 위해서 자신의 퍼블릭 키를 공개해야하기 때문이죠. 그래서 비트코인은 매번 새로운 주소로 돈을 받는 것을 권장합니다.

하지만 매번 새로운 주소를 사용하면 당연히 프라빗 키들의 관리가 복잡해집니다. 주소는 퍼블릭 키의 해시 값입니다. 이 말은 즉, 많은 주소를 관리하려면 많은 프라이빗 키를 가지고 있어야 하는 거죠.

이를 해결하기 위해 나온 방법이 HD wallet입니다. master private key와 master public key로부터 수많은 private key / public key들을 만들어낼 수 있습니다.

HD wallet의 원리

기본적인 원리는 간단합니다. 비트코인에서 private key는 랜덤한 숫자입니다. 간단한 규칙을 통하여 하나의 숫자로 다른 수많은 숫자를 만들어 낼 수 있죠. 예를 들어 제가 가지고 있는 private key가 17이라면 18, 19, 20, … 이렇게 숫자를 하나씩 증가시키면 무수히 많은 private key를 만들어낼 수 있습니다.

하지만 이 방식엔 문제가 하나 있습니다. 19와 20의 public key가 알려지게 된다면 역추적해서 맨 처음 public key를 찾아낼 수 있습니다.

그래서 이 문제를 해결하기 위하여 HD wallet에서는 chain code라는 숫자를 하나 더 사용합니다. parent key와 chain code를 사용하여 child key와 chain code를 만들어 냅니다. 이 방식을 사용하면 자식의 public key로 부모의 public key를 추론하는 것이 매우 어려워지죠.

bitcoin core 에서의 구현

bitcoin core의 구현에서는 클래스가 4가지 있습니다. CKey, CPubKey, CExtKey, CExtPubKey로 나뉩니다. CKey와 CPubKey는 HD wallet의 키가 아닌 평범한 비밀키와 공개키입니다. CExtKey와 CExtPubKey는 chain code를 가지고 있는 클래스입니다.

CExtKey는 CKey와 ChainCode를 가지고 있습니다.

HD wallet에서 가장 중요한 기능은 자식의 키를 만드는 거죠. 그래서 각 클래스에는 Derive라는 함수가 있습니다. chaincode와 public key로 다음 public key를 만들거나, chaincode와 private key로 다음 private key를 만드는 함수죠.

pubkey의 Derive함수

Derive함수를 보면 6번째 줄에서 cc와 nChild를 이용하여 계산한 Hash값을 out에 저장합니다.
7번째 줄에서 out변수에 있는 값으로 자식의 chain code를 만들어냅니다.
12번째 줄에서 부모의 pubkey와 out의 값으로 자식의 public key를 만들어냅니다.

CExtKey의 선언 부분 코드 링크

CPubKey의 Derive함수 구현 부분 코드 링크

코드에 대한 의견

CKey, CPubKey클래스와 CExtKey, CExtPubKey 클래스를 나눈 것은 자연스럽습니다. Ext라는 prefix를 통해 이름을 통일시킨 것도 좋네요.

하지만 Derive함수가 CKey, CPubKey, CExtKey, CExtPubKey에 있는 건 어색합니다. CKey를 쓰는 입장에서는 HD wallet에 대한 내용을 알 필요가 없습니다. HD wallet을 쓰려면 CExtKey를 써야합니다. CKey에서 임의의 chain code로 child를 생성하는 기능을 제공하는 건 이상하지 않나요?

실제로 CKey의 Derive함수는 CExtKey에서만 사용합니다. CPubKey의 Derive함수도 CExtPubKey에서만 사용합니다. 제 생각엔, HD wallet에 대한 코드는 전부 Ext 코드로 빠지는 게 더 좋네요.

--

--