Skip to content

Latest commit

 

History

History
447 lines (296 loc) · 32.4 KB

bip-0032.md

File metadata and controls

447 lines (296 loc) · 32.4 KB

BIP-32

📖 원문: BIP-0032

BIP: 32
레이어: 애플리케이션
제목: 계층 결정적 지갑
작성자: 피터 우일(Pieter Wuille, [email protected])
의견 요약: 의견 없음
의견 주소: https://github.com/bitcoin/bips/wiki/Comments:BIP-0032
상태: 완결됨
유형: 정보 제공
생성일: 2012년 2월 11일
라이선스: BSD-2-Clause


목차



초록

이 문서는 계층 결정적 지갑(또는 HD 지갑)에 대해 설명한다. 계층 결정적 지갑은 다른 시스템과 부분적 혹은 전체적으로 공유할 수 있으며, 코인을 사용할 수 있는 기능을 가지기도, 가지지 않기도 한다.

명세(Specification)는 서로 다른 클라이언트 간에 교환할 수 있는 결정적 지갑에 대한 표준을 설정하기 위하여 작성하였다. 여기에 설명된 지갑에는 많은 기능이 있지만 클라이언트 지원에 모든 기능이 필요한 것은 아니다.

명세는 두 부분으로 구성된다. 첫 번째 파트에서는 단일 시드로부터 키 쌍 트리를 도출하는 시스템을 소개한다. 두 번째 파트에서는 이러한 트리 위에 지갑 구조를 만드는 방법에 대해 설명한다.


저작권

이 BIP는 2조항 BSD 라이선스에 따라 라이선스가 부여된다.


동기

비트코인 참조 클라이언트는 무작위로 생성된 키를 사용한다. 모든 거래 이후 백업할 필요가 없도록 (기본적으로) 100개의 키가 예비 키 풀에 캐싱된다. 하지만 이러한 지갑들은 여러 시스템에서 동시에 공유하여 사용하기 위한 것이 아니다. 지갑들은 암호화 기능을 사용해 개인키를 숨기고 비밀번호를 공유하지 않도록 지원하기는 하지만, 이러한 “중립적인(neutered)” 지갑은 공개키를 생성할 수 있는 권한도 잃게 된다.

결정적 지갑은 자주 백업할 필요가 없으며, 타원 곡선 수학은 개인키를 공개하지 않고 공개키를 계산할 수 있게 한다. 예를 들어 온라인 상품 판매 비즈니스에서는 웹 서버가 각 주문 또는 각 고객에 대한 새로운 주소(공개키 해시)를 생성하도록 허용하면서 웹 서버에 해당 개인키(수신된 자금을 사용하는데 필요한)에 대한 접근 권한은 부여하지 않을 수 있다.

하지만 결정적 지갑은 일반적으로 키 쌍의 단일 “체인”으로 구성되어 있다. 체인이 하나라는 것은 지갑 공유가 모 아니면 도(전체 아니면 아무것도 아닌)로 이뤄진다는 뜻이다. 그러나 일부 (공개)키만 공유하고 복구할 수 있기를 바라는 경우도 있다. 온라인 상품 판매점에서 웹 서버는 고객의 결제를 받는 데 사용되는 주소에만 접근하고 판매자가 돈을 쓸 때 생성되는 거스름돈(change) 주소에는 접근하지 않아도 된다. 계층 결정적 지갑은 단일 루트로부터 파생된 여러 키 쌍 체인을 지원함으로써 이러한 선택적 공유를 허용한다.


명세: 키 파생

규칙

