2017-02-07 02:44:21 +01:00
|
|
|
#include <bitcoin/privkey.h>
|
|
|
|
#include <bitcoin/pubkey.h>
|
|
|
|
#include <ccan/crypto/sha256/sha256.h>
|
2017-08-28 18:05:01 +02:00
|
|
|
#include <common/key_derive.h>
|
2017-08-28 18:02:01 +02:00
|
|
|
#include <common/utils.h>
|
2017-03-07 02:01:55 +01:00
|
|
|
#include <wally_bip32.h>
|
2017-02-07 02:44:21 +01:00
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
2017-11-15 07:16:39 +01:00
|
|
|
* ### `localkey`, `remotekey`, `local_htlckey`, `remote_htlckey`, `local_delayedkey` and `remote_delayedkey` Derivation
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
|
|
|
* These keys are simply generated by addition from their base points:
|
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* pubkey = basepoint + SHA256(per_commitment_point || basepoint)*G
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* The `localkey` uses the local node's `payment_basepoint`, `remotekey`
|
|
|
|
* uses the remote node's `payment_basepoint`, the `local_delayedkey`
|
2017-11-15 07:16:39 +01:00
|
|
|
* uses the local node's `delayed_payment_basepoint`, the `local_htlckey`
|
|
|
|
* uses the local node's `htlc_basepoint` and the `remote_delayedkey` uses
|
|
|
|
* the remote node's `delayed_payment_basepoint`.
|
2017-02-07 02:44:21 +01:00
|
|
|
*/
|
|
|
|
bool derive_simple_key(const struct pubkey *basepoint,
|
|
|
|
const struct pubkey *per_commitment_point,
|
|
|
|
struct pubkey *key)
|
|
|
|
{
|
|
|
|
struct sha256 sha;
|
|
|
|
unsigned char der_keys[PUBKEY_DER_LEN * 2];
|
|
|
|
|
|
|
|
pubkey_to_der(der_keys, per_commitment_point);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, basepoint);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(per_commitment_point || basepoint)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n",
|
|
|
|
tal_hexstr(tmpctx, &sha, sizeof(sha)));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
*key = *basepoint;
|
|
|
|
if (secp256k1_ec_pubkey_tweak_add(secp256k1_ctx,
|
|
|
|
&key->pubkey, sha.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
|
|
|
printf("# + basepoint (0x%s)\n",
|
|
|
|
type_to_string(tmpctx, struct pubkey, basepoint));
|
|
|
|
printf("# = 0x%s\n",
|
|
|
|
type_to_string(tmpctx, struct pubkey, key));
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
|
|
|
* The corresponding private keys can be derived similarly if the basepoint
|
2017-11-15 07:16:39 +01:00
|
|
|
* secrets are known (i.e., `localkey`, `local_htlckey` and `local_delayedkey`
|
|
|
|
* only):
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* secretkey = basepoint_secret + SHA256(per_commitment_point || basepoint)
|
2017-02-07 02:44:21 +01:00
|
|
|
*/
|
2017-05-06 04:19:44 +02:00
|
|
|
bool derive_simple_privkey(const struct secret *base_secret,
|
2017-02-07 02:44:21 +01:00
|
|
|
const struct pubkey *basepoint,
|
|
|
|
const struct pubkey *per_commitment_point,
|
|
|
|
struct privkey *key)
|
|
|
|
{
|
|
|
|
struct sha256 sha;
|
|
|
|
unsigned char der_keys[PUBKEY_DER_LEN * 2];
|
|
|
|
|
|
|
|
pubkey_to_der(der_keys, per_commitment_point);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, basepoint);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(per_commitment_point || basepoint)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, &sha, sizeof(sha)));
|
|
|
|
#endif
|
|
|
|
|
2017-05-06 04:19:44 +02:00
|
|
|
key->secret = *base_secret;
|
|
|
|
if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data,
|
2017-02-07 02:44:21 +01:00
|
|
|
sha.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
|
|
|
printf("# + basepoint_secret (0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, base_secret, sizeof(*base_secret)));
|
|
|
|
printf("# = 0x%s\n",
|
|
|
|
tal_hexstr(tmpctx, key, sizeof(*key)));
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* The `revocationkey` is a blinded key: when a node wishes to create a new
|
|
|
|
* commitment for a remote node, it uses its own `revocation_basepoint` and
|
|
|
|
* the remote node's `per_commitment_point` to derive a new `revocationkey`
|
|
|
|
* for the commitment. Once the remote node reveals (thereby revoking that
|
|
|
|
* commitment) the `per_commitment_secret` used, the node can now derive the
|
|
|
|
* `revocationsecretkey` as they now know the two secrets necessary to derive
|
|
|
|
* the key (`revocation_basepoint_secret` and `per_commitment_secret`).
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* The `per_commitment_point` is generated using EC multiplication:
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* per_commitment_point = per_commitment_secret * G
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
|
|
|
* And this is used to derive the revocation key from the remote node's
|
2017-06-06 01:48:10 +02:00
|
|
|
* `revocation_basepoint`:
|
2017-02-07 02:44:21 +01:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* revocationkey = revocation_basepoint * SHA256(revocation_basepoint || per_commitment_point) + per_commitment_point*SHA256(per_commitment_point || revocation_basepoint)
|
2017-02-07 02:44:21 +01:00
|
|
|
*/
|
|
|
|
bool derive_revocation_key(const struct pubkey *basepoint,
|
|
|
|
const struct pubkey *per_commitment_point,
|
|
|
|
struct pubkey *key)
|
|
|
|
{
|
|
|
|
struct sha256 sha;
|
|
|
|
unsigned char der_keys[PUBKEY_DER_LEN * 2];
|
|
|
|
secp256k1_pubkey add[2];
|
|
|
|
const secp256k1_pubkey *args[2];
|
|
|
|
|
|
|
|
pubkey_to_der(der_keys, basepoint);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, per_commitment_point);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(revocation_basepoint || per_commitment_point)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))),
|
|
|
|
#endif
|
|
|
|
|
|
|
|
add[0] = basepoint->pubkey;
|
|
|
|
if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &add[0], sha.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# x revocation_basepoint = 0x%s\n",
|
2017-02-07 02:44:21 +01:00
|
|
|
type_to_string(tmpctx, secp256k1_pubkey, &add[0]));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pubkey_to_der(der_keys, per_commitment_point);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, basepoint);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(per_commitment_point || revocation_basepoint)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))),
|
|
|
|
#endif
|
|
|
|
|
|
|
|
add[1] = per_commitment_point->pubkey;
|
|
|
|
if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &add[1], sha.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# x per_commitment_point = 0x%s\n",
|
2017-02-07 02:44:21 +01:00
|
|
|
type_to_string(tmpctx, secp256k1_pubkey, &add[1]));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
args[0] = &add[0];
|
|
|
|
args[1] = &add[1];
|
|
|
|
if (secp256k1_ec_pubkey_combine(secp256k1_ctx, &key->pubkey, args, 2)
|
|
|
|
!= 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
#ifdef SUPERVERBOSE
|
|
|
|
printf("# 0x%s + 0x%s => 0x%s\n",
|
|
|
|
type_to_string(tmpctx, secp256k1_pubkey, args[0]),
|
|
|
|
type_to_string(tmpctx, secp256k1_pubkey, args[1]),
|
|
|
|
type_to_string(tmpctx, struct pubkey, key));
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* The corresponding private key can be derived once the `per_commitment_secret`
|
2017-02-07 02:44:21 +01:00
|
|
|
* is known:
|
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* revocationsecretkey = revocation_basepoint_secret * SHA256(revocation_basepoint || per_commitment_point) + per_commitment_secret*SHA256(per_commitment_point || revocation_basepoint)
|
2017-02-07 02:44:21 +01:00
|
|
|
*/
|
2017-05-06 04:19:44 +02:00
|
|
|
bool derive_revocation_privkey(const struct secret *base_secret,
|
|
|
|
const struct secret *per_commitment_secret,
|
2017-02-07 02:44:21 +01:00
|
|
|
const struct pubkey *basepoint,
|
|
|
|
const struct pubkey *per_commitment_point,
|
|
|
|
struct privkey *key)
|
|
|
|
{
|
|
|
|
struct sha256 sha;
|
|
|
|
unsigned char der_keys[PUBKEY_DER_LEN * 2];
|
2017-05-06 04:19:44 +02:00
|
|
|
struct secret part2;
|
2017-02-07 02:44:21 +01:00
|
|
|
|
|
|
|
pubkey_to_der(der_keys, basepoint);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, per_commitment_point);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(revocation_basepoint || per_commitment_point)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))),
|
|
|
|
#endif
|
|
|
|
|
2017-05-06 04:19:44 +02:00
|
|
|
key->secret = *base_secret;
|
|
|
|
if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, key->secret.data,
|
|
|
|
sha.u.u8)
|
2017-02-07 02:44:21 +01:00
|
|
|
!= 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# * revocation_basepoint_secret (0x%s)",
|
2017-02-07 02:44:21 +01:00
|
|
|
tal_hexstr(tmpctx, base_secret, sizeof(*base_secret))),
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, key, sizeof(*key))),
|
|
|
|
#endif
|
|
|
|
|
|
|
|
pubkey_to_der(der_keys, per_commitment_point);
|
|
|
|
pubkey_to_der(der_keys + PUBKEY_DER_LEN, basepoint);
|
|
|
|
sha256(&sha, der_keys, sizeof(der_keys));
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# SHA256(per_commitment_point || revocation_basepoint)\n");
|
2017-02-07 02:44:21 +01:00
|
|
|
printf("# => SHA256(0x%s || 0x%s)\n",
|
|
|
|
tal_hexstr(tmpctx, der_keys, PUBKEY_DER_LEN),
|
|
|
|
tal_hexstr(tmpctx, der_keys + PUBKEY_DER_LEN, PUBKEY_DER_LEN));
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, sha.u.u8, sizeof(sha.u.u8))),
|
|
|
|
#endif
|
|
|
|
|
|
|
|
part2 = *per_commitment_secret;
|
2017-05-06 04:19:44 +02:00
|
|
|
if (secp256k1_ec_privkey_tweak_mul(secp256k1_ctx, part2.data,
|
2017-02-07 02:44:21 +01:00
|
|
|
sha.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
#ifdef SUPERVERBOSE
|
2017-06-06 01:48:10 +02:00
|
|
|
printf("# * per_commitment_secret (0x%s)",
|
2017-02-07 02:44:21 +01:00
|
|
|
tal_hexstr(tmpctx, per_commitment_secret,
|
|
|
|
sizeof(*per_commitment_secret))),
|
|
|
|
printf("# = 0x%s\n", tal_hexstr(tmpctx, &part2, sizeof(part2)));
|
|
|
|
#endif
|
|
|
|
|
2017-05-06 04:19:44 +02:00
|
|
|
if (secp256k1_ec_privkey_tweak_add(secp256k1_ctx, key->secret.data,
|
|
|
|
part2.data) != 1)
|
2017-02-07 02:44:21 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
#ifdef SUPERVERBOSE
|
|
|
|
printf("# => 0x%s\n", tal_hexstr(tmpctx, key, sizeof(*key)));
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
2017-03-07 02:01:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
bool bip32_pubkey(const struct ext_key *bip32_base,
|
|
|
|
struct pubkey *pubkey, u32 index)
|
|
|
|
{
|
|
|
|
struct ext_key ext;
|
|
|
|
|
|
|
|
if (index >= BIP32_INITIAL_HARDENED_CHILD)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (bip32_key_from_parent(bip32_base, index,
|
|
|
|
BIP32_FLAG_KEY_PUBLIC, &ext) != WALLY_OK)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey->pubkey,
|
|
|
|
ext.pub_key, sizeof(ext.pub_key)))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|