libbtc
bitcoinclibrary
bip32.c
Go to the documentation of this file.
1 
26 #include "btc/bip32.h"
27 
28 #include <assert.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <inttypes.h>
33 
34 #include "btc/base58.h"
35 #include "btc/ecc.h"
36 
37 #include "ripemd160.h"
38 #include "sha2.h"
39 #include "utils.h"
40 
41 // write 4 big endian bytes
42 static void write_be(uint8_t* data, uint32_t x)
43 {
44  data[0] = x >> 24;
45  data[1] = x >> 16;
46  data[2] = x >> 8;
47  data[3] = x;
48 }
49 
50 
51 // read 4 big endian bytes
52 static uint32_t read_be(const uint8_t* data)
53 {
54  return (((uint32_t)data[0]) << 24) |
55  (((uint32_t)data[1]) << 16) |
56  (((uint32_t)data[2]) << 8) |
57  (((uint32_t)data[3]));
58 }
59 
60 
61 btc_bool btc_hdnode_from_seed(const uint8_t* seed, int seed_len, btc_hdnode* out)
62 {
64  memset(out, 0, sizeof(btc_hdnode));
65  out->depth = 0;
66  out->fingerprint = 0x00000000;
67  out->child_num = 0;
68  hmac_sha512((const uint8_t*)"Bitcoin seed", 12, seed, seed_len, I);
69  memcpy(out->private_key, I, BTC_ECKEY_PKEY_LENGTH);
70 
72  memset(I, 0, sizeof(I));
73  return false;
74  }
75 
78  memset(I, 0, sizeof(I));
79  return true;
80 }
81 
82 
84 {
85  uint8_t data[1 + 32 + 4];
86  uint8_t I[32 + BTC_BIP32_CHAINCODE_SIZE];
87  uint8_t fingerprint[32];
88 
89  if (i & 0x80000000) { // private derivation
90  return false;
91  } else { // public derivation
92  memcpy(data, inout->public_key, BTC_ECKEY_COMPRESSED_LENGTH);
93  }
95 
97  ripemd160(fingerprint, 32, fingerprint);
98  inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) + (fingerprint[2] << 8) + fingerprint[3];
99 
100  memset(inout->private_key, 0, 32);
101 
102  int failed = 0;
103  hmac_sha512(inout->chain_code, 32, data, sizeof(data), I);
104  memcpy(inout->chain_code, I + 32, BTC_BIP32_CHAINCODE_SIZE);
105 
106 
107  if (!ecc_public_key_tweak_add(inout->public_key, I))
108  failed = false;
109 
110  if (!failed) {
111  inout->depth++;
112  inout->child_num = i;
113  }
114 
115  // Wipe all stack data.
116  memset(data, 0, sizeof(data));
117  memset(I, 0, sizeof(I));
118  memset(fingerprint, 0, sizeof(fingerprint));
119 
120  return failed ? false : true;
121 }
122 
123 
125 {
126  uint8_t data[1 + BTC_ECKEY_PKEY_LENGTH + 4];
128  uint8_t fingerprint[BTC_BIP32_CHAINCODE_SIZE];
130 
131  if (i & 0x80000000) { // private derivation
132  data[0] = 0;
133  memcpy(data + 1, inout->private_key, BTC_ECKEY_PKEY_LENGTH);
134  } else { // public derivation
135  memcpy(data, inout->public_key, BTC_ECKEY_COMPRESSED_LENGTH);
136  }
138 
139  sha256_Raw(inout->public_key, BTC_ECKEY_COMPRESSED_LENGTH, fingerprint);
140  ripemd160(fingerprint, 32, fingerprint);
141  inout->fingerprint = (fingerprint[0] << 24) + (fingerprint[1] << 16) +
142  (fingerprint[2] << 8) + fingerprint[3];
143 
144  memset(fingerprint, 0, sizeof(fingerprint));
145  memcpy(p, inout->private_key, BTC_ECKEY_PKEY_LENGTH);
146 
147  hmac_sha512(inout->chain_code, BTC_BIP32_CHAINCODE_SIZE, data, sizeof(data), I);
149  memcpy(inout->private_key, I, BTC_ECKEY_PKEY_LENGTH);
150 
151  memcpy(z, inout->private_key, BTC_ECKEY_PKEY_LENGTH);
152 
153  int failed = 0;
154  if (!ecc_verify_privatekey(z)) {
155  failed = 1;
156  return false;
157  }
158 
159  memcpy(inout->private_key, p, BTC_ECKEY_PKEY_LENGTH);
160  if (!ecc_private_key_tweak_add(inout->private_key, z)) {
161  failed = 1;
162  }
163 
164  if (!failed) {
165  inout->depth++;
166  inout->child_num = i;
168  }
169 
170  memset(data, 0, sizeof(data));
171  memset(I, 0, sizeof(I));
172  memset(p, 0, sizeof(p));
173  memset(z, 0, sizeof(z));
174  return true;
175 }
176 
177 
179 {
180  size_t outsize = BTC_ECKEY_COMPRESSED_LENGTH;
181  ecc_get_pubkey(node->private_key, node->public_key, &outsize, true);
182 }
183 
184 
185 static void btc_hdnode_serialize(const btc_hdnode* node, uint32_t version, char use_public, char* str, int strsize)
186 {
187  uint8_t node_data[78];
188  write_be(node_data, version);
189  node_data[4] = node->depth;
190  write_be(node_data + 5, node->fingerprint);
191  write_be(node_data + 9, node->child_num);
192  memcpy(node_data + 13, node->chain_code, BTC_BIP32_CHAINCODE_SIZE);
193  if (use_public) {
194  memcpy(node_data + 45, node->public_key, BTC_ECKEY_COMPRESSED_LENGTH);
195  } else {
196  node_data[45] = 0;
197  memcpy(node_data + 46, node->private_key, BTC_ECKEY_PKEY_LENGTH);
198  }
199  btc_base58_encode_check(node_data, 78, str, strsize);
200 }
201 
202 
203 void btc_hdnode_serialize_public(const btc_hdnode* node, const btc_chain* chain, char* str, int strsize)
204 {
205  btc_hdnode_serialize(node, chain->b58prefix_bip32_pubkey, 1, str, strsize);
206 }
207 
208 
209 void btc_hdnode_serialize_private(const btc_hdnode* node, const btc_chain* chain, char* str, int strsize)
210 {
211  btc_hdnode_serialize(node, chain->b58prefix_bip32_privkey, 0, str, strsize);
212 }
213 
214 
215 // check for validity of curve point in case of public data not performed
216 btc_bool btc_hdnode_deserialize(const char* str, const btc_chain* chain, btc_hdnode* node)
217 {
218  uint8_t node_data[strlen(str)];
219  memset(node, 0, sizeof(btc_hdnode));
220  size_t outlen = 0;
221 
222  outlen = btc_base58_decode_check(str, node_data, sizeof(node_data));
223  if (!outlen) {
224  return false;
225  }
226  uint32_t version = read_be(node_data);
227  if (version == chain->b58prefix_bip32_pubkey) { // public node
228  memcpy(node->public_key, node_data + 45, BTC_ECKEY_COMPRESSED_LENGTH);
229  } else if (version == chain->b58prefix_bip32_privkey) { // private node
230  if (node_data[45]) { // invalid data
231  return false;
232  }
233  memcpy(node->private_key, node_data + 46, BTC_ECKEY_PKEY_LENGTH);
235  } else {
236  return false; // invalid version
237  }
238  node->depth = node_data[4];
239  node->fingerprint = read_be(node_data + 5);
240  node->child_num = read_be(node_data + 9);
241  memcpy(node->chain_code, node_data + 13, BTC_BIP32_CHAINCODE_SIZE);
242  return true;
243 }
244 
245 btc_bool btc_hd_generate_key(btc_hdnode* node, const char* keypath, const uint8_t* privkeymaster, const uint8_t* chaincode)
246 {
247  static char delim[] = "/";
248  static char prime[] = "phH\'";
249  static char digits[] = "0123456789";
250  uint64_t idx = 0;
251  assert(strlens(keypath) < 1024);
252  char* pch, *kp = malloc(strlens(keypath) + 1);
253 
254  if (!kp) {
255  return false;
256  }
257 
258  if (strlens(keypath) < strlens("m/")) {
259  goto err;
260  }
261 
262  memset(kp, 0, strlens(keypath) + 1);
263  memcpy(kp, keypath, strlens(keypath));
264 
265  if (kp[0] != 'm' || kp[1] != '/') {
266  goto err;
267  }
268 
269  node->depth = 0;
270  node->child_num = 0;
271  node->fingerprint = 0;
272  memcpy(node->chain_code, chaincode, BTC_BIP32_CHAINCODE_SIZE);
273  memcpy(node->private_key, privkeymaster, BTC_ECKEY_PKEY_LENGTH);
275 
276  pch = strtok(kp + 2, delim);
277  while (pch != NULL) {
278  size_t i = 0;
279  int prm = 0;
280  for (; i < strlens(pch); i++) {
281  if (strchr(prime, pch[i])) {
282  if (i != strlens(pch) - 1) {
283  goto err;
284  }
285  prm = 1;
286  } else if (!strchr(digits, pch[i])) {
287  goto err;
288  }
289  }
290 
291  idx = strtoull(pch, NULL, 10);
292  if (idx > UINT32_MAX) {
293  goto err;
294  }
295 
296  if (prm) {
297  if (btc_hdnode_private_ckd_prime(node, idx) != true) {
298  goto err;
299  }
300  } else {
301  if (btc_hdnode_private_ckd(node, idx) != true) {
302  goto err;
303  }
304  }
305  pch = strtok(NULL, delim);
306  }
307  free(kp);
308  return true;
309 
310 err:
311  free(kp);
312  return false;
313 }
btc_bool btc_hdnode_private_ckd(btc_hdnode *inout, uint32_t i)
Definition: bip32.c:124
uint8_t btc_bool
Definition: btc.h:34
uint8_t private_key[BTC_ECKEY_PKEY_LENGTH]
Definition: bip32.h:47
#define strlens(s)
Definition: utils.h:40
btc_bool btc_hd_generate_key(btc_hdnode *node, const char *keypath, const uint8_t *privkeymaster, const uint8_t *chaincode)
derive btc_hdnode including private key from master private key
Definition: bip32.c:245
void ecc_get_pubkey(const uint8_t *private_key, uint8_t *public_key, size_t *in_outlen, btc_bool compressed)
get public key from given private key
#define BTC_ECKEY_PKEY_LENGTH
Definition: btc.h:70
uint32_t b58prefix_bip32_pubkey
Definition: chain.h:46
void btc_hdnode_serialize_private(const btc_hdnode *node, const btc_chain *chain, char *str, int strsize)
Definition: bip32.c:209
uint32_t child_num
Definition: bip32.h:45
#define BTC_ECKEY_COMPRESSED_LENGTH
Definition: btc.h:68
uint32_t b58prefix_bip32_privkey
private key
Definition: chain.h:45
void sha256_Raw(const sha2_byte *data, size_t len, uint8_t digest[SHA256_DIGEST_LENGTH])
Definition: sha2.c:652
uint32_t depth
Definition: bip32.h:43
void btc_hdnode_fill_public_key(btc_hdnode *node)
Definition: bip32.c:178
int btc_base58_decode_check(const char *str, uint8_t *data, size_t datalen)
Definition: base58.c:219
uint32_t fingerprint
Definition: bip32.h:44
uint8_t chain_code[BTC_BIP32_CHAINCODE_SIZE]
Definition: bip32.h:46
btc_bool ecc_public_key_tweak_add(uint8_t *public_key_inout, const uint8_t *tweak)
ec mul tweak on given public key
static uint32_t read_be(const uint8_t *data)
Definition: bip32.c:52
uint8_t public_key[BTC_ECKEY_COMPRESSED_LENGTH]
Definition: bip32.h:48
void ripemd160(const uint8_t *msg, uint32_t msg_len, uint8_t *hash)
Definition: ripemd160.c:292
static void write_be(uint8_t *data, uint32_t x)
Definition: bip32.c:42
btc_bool ecc_private_key_tweak_add(uint8_t *private_key, const uint8_t *tweak)
ec mul tweak on given private key
static void btc_hdnode_serialize(const btc_hdnode *node, uint32_t version, char use_public, char *str, int strsize)
Definition: bip32.c:185
int btc_base58_encode_check(const uint8_t *data, int datalen, char *str, int strsize)
Definition: base58.c:198
#define BTC_BIP32_CHAINCODE_SIZE
Definition: bip32.h:39
btc_bool btc_hdnode_from_seed(const uint8_t *seed, int seed_len, btc_hdnode *out)
Definition: bip32.c:61
#define btc_hdnode_private_ckd_prime(X, I)
Definition: bip32.h:52
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac)
Definition: sha2.c:996
btc_bool ecc_verify_privatekey(const uint8_t *private_key)
verifies a given 32byte key
void btc_hdnode_serialize_public(const btc_hdnode *node, const btc_chain *chain, char *str, int strsize)
Definition: bip32.c:203
btc_bool btc_hdnode_deserialize(const char *str, const btc_chain *chain, btc_hdnode *node)
Definition: bip32.c:216
btc_bool btc_hdnode_public_ckd(btc_hdnode *inout, uint32_t i)
Definition: bip32.c:83