Skip to content

Commit

Permalink
BRBIP32PrivKeyPath()
Browse files Browse the repository at this point in the history
  • Loading branch information
voisine committed Sep 24, 2017
1 parent d0dbad3 commit 8256769
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 38 deletions.
72 changes: 34 additions & 38 deletions BRBIP32Sequence.c
Expand Up @@ -28,7 +28,6 @@
#include <string.h>
#include <assert.h>

#define BIP32_HARD 0x80000000
#define BIP32_SEED_KEY "Bitcoin seed"
#define BIP32_XPRV "\x04\x88\xAD\xE4"
#define BIP32_XPUB "\x04\x88\xB2\x1E"
Expand Down Expand Up @@ -158,9 +157,7 @@ size_t BRBIP32PubKey(uint8_t *pubKey, size_t pubKeyLen, BRMasterPubKey mpk, uint
// sets the private key for path m/0H/chain/index to key
void BRBIP32PrivKey(BRKey *key, const void *seed, size_t seedLen, uint32_t chain, uint32_t index)
{
assert(key != NULL);
assert(seed != NULL || seedLen == 0);
BRBIP32PrivKeyList(key, 1, seed, seedLen, chain, &index);
BRBIP32PrivKeyPath(key, seed, seedLen, 3, 0 | BIP32_HARD, chain, index);
}

// sets the private key for path m/0H/chain/index to each element in keys
Expand Down Expand Up @@ -194,6 +191,34 @@ void BRBIP32PrivKeyList(BRKey keys[], size_t keysCount, const void *seed, size_t
}
}

// sets the private key for the specified path to key
void BRBIP32PrivKeyPath(BRKey *key, const void *seed, size_t seedLen, int depth, ...)
{
UInt512 I;
UInt256 secret, chainCode;
va_list ap;

assert(key != NULL);
assert(seed != NULL || seedLen == 0);
assert(depth >= 0);

if (key && (seed || seedLen == 0)) {
BRHMAC(&I, BRSHA512, sizeof(UInt512), BIP32_SEED_KEY, strlen(BIP32_SEED_KEY), seed, seedLen);
secret = *(UInt256 *)&I;
chainCode = *(UInt256 *)&I.u8[sizeof(UInt256)];
var_clean(&I);
va_start(ap, depth);

for (int i = 0; i < depth; i++) {
_CKDpriv(&secret, &chainCode, va_arg(ap, uint32_t));
}

va_end(ap);
BRKeySetSecret(key, &secret, 1);
var_clean(&secret, &chainCode);
}
}

// writes the base58check encoded serialized master private key (xprv) to str
// returns number of bytes written including NULL terminator, or strLen needed if str is NULL
size_t BRBIP32SerializeMasterPrivKey(char *str, size_t strLen, const void *seed, size_t seedLen)
Expand Down Expand Up @@ -228,24 +253,7 @@ BRMasterPubKey BRBIP32ParseMasterPubKey(const char *str)
// key used for authenticated API calls, i.e. bitauth: https://github.com/bitpay/bitauth - path m/1H/0
void BRBIP32APIAuthKey(BRKey *key, const void *seed, size_t seedLen)
{
UInt512 I;
UInt256 secret, chainCode;

assert(key != NULL);
assert(seed != NULL || seedLen == 0);

if (key && (seed || seedLen == 0)) {
BRHMAC(&I, BRSHA512, sizeof(UInt512), BIP32_SEED_KEY, strlen(BIP32_SEED_KEY), seed, seedLen);
secret = *(UInt256 *)&I;
chainCode = *(UInt256 *)&I.u8[sizeof(UInt256)];
var_clean(&I);

_CKDpriv(&secret, &chainCode, 1 | BIP32_HARD); // path m/1H
_CKDpriv(&secret, &chainCode, 0); // path m/1H/0

BRKeySetSecret(key, &secret, 1);
var_clean(&secret, &chainCode);
}
BRBIP32PrivKeyPath(key, seed, seedLen, 2, 1 | BIP32_HARD, 0);
}

// key used for BitID: https://github.com/bitid/bitid/blob/master/BIP_draft.md
Expand All @@ -256,28 +264,16 @@ void BRBIP32BitIDKey(BRKey *key, const void *seed, size_t seedLen, uint32_t inde
assert(uri != NULL);

if (key && (seed || seedLen == 0) && uri) {
UInt512 I;
UInt256 secret, chainCode, hash;
UInt256 hash;
size_t uriLen = strlen(uri);
uint8_t data[sizeof(index) + uriLen];

UInt32SetLE(data, index);
memcpy(&data[sizeof(index)], uri, uriLen);
BRSHA256(&hash, data, sizeof(data));

BRHMAC(&I, BRSHA512, sizeof(UInt512), BIP32_SEED_KEY, strlen(BIP32_SEED_KEY), seed, seedLen);
secret = *(UInt256 *)&I;
chainCode = *(UInt256 *)&I.u8[sizeof(UInt256)];
var_clean(&I);

_CKDpriv(&secret, &chainCode, 13 | BIP32_HARD); // path m/13H
_CKDpriv(&secret, &chainCode, UInt32GetLE(&hash.u32[0]) | BIP32_HARD); // path m/13H/aH
_CKDpriv(&secret, &chainCode, UInt32GetLE(&hash.u32[1]) | BIP32_HARD); // path m/13H/aH/bH
_CKDpriv(&secret, &chainCode, UInt32GetLE(&hash.u32[2]) | BIP32_HARD); // path m/13H/aH/bH/cH
_CKDpriv(&secret, &chainCode, UInt32GetLE(&hash.u32[3]) | BIP32_HARD); // path m/13H/aH/bH/cH/dH

BRKeySetSecret(key, &secret, 1);
var_clean(&secret, &chainCode);
BRBIP32PrivKeyPath(key, seed, seedLen, 5, 13 | BIP32_HARD, UInt32GetLE(&hash.u32[0]) | BIP32_HARD,
UInt32GetLE(&hash.u32[1]) | BIP32_HARD, UInt32GetLE(&hash.u32[2]) | BIP32_HARD,
UInt32GetLE(&hash.u32[3]) | BIP32_HARD); // path m/13H/aH/bH/cH/dH
}
}

5 changes: 5 additions & 0 deletions BRBIP32Sequence.h
Expand Up @@ -37,6 +37,8 @@ extern "C" {
// BIP32 is a scheme for deriving chains of addresses from a seed value
// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki

#define BIP32_HARD 0x80000000

#define SEQUENCE_GAP_LIMIT_EXTERNAL 10
#define SEQUENCE_GAP_LIMIT_INTERNAL 5
#define SEQUENCE_EXTERNAL_CHAIN 0
Expand Down Expand Up @@ -64,6 +66,9 @@ void BRBIP32PrivKey(BRKey *key, const void *seed, size_t seedLen, uint32_t chain
// sets the private key for path m/0H/chain/index to each element in keys
void BRBIP32PrivKeyList(BRKey keys[], size_t keysCount, const void *seed, size_t seedLen, uint32_t chain,
const uint32_t indexes[]);

// sets the private key for the specified path to key
void BRBIP32PrivKeyPath(BRKey *key, const void *seed, size_t seedLen, int depth, ...);

// writes the base58check encoded serialized master private key (xprv) to str
// returns number of bytes written including NULL terminator, or strLen needed if str is NULL
Expand Down

1 comment on commit 8256769

@JasonCoombs
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.