Intro.
Public key와 address간 차이에 대해 궁금하여 리서치하던 중 이더리움 공식 문서상에서 다음과 같은 정의를 찾아내었다.
.
The public key is generated from the private key using the Elliptic Curve Digital Signature Algorithm(opens in a new tab). You get a public address for your account by taking the last 20 bytes of the Keccak-256 hash of the public key and adding 0x to the beginning.
즉, public key를 해시하여 나온 값의 마지막 20바이트를 헥사 스트링으로 변환한 후, 0x를 붙인것이 지갑 주소라는 것.
근데 생각해보면 정작, 개발할 때 하나의 ( private key - public key ) 페어를 가지고 우린 여러 개의 지갑 주소를 생성해낼 수 있다.
즉, 다음과 같은 가정을 해보았다.
- private key하나 가지고 여러개의 public key를 만들 수 있나?
- public key에서 address를 뽑아내는 과정에서 내가 모르는 로직이 존재하나?
결과론적으로는 2에 가까운데,
Addresses can use derivation paths to create multiple addresses from the same public key
derivation path이 친구에 대해 이해하기 위해 BIP32 - HD Wallet에 관한 이해가 필요하였다.
HD Wallet
BIP32는 일반적인 HD지갑을 만드는 방법에 대한 제안이다.
꼬리에 꼬리를 물듯, BIP-32를 논할때는 BIP-39(Mnemonic words), BIP-44(Multi account hierarchy for HD wallet)가 같이 나오던데 이번 글에서는 최대한 배제하고 이야기 하겠다.
간단하게 이야기하자면 다음과 같다.
BIP39 : mnemonic 구문에서 seed 구문을 뽑아내는 방법에관한 제안
여기서 seed 구문은 결정론적 지갑에서 private key & public key를 생성하는데 필요하다.
참고로 HD지갑 말고 Squential Deterministic Wallet도 존재하는데,
Sha256(seed구문 + n) , 여기서 n은 인덱스 ( 0 , 1, 2, 3, ...) 이라하는데, 관심없어서 여기까지만 하겠다.
1. seed 구문을 해시하여 Master private key(m) , Master publicKey(M) , Master chain code(c)를 추출한다.
seed 구문의 해시 결과, 512바이트를 정확히 양분하여 좌측이 private key, 우측이 public key가 된다.
처음보는 요상한 chain code는 CKD 함수(Child key derivation)에서 엔트로피 값으로 사용되는데, 지금 굳이 이해안하고 넘어가도 된다.
앞서 서론에서 말했듯, HD지갑은 자식 키(child key)를 생성할 수 있는데 일반(normal) / 강화(hardened) 타입의 자식 키를 생성할 수 있다.
해시 하는 과정(CDK 함수)에서, 부모의 private key를 넣느냐 혹은 public key를 넣느냐에 따라 자식 키의 타입이 달라진다.
private key를 넣으면 hardened , Public key를 넣으면 normal 타입이 된다.
자식 키 생성과정은 처음의 seed 구문에서 master key들을 생성하는 과정거의 유사하다.
단, 부모의 private key(m)를 넣을 경우, m + 해시 결과의 좌측 256bit를 합친것이 자식의 private key가 된다.
normal type의 자식 키의 경우, 위 과정에서 private key를 public key로 치환하면 된다.
해시 함수의 인자로 index라는 32비트의 값을 받는데, 이 값 또한 normal이냐 hardened이냐에 따라 값의 범위가 달라진다.
normal의 경우 0 ~ 2^31 -1
hardened의 경우 2^31 ~ 2^32 -1 이다.
자, 그렇다면 만약 위에서, m/1의 강화 자식 키를 생성하고 싶으면 어떻해야할까?
m/1의 private key = prv
m/1의 chainCode = m1c 라고 하자.
1. 자식 키의 chain code를 구한다.
m/1 의 인덱스가 1이므로, 인덱스 값에는 2^31 + 1 을 넣고, prv, m1c를 CDK함수에 넣어 자식 키의 chain code(cc)를 구한다.
이제 기존 인자에서 m1c만 cc로 교체하고 인덱스값을 다시 0부터 시작하여 CDK를 돌려 자식 개인키를 구할 수 있다.
Extended Keys
private key/ public key + chain code 를 extended private key / public key라 칭한다.
예를 들자면 다음과 같다.
private key : ef7ac307b3f5437768282886cbc23e6c8fda8855f05a8a2fee6318b7810714d1
chain code: a3ac24407a320f9fd80e2f896748a8c309a2e840b2137075cf82be33a30fbead
extended private key: ef7ac307b3f5437768282886cbc23e6c8fda8855f05a8a2fee6318b7810714d1a3ac24407a320f9fd80e2f896748a8c309a2e840b2137075cf82be33a30fbead
Extended public key의 경우, 오직 public key만 파생시킬 수 있는데, 이러한 특성 때문에 특정 지갑이 서명 혹은 거래 승인 같은 기능을 수행할 필요가 없을 경우 보안적인 측면에서 굉장히 유용하게 사용할 수 있다.
** Reference **
https://kwjdnjs.tistory.com/84
[비트코인 구조] BIP32: HD지갑(Hierarchical Deterministic Wallet)
미리 알아야 할 내용들 [비트코인 구조] BIP39: 니모닉(Mnemonic)과 시드(Seed) 미리 알아야 할 내용들 [블록체인 용어] 니모닉(Mnemonic) 코인을 보관하기 위해 개인 지갑을 이용하는 경우 사용자는 블록
kwjdnjs.tistory.com
'blockchain' 카테고리의 다른 글
[Cosmos + JS] ADR-036 구현하기 (1) | 2023.10.09 |
---|---|
[Ethereum] Message prefix용도 (2) | 2023.10.02 |
[Crypto] Signature Replay Attack (0) | 2023.10.02 |
[Ethereum]메세지 서명 (signMessage) (1) | 2023.10.02 |
SECP256k1 훝어보기 (0) | 2023.09.28 |