이 문서의 나머지 부분에서는 비트코인에서 사용되는 공개키 암호 방식, 즉 secp256k1(http://www.secg.org/sec2-v2.pdf)에 정의된 필드 및 곡선 매개변수를 사용하는 타원 곡선 암호화를 가정한다. 아래의 변수는 다음과 같다.

  • 곡선의 순서를 모듈로 연산한 정수 (n)
  • 곡선의 점 좌표
  • 바이트 시퀀스

두 좌표 쌍의 더하기(+)는 EC 그룹 연산의 적용으로 정의된다. 연결 연산자(||, concatenation)는 한 바이트 시퀀스를 다른 바이트 시퀀스에 추가하는 연산이다.

표준 변환 함수는 다음과 같다.

  • point(p): secp256k1 기준점과 정수 p의 EC 점 곱셈(EC 그룹 연산의 반복 적용)으로부터 나온 좌표 쌍을 반환한다.
  • ser32(i): 32비트 부호 없는 정수 i를 가장 중요한 바이트부터 4바이트 시퀀스로 직렬화 한다.
  • ser256(p): 정수 p를 가장 중요한 바이트부터 32바이트 시퀀스로 직렬화 한다.
  • serp(P): 좌표 쌍 P=(x, y)를 SEC1의 압축 형식인 (0x02 또는 0x03) || ser256(x)를 사용하여 바이트 시퀀스로 직렬화 한다 (여기서의 헤더 바이트는 생략된 y 좌표의 패리티에 따라 달라짐).
  • parse256(p): 32바이트 시퀀스를 가장 중요한 바이트부터 256비트 숫자로 해석한다.

💡 패리티

패리티(Parity)는 짝수와 홀수를 구분하는 개념이다. 국제 표준에서는 이러한 패리티 개념을 사용해 타원 곡선 암호 공개키를 압축하고 직렬화 한다.


확장 키

다음으로는 부모 키에서 여러 개의 자식 키를 파생하는 함수를 정의한다. 이러한 함수가 키 자체에만 의존하는 것을 방지하기 위해 먼저 개인키와 공개키를 모두 256비트의 엔트로피로 확장한다. 체인코드라고 하는 이 확장은 개인키와 공개키에 대해 동일하며, 32바이트로 구성된다.

확장 개인키는 (k, c)로 표현하며, k는 일반 개인키, c는 체인코드이다. 확장 공개키는 (K, c)로 표현되며, K = point(k)이고 c는 체인코드이다.

각 확장 키에는 231개의 일반 자식 키와 231개의 단절된 자식 키가 있으며, 각 자식 키에는 인덱스가 있다. 일반 자식 키는 0~231-1까지의 인덱스를 사용하고, 단절된 자식 키는 231~232-1까지의 인덱스를 사용한다. 단절된 키 인덱스의 표기를 쉽게 하기 위해 숫자 iH는 i+231을 나타낸다.


자식 키 파생(CKD, Child key derivation) 함수

부모 확장 키와 인덱스 i가 주어지면 그에 해당하는 자식 확장 키를 계산할 수 있다. 이를 위한 알고리즘은 자식이 단절된 키인지 아닌지 (i가 231 이상인지 아닌지), 개인키인지 공개키인지에 따라 달라진다.


개인 부모 키 → 개인 자식 키

CKDpriv((kpar, cpar), i) → (ki, ci) 함수는 부모 확장 개인키로부터 자식 확장 키를 계산한다.

  • i ≥ 231인지 확인한다 (자식이 단절된 키인지 여부).
    • 만약 그렇다면 (단절된 자식): I = HMAC-SHA512(Key = cpar, Data = 0x00 || ser256(kpar) || ser32(i))로 한다. (참고: 0x00은 개인키를 33바이트 길이로 만들기 위해 패딩한다.)
    • 그렇지 않다면 (일반 자식): I = HMAC-SHA512(Key = cpar, Data = serP(point(kpar)) || ser32(i))로 한다.
  • I를 두 개의 32바이트 시퀀스 IL과 IR로 분할한다.
  • 반환된 자식 키 ki는 parse256(IL) + kpar(mod n)이다.
  • 반환된 체인코드 ci는 IR이다.
  • parse256(IL) ≥ n 또는 ki = 0인 경우, 결과 키는 유효하지 않으며, 다음 값으로 i를 진행해야 한다. (참고: 이는 1/2127보다 낮은 확률이다.)

HMAC-SHA512 함수는 RFC 4231에 정의되어 있다.


💡 패딩

패딩(Padding)은 데이터를 일정한 길이로 만들기 위해 추가하는 바이트를 의미한다.


공개 부모 키 → 공개 자식 키

CKDpub((Kpar, cpar), i) → (Ki, ci) 함수는 부모 확장 공개키에서 자식 확장 공개키를 계산한다. 이 함수는 단절되지 않은 자식 키에 대해서만 정의된다.

  • i ≥ 231인지 확인한다 (자식이 단절된 키인지 여부).
    • 만약 그렇다면 (단절된 자식): 실패를 반환한다.
    • 그렇지 않다면 (일반 자식): I = HMAC-SHA512(Key = cpar, Data = serP(Kpar) || ser32(i))로 한다.
  • I를 두 개의 32바이트 시퀀스 IL과 IR로 분할한다.
  • 반환된 자식 키 Ki는 point(parse256(IL)) + Kpar 이다.
  • 반환된 체인코드 ci는 IR이다.
  • parse256(IL) ≥ n 또는 Ki가 무한대의 점인 경우 결과 키는 유효하지 않으며, i의 다음 값으로 진행해야 한다.

개인 부모 키 → 공개 자식 키

N((k, c)) → (K, c) 함수는 확장된 개인키에 해당하는 확장된 공개키를 계산한다. (트랜잭션 서명 기능이 제거된 중립 버전)

  • 반환된 키 K는 point(k)이다.
  • 반환된 체인코드 c는 전달된 체인코드이다.

부모 개인키의 공개 자식 키를 계산하려면:

  • N(CKDpriv((kpar, cpar), i)) (항상 동작)
  • CKDpub(N(kpar, cpar), i) (단절되지 않은 자식 키에 대해서만 동작)

이 두 키가 동등하다는 사실이 단절되지 않은 키를 유용(개인키를 모르더라도 주어진 부모 키의 자식 공개키를 도출할 수 있음)하게 만드는 이유이다. 또한, 단절된 키와 구별되는 이유이기도 하다. (더 유용한) 단절되지 않은 키를 항상 사용하지 않는 이유는 보안 때문이다. 자세한 내용은 아래에서 확인할 수 있다.


공개 부모 키 → 개인 자식 키

불가능하다.


키 트리

다음 단계는 여러 개의 CKD 구성을 계단식으로 연결하여 트리를 만드는 것이다. 먼저, 하나의 루트인 마스터 확장 키 m부터 시작하여 여러 값 i에 대해 CKDpriv(m,i)를 평가함으로써 여러 개의 1레벨 파생 노드를 얻는다. 이들 각각은 다시 확장 키이므로 CKDpriv는 이들에게도 적용될 수 있다.

단축 표기법을 위해 CKDpriv(CKDpriv(CKDpriv(m,3H),2),5)를 m/3H/2/5로 표기한다. 공개키도 마찬가지로 CKDpub(CKDpub(CKDpub(M,3),2),5)을 M/3/2/5로 표기한다. 이렇게 할 때 다음과 같은 결과를 얻는다.

  • N(m/a/b/c) = N(m/a/b)/c = N(m/a)/b/c = N(m)/a/b/c = M/a/b/c.
  • N(m/aH/b/c) = N(m/aH/b)/c = N(m/aH)/b/c.

하지만, 후자는 불가능하기 때문에 N(m/aH)를 N(m)/aH로 다시 쓸 수 없다.

트리의 각 리프 노드는 실제 키에 해당하며, 내부 노드는 리프 노드에서 내려오는 키의 모음에 해당한다. 리프 노드의 체인코드는 무시되며, 내장된 개인키 또는 공개키만 관련이 있다. 이러한 구조로 인해 확장 개인키를 알면 모든 하위 개인키와 공개키를 재구성할 수 있고, 확장 공개키를 알면 모든 하위의 단절되지 않은 공개키를 재구성할 수 있다.


키 식별자

확장 키는 체인코드를 무시하고 직렬화된 ECDSA 공개키 K의 Hash160(SHA256 뒤의 RIPEMD160) 값으로 식별할 수 있다. 이는 기존 비트코인 주소에 사용된 데이터와 정확히 일치한다. 하지만 이 데이터는 주소로 해석될 수 있기 때문에 base58 형식으로 표현하는 것은 권장하지 않는다. (지갑 소프트웨어는 체인 키 자체에 대한 결제를 수락할 필요가 없다.)

식별자의 첫 32비트는 키 지문(fingerprint)이라고 한다.


직렬화 형식

확장 공개키와 개인키는 다음과 같이 직렬화 된다.

  • 4바이트: 버전 바이트 (메인넷: 0x0488B21E 공개, 0x0488ADE4 비공개 / 테스트넷: 0x043587CF 공개, 0x04358394 비공개)
  • 1바이트: 깊이: 마스터 노드의 경우 0x00, 레벨 1 파생 키의 경우 0x01
  • 4바이트: 부모 키의 지문 (마스터 키인 경우 0x00000000)
  • 4바이트: 자식 번호. xi = xpar/i에서 i에 대한 ser32(i)이며, xi는 직렬화되는 키다. (마스터 키인 경우 0x00000000)
  • 32바이트: 체인코드
  • 33바이트: 공개키 또는 개인키 데이터 (공개키의 경우 serP(K), 개인키의 경우 0x00 || ser256(k))

이 78바이트 구조는 다른 비트코인 데이터와 마찬가지로 먼저 32개의 체크섬 비트(이중 SHA256 체크섬에서 파생됨)를 추가한 다음 Base58 표현으로 변환하여 Base58로 인코딩 할 수 있다. 그 결과 최대 112글자의 Base58 인코딩 문자열이 생성된다. 버전 바이트의 선택으로 인해 Base58의 표현은 메인넷에서는 “xprv” 또는 “xpub”으로, 테스트넷에서는 “tprv” 또는 “tpub”으로 시작된다.

부모의 지문은 소프트웨어에서 부모 노드와 자식 노드를 빠르게 감지하는 방법으로만 사용되며, 소프트웨어는 충돌에 대처할 수 있어야 한다. 내부적으로는 전체 160비트 식별자를 사용할 수 있다.

직렬화된 확장 공개키를 가져올 때, 구현은 공개키 데이터의 X 좌표가 곡선의 한 점과 일치하는지 확인해야 한다. 그렇지 않은 경우 확장 공개키는 유효하지 않다.


마스터 키 생성

가능한 확장 키 쌍의 총 개수는 약 2512개이지만 생성된 키의 길이는 256비트에 불과하며 보안 측면에서는 그 절반 정도에 불과하다. 따라서 마스터 키는 직접 생성되지 않고 잠재적으로 짧은 시드 값에서 생성된다.

  • 선택된 길이(128~512비트 사이, 256비트가 권장됨)의 시드 바이트 시퀀스 S를 (P)RNG에서 생성한다.
  • I = HMAC-SHA512(키 = 비트코인 시드, 데이터 = S)를 계산한다.
  • I를 두 개의 32바이트 시퀀스 IL과 IR로 분할한다.
  • parse256(IL)을 마스터 비밀 키로, IR을 마스터 체인코드로 사용한다.

parse256(IL)이 0이거나, parse256(IL) ≥ n인 경우 마스터 키는 유효하지 않다.



명세: 지갑 구조

이전 장에서는 키 트리와 해당 노드를 지정했다. 다음 단계는 이 트리에 지갑 구조를 도입하는 것이다. 이 장에서 정의한 레이아웃은 기본값일 뿐이며, 모든 기능이 지원되지 않더라도 클라이언트는 호환성을 위해 이 레이아웃을 모방할 것을 권장한다.


기본 지갑 구성

HDW는 여러 개의 계정으로 구성된다. 계정은 번호가 매겨지며, 기본 계정(””)은 0번이다. 클라이언트는 두 개 이상의 계정을 지원할 필요는 없으며, 지원하지 않는 경우 기본 계정만 사용하면 된다.

각 계정은 내부 키체인과 외부 키체인 두 가지 키 쌍 체인으로 구성된다. 외부 키체인은 새 공개 주소를 생성하는데 사용되며, 내부 키체인은 그 외의 모든 작업(주소 변경, 주소 생성 등 전달할 필요가 없는 모든 작업)에 사용된다. 별도의 키체인을 지원하지 않는 클라이언트는 모든 작업에 대해 외부 키체인을 사용해야 한다.

  • m/iH/0/k는 마스터 m에서 파생된 HDW의 계정 번호 i에 대한 외부 체인의 k번째 키 쌍에 해당한다.
  • m/iH/1/k는 마스터 m에서 파생된 HDW의 계정 번호 i에 대한 내부 체인의 k번째 키 쌍에 해당한다.

활용 사례

전체 지갑 공유: m

두 시스템이 하나의 공유 지갑에 접근해야 하고, 두 시스템 모두 지출을 수행할 수 있어야 하는 경우, 마스터 개인 확장 키를 공유해야 한다. 노드는 외부 체인을 위해 N개의 look-ahead 키 풀을 캐시하여 들어오는 결제를 감시할 수 있다. 내부 체인에 대한 look-ahead는 격차가 예상되지 않기 때문에 매우 작을 수 있다. 사용하지 않은 첫 번째 계정의 체인에 대해 추가 look-ahead를 활성화하여 사용 시 계정 생성을 트리거 할 수 있다. 계정 이름은 여전히 수동으로 입력해야 하며, 블록체인을 통해 동기화 할 수 없다.


감사: N(m/*)

감사자가 수신 및 발신 결제 목록에 대한 전체 접근 권한이 필요한 경우, 모든 계정의 공개 확장 키를 공유할 수 있다. 이렇게 하면 감사자가 모든 계정에서 지갑과 주고 받는 모든 트랜잭션을 볼 수 있지만, 비밀키는 볼 수 없다.


지사별 잔고: m/iH

비즈니스에 여러 개의 독립된 지사가 있는 경우, 모두 단일 마스터에서 파생된 지갑을 사용할 수 있다. 이렇게 하면 본사에서 모든 지사의 모든 입출금 트랜잭션을 볼 수 있는 슈퍼 지갑을 관리할 수 있고, 지사 간 자금 이동도 허용할 수 있다.


반복적인 기업 간 거래: N(m/iH/0)

두 비즈니스 파트너가 자주 송금하는 경우, 특정 계정의 외부 체인에 대한 확장 공개키(M/iH/0)를 일종의 “슈퍼 주소”로 사용하여 (쉽게) 연결할 수 없는 잦은 거래를 허용하지만 매번 송금할 때마다 새 주소를 요청할 필요는 없다. 이러한 매커니즘은 마이닝 풀 운영자가 가변 지급 주소로 사용할 수 있다.


안전하지 않은 자금 수령인: N(m/iH/0)

보안되지 않은 웹 서버가 전자상거래 사이트를 운영하는데 사용되는 경우, 웹 서버는 결제를 받는데 사용되는 공개 주소를 알고 있어야 한다. 웹 서버는 단일 계정의 외부 체인에 대한 공개 확장 키만 알면 된다. 즉, 웹 서버에 불법적으로 접근하는 사용자는 기껏해야 들어오는 모든 결제만 볼 수 있을 뿐 돈을 훔칠 수는 없으며, 나가는 거래를 (사소하게) 구분할 수는 없다. 또한, 다른 웹 서버가 여러개 있는 경우 다른 웹 서버가 받은 결제도 볼 수 없다.


호환성

이 표준을 준수하려면 클라이언트는 최소한 확장된 공개키 또는 개인키를 가져와 직계 자손에게 지갑 키로 접근 권한을 부여할 수 있어야 한다. 명세의 두 번째 부분에 제시된 지갑 구조(마스터/계정/체인/서브 체인)는 권고사항일 뿐이며, 별도의 계정이나 내부 및 외부 체인을 구분하지 않더라도 쉽게 호환될 수 있도록 최소한의 구조로 제안되었다. 그러나 특정 요구사항에 따라 구현이 달라질 수 있으며, 더 복잡한 애플리케이션의 경우 더 복잡한 트리 구조가 필요할 수 있다.


보안

EC 공개키 암호화 자체에서 기대할 수 있는 것 외에도

  • 공개키 K가 주어지면 공격자는 EC 이산 로그 문제(2128개의 그룹 연산이 필요한 것으로 가정)를 푸는 것보다 더 효율적으로 해당 개인키를 찾을 수 없다.

이 표준의 의도된 보안 특성은 다음과 같다.

  • 자식 확장 키(ki, ci)와 정수 i가 주어졌을 때, 공격자는 2256개의 HMAC-SHA512 무차별 대입보다 더 효율적으로 부모 개인키 kpar를 찾을 수 없다.
  • 임의의 수(2 ≤ N ≤ 232-1)의 (인덱스, 확장 개인키) 튜플(ij, (kij, cij))이 주어졌을 때, 고유한 ij를 사용하여 공통 부모 확장 개인키에서 파생되었는지 여부를 결정한다. (즉, 다음과 같이) (0..N-1)의 각 j에 대해 CKDpriv((kpar, cpar), ij) = (kij, cij)가 존재하는지 여부를 결정하는 것은 HMAC-SHA512의 2256 무차별 대입보다 더 효율적으로 수행될 수 없다.

그러나 다음과 같은 속성은 존재하지 않는다.

  • 부모 확장 공개키(Kpar, cpar)와 자식 공개키(Ki)가 주어졌을 때, i를 찾기 어렵다.
  • 부모 확장 공개키(Kpar, cpar)와 단절되지 않은 자식 개인키(ki)가 주어졌을 때, kpar를 찾기 어렵다.

💡 튜플

튜플(Tuple)은 일련의 항목들이 순서를 가지는 집합을 의미한다. 튜플의 각 항목은 쉼표로 구분되며, 전체적으로 괄호로 둘러싸여 있다.


시사점

개인키와 공개키는 평소와 같이 안전하게 보관해야 한다. 개인키 유출은 코인에 대한 접근을 의미하며, 공개키 유출은 프라이버시 손실을 의미할 수 있다.

확장 키는 키의 전체 (하위)트리에 해당하므로, 확장 키에 대해서는 조금 더 주의를 기울여야 한다.

명확하지 않을 수 있는 한 가지 약점은 부모 확장 공개키와 이 키에서 내려오는 단절되지 않은 개인키를 아는 것은 부모 확장 개인키(이 키에서 내려오는 모든 개인키와 공개키)를 아는 것과 같다는 것이다. 이는 확장 공개키를 일반 공개키보다 더 신중하게 취급해야 한다는 것을 의미한다. 이는 또한 단절된 키가 존재하는 이유이며, 트리에서 계정 수준에 사용되는 이유이기도 하다. 이렇게 하면 계정별(또는 그 이하) 개인키가 유출되더라도 마스터 또는 다른 계정이 손상될 위험이 없다.


테스트 벡터

테스트 벡터 1

시드(Seed) (hex): 000102030405060708090a0b0c0d0e0f

  • 체인(Chain) m
    • 외부 공개키(ext pub): xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8
    • 외부 개인키(ext prv): xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi
  • 체인(Chain) m/0H
    • 외부 공개키(ext pub): xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw
    • 외부 개인키(ext prv): xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7
  • 체인(Chain) m/0H/1
    • 외부 공개키(ext pub): xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ
    • 외부 개인키(ext prv): xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs
  • 체인(Chain) m/0H/1/2H
    • 외부 공개키(ext pub): xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5
    • 외부 개인키(ext prv): xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM
  • 체인(Chain) m/0H/1/2H/2
    • 외부 공개키(ext pub): xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV
    • 외부 개인키(ext prv): xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334
  • 체인(Chain) m/0H/1/2H/2/1000000000
    • 외부 공개키(ext pub): xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy
    • 외부 개인키(ext prv): xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76

테스트 벡터 2

시드(Seed) (hex): fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542

  • 체인(Chain) m
    • 외부 공개키(ext pub): xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB
    • 외부 개인키(ext prv): xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U
  • 체인(Chain) m/0
    • 외부 공개키(ext pub): xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH
    • 외부 개인키(ext prv): xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt
  • 체인(Chain) m/0/2147483647H
    • 외부 공개키(ext pub): xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a
    • 외부 개인키(ext prv): xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9
  • 체인(Chain) m/0/2147483647H/1
    • 외부 공개키(ext pub): xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon
    • 외부 개인키(ext prv): xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef
  • 체인(Chain) m/0/2147483647H/1/2147483646H
    • 외부 공개키(ext pub): xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL
    • 외부 개인키(ext prv): xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc
  • 체인(Chain) m/0/2147483647H/1/2147483646H/2
    • 외부 공개키(ext pub): xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt
    • 외부 개인키(ext prv): xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j

테스트 벡터 3

이 벡터들은 전치 0이 유지되는지 테스트 한다. 자세한 내용은 bitpay/bitcore-lib#47iancoleman/bip39#58에서 확인할 수 있다.

시드(Seed) (hex): 4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be

  • 체인(Chain) m
    • 외부 공개키(ext pub): xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13
    • 외부 개인키(ext prv): xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6
  • 체인(Chain) m/0H
    • 외부 공개키(ext pub): xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y
    • 외부 개인키(ext prv): xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L

테스트 벡터 4

이 벡터들은 전치 0이 유지되는지 테스트 한다. 자세한 내용은 btcsuite/btcutil#172에서 확인할 수 있다.

시드(Seed) (hex): 3ddd5602285899a946114506157c7997e5444528f3003f6134712147db19b678

  • 체인(Chain) m
    • 외부 공개키(ext pub): xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa
    • 외부 개인키(ext prv): xprv9s21ZrQH143K48vGoLGRPxgo2JNkJ3J3fqkirQC2zVdk5Dgd5w14S7fRDyHH4dWNHUgkvsvNDCkvAwcSHNAQwhwgNMgZhLtQC63zxwhQmRv
  • 체인(Chain) m/0H
    • 외부 공개키(ext pub): xpub69AUMk3qDBi3uW1sXgjCmVjJ2G6WQoYSnNHyzkmdCHEhSZ4tBok37xfFEqHd2AddP56Tqp4o56AePAgCjYdvpW2PU2jbUPFKsav5ut6Ch1m
    • 외부 개인키(ext prv): xprv9vB7xEWwNp9kh1wQRfCCQMnZUEG21LpbR9NPCNN1dwhiZkjjeGRnaALmPXCX7SgjFTiCTT6bXes17boXtjq3xLpcDjzEuGLQBM5ohqkao9G
  • 체인(Chain) m/0H/1H
    • 외부 공개키(ext pub): xpub6BJA1jSqiukeaesWfxe6sNK9CCGaujFFSJLomWHprUL9DePQ4JDkM5d88n49sMGJxrhpjazuXYWdMf17C9T5XnxkopaeS7jGk1GyyVziaMt
    • 외부 개인키(ext prv): xprv9xJocDuwtYCMNAo3Zw76WENQeAS6WGXQ55RCy7tDJ8oALr4FWkuVoHJeHVAcAqiZLE7Je3vZJHxspZdFHfnBEjHqU5hG1Jaj32dVoS6XLT1

테스트 벡터 5

이 벡터들은 유효하지 않은 확장 키가 유효하지 않은 것으로 판단되는지 테스트 한다.

  • xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm (공개키 버전 / 개인키 불일치)
  • xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGTQQD3dC4H2D5GBj7vWvSQaaBv5cxi9gafk7NF3pnBju6dwKvH (개인키 버전 / 공개키 불일치)
  • xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Txnt3siSujt9RCVYsx4qHZGc62TG4McvMGcAUjeuwZdduYEvFn (잘못된 공개키 접두사 04)
  • xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFGpWnsj83BHtEy5Zt8CcDr1UiRXuWCmTQLxEK9vbz5gPstX92JQ (잘못된 개인키 접두사 04)
  • xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6N8ZMMXctdiCjxTNq964yKkwrkBJJwpzZS4HS2fxvyYUA4q2Xe4 (잘못된 공개키 접두사 01)
  • xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD9y5gkZ6Eq3Rjuahrv17fEQ3Qen6J (잘못된 개인키 접두사 01)
  • xprv9s2SPatNQ9Vc6GTbVMFPFo7jsaZySyzk7L8n2uqKXJen3KUmvQNTuLh3fhZMBoG3G4ZW1N2kZuHEPY53qmbZzCHshoQnNf4GvELZfqTUrcv (0이 아닌 부모 지문이 있는 0 깊이)
  • xpub661no6RGEX3uJkY4bNnPcw4URcQTrSibUZ4NqJEw5eBkv7ovTwgiT91XX27VbEXGENhYRCf7hyEbWrR3FewATdCEebj6znwMfQkhRYHRLpJ (0이 아닌 부모 지문이 있는 0 깊이)
  • xprv9s21ZrQH4r4TsiLvyLXqM9P7k1K3EYhA1kkD6xuquB5i39AU8KF42acDyL3qsDbU9NmZn6MsGSUYZEsuoePmjzsB3eFKSUEh3Gu1N3cqVUN (0이 아닌 인덱스가 있는 0 깊이)
  • xpub661MyMwAuDcm6CRQ5N4qiHKrJ39Xe1R1NyfouMKTTWcguwVcfrZJaNvhpebzGerh7gucBvzEQWRugZDuDXjNDRmXzSZe4c7mnTK97pTvGS8 (0이 아닌 인덱스가 있는 0 깊이)
  • DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHGMQzT7ayAmfo4z3gY5KfbrZWZ6St24UVf2Qgo6oujFktLHdHY4 (확장 키 버전 알 수 없음)
  • DMwo58pR1QLEFihHiXPVykYB6fJmsTeHvyTp7hRThAtCX8CvYzgPcn8XnmdfHPmHJiEDXkTiJTVV9rHEBUem2mwVbbNfvT2MTcAqj3nesx8uBf9 (확장 키 버전 알 수 없음)
  • xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21Teqt1VvEHx (개인키 0이 1..n-1에 없음)
  • xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzFAzHGBP2UuGCqWLTAPLcMtD5SDKr24z3aiUvKr9bJpdrcLg1y3G (개인키 0이 1..n-1에 없음)
  • xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6Q5JXayek4PRsn35jii4veMimro1xefsM58PgBMrvdYre8QyULY (유효하지 않은 공개키 020000000000000000000000000000000000000000000000000000000000000007)
  • xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHL (유효하지 않은 체크섬)

사사(Acknowledgement)

  • 그레고리 맥스웰(Gregory Maxwell): 유형 2 결정적 지갑에 대한 독창적인 아이디어와 이에 대한 많은 토론을 제공
  • 앨런 레이너(Alan Reiner): 이 방식을 아모리(Armory)에서 구현하고 이후 제안들을 제시
  • 에릭 롬브로조(Eric Lombrozo): BIP를 검토하고 수정
  • 마이크 콜드웰(Mike Caldwell): 사람이 인식할 수 있는 Base58 문자열을 얻기 위한 버전 바이트를 제공