비트코인을 거래할 때 우리는 공개키를 해싱하여 만든 비트코인 주소를 사용합니다.
그리고 공개키는 타원곡선 암호화를 이용하여 개인키로부터 유도되는데요
공개키를 유도하는 개인키는 0부터 2256보다 약간 작은 소수인
2 256-232-29-28-27-26-24-1 = 1.1579208923731619542357098500869 * 1077
사이의 값을 사용합니다.
이 때 소수를 사용하는 이유는 타원곡선암호화 시 위수를 소수로 정해야만 K(공개키) = k(개인키) * G 를 계산할 때 k(개인키)값에 따라 중복되는 K(공개키)가 없기 때문이에요
비트코인 주소를 만들었다고 땡이 아니라 우리는 거래내역 서명을 하고, 주소를 복구하려면 이 수를 기억하고 있어야만 하고 돈을 도둑맞기 싫다면 다른 사람이 이 숫자를 절대로 몰라야 합니다.
꽤나 어려운 요청이죠? 그래도 개인키 한 개정도는 어떻게든 안전하게 관리할 수 있을 것같아요!
하지만 여러 번을 거래할 때 한 주소만 사용하게 되면 블록체인에 저장될 때 내 주소가 기록되어 누군가가 내 주소를 주시하며 감시할 수도 있기 때문에 거래 때마다 새 주소를 사용하는게 좋은데요
그래서 거래 때마다 새로운 개인키를 만들었다고 칩시다. 거래를 하면 할수록 개인키가 마구마구 늘어날거예요 @_@)) (이렇게 저장하고 있는 지갑을 비결정적 지갑이라 해요)
이렇게 엄청나게 늘어난 개인키는 사용하기도 힘들고 백업도 힘들거예요
내 비밀번호가 '철수123'이라면 여기에 숫자를 붙여서 간단하게 '철수1230', '철수12300'처럼 새로운 비밀번호를 만들 수 있는 것 처럼 '철수123'에 해당하는 값만 기억하면 되도록 만든다면 사용하기 편리하지 않을까요?
이러한 아이디어를 보여준 제안이 BIP32입니다.
BIP32에서는 '철수123'에 해당하는 Master Seed값을 128~256bits entropy(무작위 값)를 사용합니다.
Master Seed -> Master Node 과정에서 HMAC-SHA256방식으로 갖고잊는 값을 512bits값으로 해시화 시킵니다.
SHA256이 아닌 HMAC-SHA256을 쓰는 이유는 SHA256이 Merkle-Damgard construction에 기반하여 해시 길이 확장 공격에 취약하기 때문입니다!
그 뒤의 CKD는 똑같이 HMAC-SHA256로 해시화 하지만 과정이 앞에서와는 조금 달라요.
해시화된 512bits 값을 256bits + 256bits로 나눠서 하나는 개인키로, 하나는 Chain code(체인코드)로 나누고
이 개인키를 타원곡선 암호화를 이용해 공개키를 만들어서 공개키 + 체인코드 + 32bits 인덱스 숫자(0 ~ 20억개의 자식키를 만들 수 있어요) 를 이어붙여서 HMAC-SHA256 해시화를 하여 또 해시화된 512bits 값을 얻습니다(계속 반복되면서 계층화(Hierarchical)되는 거예요)
이 그림은 BIP32의 개념을 보여주는데요 BIP 43과 44에서 추가된 개념도 약간 포함되어 있어요!
BIP43과 44의 개념을 간단하게 말하자면
우리의 집주소개념과 비슷합니다 '경기도 성남시 분당구 판교로' 이런식으로요
BIP43는 주소를 사용하자! 라는 의견이고
BIP44는 계층을
m / purpose' / coin type' / account' / change / address index 로 규정했어요.
여기서 '는 단절 유도법을 이야기합니다
단절 유도법이 나온 이유는 앞의 방법은 개인키가 유출되면 개인키와 체인코드를 이용해서 그 개인키의 하위 개인 키와 체인코드를 계속해서 알아낼 수 있는 문제가 있기 때문이에요!
단절 유도법은 개인키 + 체인코드 + 32bits 인덱스 숫자(0 ~ 20억개의 자식키를 만들 수 있어요)를 HMAC-SHA256로 해시시키는 것을 말합니다.
차례대로 설명하면
m: Entropy값입니다
purpose': 항상 44로 맞추어져있어요
coin type': 코인의 종류로 0은 비트코인, 1은 비트코인 테스트넷, 2는 라이트코인입니다!
account': 회사에서 법무부용, 회계부용 등 조직적인 용도로 세분화시킬 수 있도록 나누어둔 계층이에요
// 여기부터 정규유도법을 사용한 이유는 보안이 약한 곳에서도 주소를 받기 위해서에요
change: 0은 수신 주소, 1은 잔액을 받는 주소로 사용해요
address index: 0~ 20억개 주소들을 나타냅니다!
BIP32에서 Master Seed값만 기억하면 파생되는 개인키들은 외울 필요가 없다고했죠?
이 Master seed를 더 편하게 기억할 방법은 없을까요?
이에 대한 제안이 BIP39에서 니모닉 코드의 형태로 보여줍니다.
니모닉 코드 + 추가 비밀번호를 이용해서 Master Seed를 만드는 방법이예요.
먼저 니모닉 코드가 만들어지는 과정을 볼까요?
1번은 우리가 가지고 있는 128bits의 랜덤한 값이예요
2번은 이 값을 SHA256으로 해시화하여 맨 앞의 4bits를 저장해서 랜덤 값이 바뀌었는지 확인하는 용도(3번)로 사용해요
(해시는 글자가 하나만 바뀌어도 값이 완전히 바뀌기 때문에 일부만 사용해도 충분해요)
(여기서 4bits를 한 이유는 단지 11로 나누어 떨어지게 하기위해서 그런거예요
192bits라면 Checksum을 6bits로 해서 11로 나누어 떨어지게,
256bits면 8bits로 해서 나누어 떨어지는 식이예요)
각각의 11bits는 미리 정해진 단어리스트에서 일치하는 단어로 변경되어서 사용자에게 보여주게됩니다. 이제 0과 1로 이루어진 긴 숫자 대신 단어들만 외우면 되는거예요!
니모닉 코드에서는 passphrase를 추가하는 기능도 제공하는데요.
이 기능은 니모닉 코드가 단어들의 나열인 만큼 나도 기억하기 쉽지만 다른 사람들도 기억하기 쉽기 떄문에 나만 아는 값을 추가해서 누군가 니모닉 코드를 알게되더라도 이 값을 모르면 의미가 없도록 합니다.
- salting을 하는이유
https://d2.naver.com/helloworld/318732
마지막으로 그림에서 Key Streching Function이란 값의 길이를 늘려주는 함수이고
2048rounds는 함수는 2048번 반복한다는 말입니다.
이런 과정을 통해 512bits Master Seed를 얻을 수 있어요.
이런 HDwallet을 만드는 과정을 담은 여러 오픈소스 코드들이 있지만 그 중에서 eth-lightwallet를 사용한 HDwallet코드입니다
https://github.com/dik654/beb-sprint-MnemonicWallet