2017-03-07 02:07:06 +01:00
|
|
|
#include <ccan/crypto/hkdf_sha256/hkdf_sha256.h>
|
|
|
|
#include <ccan/crypto/sha256/sha256.h>
|
2017-08-28 18:02:01 +02:00
|
|
|
#include <common/derive_basepoints.h>
|
|
|
|
#include <common/utils.h>
|
2018-07-09 13:17:59 +02:00
|
|
|
#include <wire/wire.h>
|
2017-03-07 02:07:06 +01:00
|
|
|
|
2018-07-09 13:17:58 +02:00
|
|
|
bool derive_basepoints(const struct secret *seed,
|
2017-03-07 02:07:06 +01:00
|
|
|
struct pubkey *funding_pubkey,
|
|
|
|
struct basepoints *basepoints,
|
|
|
|
struct secrets *secrets,
|
2017-06-20 08:10:03 +02:00
|
|
|
struct sha256 *shaseed)
|
2017-03-07 02:07:06 +01:00
|
|
|
{
|
|
|
|
struct keys {
|
2017-11-15 10:26:20 +01:00
|
|
|
struct privkey f, r, h, p, d;
|
2017-03-07 02:07:06 +01:00
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
2017-05-23 13:07:17 +02:00
|
|
|
if (secrets) {
|
|
|
|
secrets->funding_privkey = keys.f;
|
|
|
|
secrets->revocation_basepoint_secret = keys.r.secret;
|
|
|
|
secrets->payment_basepoint_secret = keys.p.secret;
|
2017-11-15 10:26:20 +01:00
|
|
|
secrets->htlc_basepoint_secret = keys.h.secret;
|
2017-05-23 13:07:17 +02:00
|
|
|
secrets->delayed_payment_basepoint_secret = keys.d.secret;
|
|
|
|
}
|
2017-03-07 02:07:06 +01:00
|
|
|
|
2017-05-23 13:07:17 +02:00
|
|
|
if (funding_pubkey) {
|
|
|
|
if (!pubkey_from_privkey(&keys.f, funding_pubkey))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (basepoints) {
|
|
|
|
if (!pubkey_from_privkey(&keys.r, &basepoints->revocation)
|
|
|
|
|| !pubkey_from_privkey(&keys.p, &basepoints->payment)
|
2017-11-15 10:26:20 +01:00
|
|
|
|| !pubkey_from_privkey(&keys.h, &basepoints->htlc)
|
2017-05-23 13:07:17 +02:00
|
|
|
|| !pubkey_from_privkey(&keys.d, &basepoints->delayed_payment))
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-07 02:07:06 +01:00
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
2018-06-17 12:11:53 +02:00
|
|
|
* A node:
|
|
|
|
* - MUST select an unguessable 256-bit seed for each connection,
|
|
|
|
* - MUST NOT reveal the seed.
|
2017-03-07 02:07:06 +01:00
|
|
|
*/
|
2017-05-23 13:07:17 +02:00
|
|
|
if (shaseed)
|
|
|
|
*shaseed = keys.shaseed;
|
2017-03-07 02:07:06 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2017-04-01 12:58:30 +02:00
|
|
|
|
2017-06-20 08:09:03 +02:00
|
|
|
void per_commit_secret(const struct sha256 *shaseed,
|
2018-07-09 13:17:58 +02:00
|
|
|
struct secret *commit_secret,
|
2017-06-20 08:09:03 +02:00
|
|
|
u64 per_commit_index)
|
2017-04-01 12:58:30 +02:00
|
|
|
{
|
2018-07-09 13:17:58 +02:00
|
|
|
struct sha256 s;
|
|
|
|
shachain_from_seed(shaseed, shachain_index(per_commit_index), &s);
|
|
|
|
|
|
|
|
BUILD_ASSERT(sizeof(s) == sizeof(*commit_secret));
|
|
|
|
memcpy(commit_secret, &s, sizeof(s));
|
2017-06-20 08:09:03 +02:00
|
|
|
}
|
2017-04-01 12:58:30 +02:00
|
|
|
|
2017-06-20 08:09:03 +02:00
|
|
|
bool per_commit_point(const struct sha256 *shaseed,
|
|
|
|
struct pubkey *commit_point,
|
|
|
|
u64 per_commit_index)
|
|
|
|
{
|
|
|
|
struct sha256 per_commit_secret;
|
2017-04-01 12:58:30 +02:00
|
|
|
|
|
|
|
/* Derive new per-commitment-point. */
|
2017-06-20 08:09:03 +02:00
|
|
|
shachain_from_seed(shaseed, shachain_index(per_commit_index),
|
2017-04-01 12:58:30 +02:00
|
|
|
&per_commit_secret);
|
|
|
|
|
|
|
|
/* BOLT #3:
|
|
|
|
*
|
2018-06-17 12:11:53 +02:00
|
|
|
* The `per_commitment_point` is generated using elliptic-curve
|
|
|
|
* multiplication:
|
2017-04-01 12:58:30 +02:00
|
|
|
*
|
2017-06-06 01:48:10 +02:00
|
|
|
* per_commitment_point = per_commitment_secret * G
|
2017-04-01 12:58:30 +02:00
|
|
|
*/
|
|
|
|
if (secp256k1_ec_pubkey_create(secp256k1_ctx,
|
2017-06-20 08:09:03 +02:00
|
|
|
&commit_point->pubkey,
|
2017-04-01 12:58:30 +02:00
|
|
|
per_commit_secret.u.u8) != 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2018-07-09 13:17:59 +02:00
|
|
|
|
2018-07-09 13:17:59 +02:00
|
|
|
bool derive_payment_basepoint(const struct secret *seed,
|
|
|
|
struct pubkey *payment_basepoint,
|
|
|
|
struct secret *payment_secret)
|
|
|
|
{
|
|
|
|
struct keys {
|
|
|
|
struct privkey f, r, h, p, d;
|
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
|
|
|
if (payment_basepoint) {
|
|
|
|
if (!pubkey_from_privkey(&keys.p, payment_basepoint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (payment_secret)
|
|
|
|
*payment_secret = keys.p.secret;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool derive_delayed_payment_basepoint(const struct secret *seed,
|
|
|
|
struct pubkey *delayed_payment_basepoint,
|
|
|
|
struct secret *delayed_payment_secret)
|
|
|
|
{
|
|
|
|
struct keys {
|
|
|
|
struct privkey f, r, h, p, d;
|
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
|
|
|
if (delayed_payment_basepoint) {
|
|
|
|
if (!pubkey_from_privkey(&keys.d, delayed_payment_basepoint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (delayed_payment_secret)
|
|
|
|
*delayed_payment_secret = keys.d.secret;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool derive_shaseed(const struct secret *seed, struct sha256 *shaseed)
|
|
|
|
{
|
|
|
|
struct keys {
|
|
|
|
struct privkey f, r, h, p, d;
|
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
*shaseed = keys.shaseed;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool derive_funding_key(const struct secret *seed,
|
|
|
|
struct pubkey *funding_pubkey,
|
|
|
|
struct privkey *funding_privkey)
|
|
|
|
{
|
|
|
|
struct privkey f;
|
|
|
|
|
|
|
|
hkdf_sha256(&f, sizeof(f), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
|
|
|
if (funding_pubkey) {
|
|
|
|
if (!pubkey_from_privkey(&f, funding_pubkey))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (funding_privkey)
|
|
|
|
*funding_privkey = f;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-23 04:23:02 +02:00
|
|
|
bool derive_revocation_basepoint(const struct secret *seed,
|
|
|
|
struct pubkey *revocation_basepoint,
|
|
|
|
struct secret *revocation_secret)
|
|
|
|
{
|
|
|
|
struct keys {
|
|
|
|
struct privkey f, r, h, p, d;
|
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
|
|
|
if (revocation_basepoint) {
|
|
|
|
if (!pubkey_from_privkey(&keys.r, revocation_basepoint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (revocation_secret)
|
|
|
|
*revocation_secret = keys.r.secret;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool derive_htlc_basepoint(const struct secret *seed,
|
|
|
|
struct pubkey *htlc_basepoint,
|
|
|
|
struct secret *htlc_secret)
|
|
|
|
{
|
|
|
|
struct keys {
|
|
|
|
struct privkey f, r, h, p, d;
|
|
|
|
struct sha256 shaseed;
|
|
|
|
} keys;
|
|
|
|
|
|
|
|
hkdf_sha256(&keys, sizeof(keys), NULL, 0, seed, sizeof(*seed),
|
|
|
|
"c-lightning", strlen("c-lightning"));
|
|
|
|
|
|
|
|
if (htlc_basepoint) {
|
|
|
|
if (!pubkey_from_privkey(&keys.h, htlc_basepoint))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (htlc_secret)
|
|
|
|
*htlc_secret = keys.h.secret;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-07-09 13:17:59 +02:00
|
|
|
void towire_basepoints(u8 **pptr, const struct basepoints *b)
|
|
|
|
{
|
|
|
|
towire_pubkey(pptr, &b->revocation);
|
|
|
|
towire_pubkey(pptr, &b->payment);
|
|
|
|
towire_pubkey(pptr, &b->htlc);
|
|
|
|
towire_pubkey(pptr, &b->delayed_payment);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fromwire_basepoints(const u8 **ptr, size_t *max,
|
|
|
|
struct basepoints *b)
|
|
|
|
{
|
|
|
|
fromwire_pubkey(ptr, max, &b->revocation);
|
|
|
|
fromwire_pubkey(ptr, max, &b->payment);
|
|
|
|
fromwire_pubkey(ptr, max, &b->htlc);
|
|
|
|
fromwire_pubkey(ptr, max, &b->delayed_payment);
|
|
|
|
}
|