BIP for HD Wallet

BIP란 무엇인가

BIP는 Bitcoin Improvement Proposals의 약자로서, 비트코인 기능 개선을 위한 제안을 담은 문서이다.

BIP란 비트코인을 개선하고자 제안하는 개선안 수정 및 개선이 필요한 비트코인의 사항에 대하여 문제를 제기하고 해당 쟁점이 타인들로부터 일정한 규모 이상의 지지를 얻게 되면 공식적인 절차를 통하여 BIP 프로세스에 회부되는 것이다.

BIP에는 여러 가지 종류가 있다. 이 글에서는 HD wallet을 구축하기 위해 꼭 알아야 하는 몇 가지만 짚고 넘어가겠다.

  • BIP32: HD 지갑의 일반적인 형식과 HD 지갑을 구축하는 방법을 설명한 문서.

  • BIP39: 결정성 열쇠를 파생하기 위한 니모닉 코드의 유형 및 BIP32 시드로 전환하는 프로세스

  • BIP44: BIP32 지갑의 특정 형식, 목적을 44로 설정해서 나타나는 다중 화폐 다 계정 주소를 제안

  • BIP84: P2WPKH 기반 계정의 유도 스키마

BIP32와 HD Wallet

BIP32가 탄생하게 된 배경은 하나의 비트코인 주소보다 여러 개의 비트코인 주소를 가지고 입출금을 하면 훨씬 더 안전하다는 것에서 부터 출발하여 현재는 다양한 용도로 사용 가능하다.

BIP32는 처음으로 HD 지갑에 대한 구조를 제안했는데, HD 지갑은 결정적 계층 구조 지갑으로 2진 트리처럼, 부모 자손 관계를 이용해 끝없이 파생시킬 수 있는 지갑으로 BIP32 이외에도 BIP39, BIP44등 여러 버전이 있으며 BIP39로 만들어진 프로그램은 다른 블록체인에서도 흔히 사용된다.

아래 그림과 같이 HD 지갑은 하나에 시드에서 파생된다.

BIP39와 HD Wallet

우리가 흔히 아는 니모닉은 BIP39에 의해 표준화 되어있다.

니모닉이란 단어 시퀀스를 사용한 방법으로 몇 개의 단어들의 나열을 사용자에게 기억하게 함으로써 이 단어들의 나열은 나중에 지갑 복구에 사용된다.

