본문으로 바로가기

Libbitcoin 라이브러리를 사용하여 계층결정적 지갑(HD 지갑)에서의 마스터키와 유도된 자식키의 생성에 대해서 작성해보겠습니다.

계층결정적 지갑의 이론적 배경에 대해서는 이전 포스팅을 참고하시기 바랍니다.

하기의 예제는 다음 사이트의 Tutorial에서 사용된 코드입니다.

http://aaronjaramillo.org/libbitcoin-hd-keys


하기의 작성코드는 다음의 github에서 다운로드 받을수 있습니다.

https://github.com/ihpark92/Libbitcoin_Tutorial


먼저 Libbitcoin 을 사용하기 위한 선언을 해줍니다.

#include <bitcoin/bitcoin.hpp>
#include <string.h>
#include <iostream>
using namespace bc;


다음에 의사난수를 생성하기 위해 16바이트의 data chunk 배열을 선언하고, 의사난수 생성기를 사용하여 16바이트(128비트) 의 랜덤값을 생성합니다. 128비트의 난수값을 base16 엔코딩을 통해 출력하기 때문에 출력값은 32개의 Hex 값으로 출력이 될것입니다.

int main(void)
{
data_chunk seedChunk(16);
pseudo_random_fill(seedChunk);
std::cout << "\nHex Seed: " << std::endl;
std::cout << encode_base16(seedChunk)<< std::endl;


다음에 128비트의 랜덤값을 사용하여 연상기호  단어열을 생성합니다.

128비트의 값을 사용하기 때문에 생성되는 단어열은 12개가 될것입니다.

wallet::word_list writtenWord = wallet::create_mnemonic(seedChunk);
if(wallet::validate_mnemonic(writtenWord))
{
for(auto i = writtenWord.begin(); i != writtenWord.end(); ++i)
std::cout << *i << ' ';
}else
{
std::cout << "mnemonic invalid!" << std::endl;
}


위에서 생성된 랜덤값을 사용하여 개인키를 생성하고, encoded 매쏘드를 사용하여 base58 포맷으로 출력합니다.

wallet::hd_private privateKey(seedChunk);
std::cout << "\n\nMaster Private Key: " << std::endl;
std::cout << privateKey.encoded() << std::endl;


개인키로부터 to_hd_key() 매쏘드를 통해 raw 포맷의 개인키를 얻고, base16 엔코딩을 하여 hex 포맷으로 개인키를 출력합니다.

wallet::hd_key keys = privateKey.to_hd_key();
std::cout << "\nHex Master Private Key: " << std::endl;
std::cout << encode_base16(keys) << std::endl;


개인키를 통해 공개키를 생성해내고, base58 포맷으로 엔코딩하여 출력합니다.

wallet::hd_public publicKey = privateKey.to_public();
std::cout << "\nMaster Public Key: " << std::endl;
std::cout << publicKey.encoded() << std::endl;


개인키를 통해서 1 인덱스의 유도된 자식 개인키와 공개키를 생성하고 base58 포맷으로 엔코딩하여 출력합니다.

wallet::hd_private childPrivateKey = privateKey.derive_private(1);
std::cout << "\nChild Private Key: " << std::endl;
std::cout << childPrivateKey.encoded() << std::endl;
wallet::hd_public childPublicKey = privateKey.derive_public(1);
std::cout << "\nChild Public Key: " << std::endl;
std::cout << publicKey.encoded() << std::endl;


유도된 자식 공개키를 사용하여 비트코인 주소를 생성하고 base58 포맷으로 엔코딩하여 출력합니다.

std::cout << "\nPayment Adress: " << std::endl;
std::cout << wallet::ec_public(childPublicKey.point()).to_payment_address().encoded()<< "\n" << std::endl;


출력결과는 다음과 같습니다.

ihpark92@ubuntu:~/work$ ./HD_key
Hex Seed:
c6343e966440d61d17423e81bfef3746
shiver peanut pitch silk aspect attend fringe elephant like youth soccer mind
Master Private Key:
xprv9s21ZrQH143K2CspDbSR9pNddmpvjZWpGV4KoZ2bc9d3RgthSDLreyTb72UFwwZowQjTwBBLaRceNgLwdjL77SccLQuQsp6vB8rujhW1xEp
Hex Master Private Key:
0488ade40000000000000000000ec10abb36391b6aebb63d3697b8d1c61fd6f66d274b06945f9cc42c41cd40a000df61edf0d6426ebc85
f94e0668b053b1801f3ac40dcc7dd948d4ba329030d603731b412d
Master Public Key:
xpub661MyMwAqRbcEgxHKcyRWxKNBofR92EfdhyvbwSDAVA2JVDqykf7Cmn4xGoRNgqjSPh4SkXXzQ8GUr42KAUEr53q2N8bpfpu8tznqZWm5fM
Child Private Key:
xprv9vfdCPd3QdEeYdDEGBjV2gSVkdwcDLButpskBgm88hgKTQR6CaaQnKCrHhF2YSiKW652bazqYdLATouWi5fZaiYo4YRs1Y3TXF4Cr6Boxjd
Child Public Key:
xpub661MyMwAqRbcEgxHKcyRWxKNBofR92EfdhyvbwSDAVA2JVDqykf7Cmn4xGoRNgqjSPh4SkXXzQ8GUr42KAUEr53q2N8bpfpu8tznqZWm5fM
Payment Adress:
1Bngpmye1f91RDtStQAVS2b9NsbNYhhK1K
ihpark92@ubuntu:~/work$