니모닉과 시드의 생성과정에 대해서 잠시 알아보자.

  1. 128~256 비트의 무작위 암호화 시퀀스 S를 생성한다.

  2. 128비트를 32로 나누어서 4라는 값을 얻는다. (256비트라면 256/32 => 8)

  3. 시퀀스 S를 SHA-256를 넣어 결과 값을 얻는다. (e.g. 011100011001010…)

    1. 이제 우리는 이 결과값의 첫 4비트만 사용한다. (256비트였다면 8비트)

  4. S의 마지막에 3번의 첫 4비트를 추가한다. (e.g. 0111….0111)

    1. 여기서 헷갈리지 말아야 할 것은 우리는 지금 원본 S와 해시함수에 넣은 S의 일부 둘 다 사용하고 있다는 점이다.

  5. 4번의 결과값을 S’라고 하자. S’을11비트 단위로 나눈다.

  6. 2048 단어로 구성된 BIP-39 영어 단어 목록에서 각 11비트마다 매칭되는 단어를 나열하여 니모닉 코드를 생성한다.

    1. 예를 들면 첫 11비트가 01110000111라면 영어 단어 목록에 01110000111: 'lion' 이런 식으로 각 단어가 매칭되어 있다.

    2. 즉, S`은 128 + 4 = 132비트이고 132비트를 11비트 단위로 나누었으니 총 12개의 단어를 얻을 수 있다.

이제 니모닉을 만들었다. 그러면 니모닉을 기반으로 시드를 만드는 법을 보자.

시드는 PBKDF2라는 함수를 사용하여 만들게 되는데 이 함수는 2가지 parameter를 필요로 한다.

한 가지는 위에서 구한 니모닉 단어들이고 나머지 하나는 salt이다.

salt란 사용자가 추가로 정하는 암호로 만약 선택하지 않는다면 기본값인 mnemonic 으로 설정되고, 만약 사용자가 지정한다면 기본값인 "mnemonic"에 추가되어진다.

예를 들어 사용자가 "secretkey123"이란 암호를 추가했다면 salt는 "mnemonicsecretkey123"이 되는 식이다.

PBKDF2는 HMAC-SHA512 알고리즘으로 우리의 니모닉 단어들과 salt를 인자로 집어넣으면

내부적으로 2048 해시 라운드를 사용하여 최종 결과 값으로 512비트 값을 출력하게 되는데, 이게 바로 시드다.

2048라운드란 예를 들어 해쉬함수 f(x)가 있고 f(1)의 결과값이 2라면 이 결과값을 다시 f(x)에 넣는다.

그럼 2라운드를 돌린 것이고, 이걸 2048 라운드를 하겠다는 것이다.

당연한 이야기지만 같은 니모닉 단어들이여도 salt값이 다르다면 시드 값은 달라진다.

BIP44

복수화폐(multicurrency) 및 복수계정(multiaccount) 지갑을 설명하는 일반적인 산업 표준이다.

BIP44는 BIP43의 스펙을 확장하여 목적 번호를 44'로 설정하여 복수 화폐 복수 계정 구조를 제안한다.

BIP44의 구조를 따르는 모든 HD 지갑 구조는 하나의 트리 분기(m/44'/*)만 사용하여 식별된다.

BIP44는 미리 정의된 다섯 가지 트리 레벨로 구성된 구조를 지정한다.

m / purpose' / coin_type' / account' / change / address_index

목적 (purpose)

첫 번째 레벨인 목적은 항상 44로 설정된다.

코인 종류 (coin_type) :

코인 종류는 암호화폐의 유형을 지정한다.

이더리움은 m/44’/60’, 비트코인은 m/44’/0’, 모든 테스트넷은 m/44’/1’이다.

계정 (account)

사용자는 지갑을 m/44’/0’/0’, m/44’/0’/1’ 처럼 HD 지갑에는 2개의 비트코인 계정을 포함할 수 있다.

잔고 (change)

BIP44는 원래 비트코인을 위해 제작되었기 때문에 이더리움 세계와 관련이 없는 '특이점'(quirk)이 포함되었다.

HD 지갑에는 2개의 하위 트리가 있는데 하나는 입금 주소 작성용이고 다른 하나는 잔액 주소 작성용이다.

이더리움은 비트코인에 있는 잔액 주소가 필요 없으므로 단지 '입금' 경로만 사용하여 항상 0이다.

이전 레벨은 강화파생만 사용했지만 이 레벨은 비보안 환경에서 사용할 수 있도록 확장된 공개키를 트리의 계정 수준에서 내보낼 수 있게 하기 위해서 일반 파생을 사용한다.

사용가능한 주소 인덱스 (address_index)

트리의 다섯번째 레벨은 사용 가능한 주소 인덱스로 만드는 것이다. 예를 들어 주 메인 계정에서 이더리움 지급을 위한 세 번째 입금 주소는 m/44'/60'/0'/0/2가 될 것이다. 이것은 HD 지갑에서 파생된 level-4의 자식이다.

M/44'/60'/0'/0/2 : 메인 이더리움 계정에 대한 세 번째 수신 공개키
M/44'/0'/3'/1/14 : 4번째 비트코인 계정의 15번째 주소 변경 공개키 
m/44'/2'/0'/0/1 : 트랜잭션 서명을 위한 라이트코인 메인 계정의 두 번째 개인 키

BIP84

BIP84는 기본 Segwit P2WPKH 주소에 대한 HD 지갑의 구현을 정의한다.

주소 유형을 제외하면 BIP44와 유사하다.

Segwit과 P2WPKH 개념이 조금 어려운데, 관련 글을 따로 작성한 적이 있으니 아래 링크에서 참고하면 좋을 것 같다.

Last updated