mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
pubkey: pubkey_eq helper.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e7856e6e69
commit
242fa1b2dd
@ -6,6 +6,6 @@ void bitcoin_address(const struct pubkey *key, struct bitcoin_address *addr)
|
||||
{
|
||||
struct sha256 h;
|
||||
|
||||
sha256(&h, key->key, pubkey_len(key));
|
||||
sha256(&h, key->der, pubkey_derlen(key));
|
||||
ripemd160(&addr->addr, h.u.u8, sizeof(h));
|
||||
}
|
||||
|
@ -275,7 +275,6 @@ bool key_from_base58(const char *base58, size_t base58_len,
|
||||
bool compressed;
|
||||
secp256k1_context *secpctx;
|
||||
size_t keylen;
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
BN_init(&bn);
|
||||
if (!raw_decode_base58(&bn, base58, base58_len))
|
||||
@ -312,19 +311,11 @@ bool key_from_base58(const char *base58, size_t base58_len,
|
||||
if (!secp256k1_ec_seckey_verify(secpctx, priv->secret))
|
||||
goto fail_free_secpctx;
|
||||
|
||||
/* Get public key, too. */
|
||||
/* FIXME: Don't convert. */
|
||||
if (!secp256k1_ec_pubkey_create(secpctx, &pubkey, priv->secret))
|
||||
/* Get public key, too, since we know if it's compressed. */
|
||||
if (!pubkey_from_privkey(priv, key,
|
||||
compressed ? SECP256K1_EC_COMPRESSED : 0))
|
||||
goto fail_free_secpctx;
|
||||
|
||||
memset(key, 0, sizeof(*key));
|
||||
if (!secp256k1_ec_pubkey_serialize(secpctx, key->key, &keylen,
|
||||
&pubkey,
|
||||
compressed
|
||||
? SECP256K1_EC_COMPRESSED : 0))
|
||||
goto fail_free_secpctx;
|
||||
assert(keylen == pubkey_len(key));
|
||||
|
||||
BN_free(&bn);
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <assert.h>
|
||||
#include "pubkey.h"
|
||||
#include "privkey.h"
|
||||
|
||||
/* Must agree on key validity with bitcoin! Stolen from bitcoin/src/pubkey.h's
|
||||
* GetLen:
|
||||
@ -18,29 +19,76 @@ static unsigned int GetLen(unsigned char chHeader)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pubkey_valid(const u8 *first_char, size_t len)
|
||||
size_t pubkey_derlen(const struct pubkey *key)
|
||||
{
|
||||
if (len < 1)
|
||||
return false;
|
||||
return (len == GetLen(*first_char));
|
||||
}
|
||||
|
||||
size_t pubkey_len(const struct pubkey *key)
|
||||
{
|
||||
size_t len = GetLen(key->key[0]);
|
||||
size_t len = GetLen(key->der[0]);
|
||||
|
||||
assert(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
bool pubkey_from_hexstr(const char *str, struct pubkey *key)
|
||||
bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key)
|
||||
{
|
||||
size_t slen = strlen(str), dlen;
|
||||
dlen = hex_data_size(slen);
|
||||
secp256k1_context *secpctx = secp256k1_context_create(0);
|
||||
|
||||
if (dlen != 33 && dlen != 65)
|
||||
return false;
|
||||
if (!hex_decode(str, slen, key->key, dlen))
|
||||
return false;
|
||||
return GetLen(key->key[0]) == dlen;
|
||||
if (len > sizeof(key->der))
|
||||
goto fail_free_secpctx;
|
||||
|
||||
memcpy(key->der, der, len);
|
||||
if (!secp256k1_ec_pubkey_parse(secpctx, &key->pubkey, key->der, len))
|
||||
goto fail_free_secpctx;
|
||||
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return true;
|
||||
|
||||
fail_free_secpctx:
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Pubkey from privkey */
|
||||
bool pubkey_from_privkey(const struct privkey *privkey,
|
||||
struct pubkey *key,
|
||||
unsigned int compressed_flags)
|
||||
{
|
||||
secp256k1_context *secpctx;
|
||||
size_t outlen;
|
||||
|
||||
secpctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
if (!secp256k1_ec_pubkey_create(secpctx, &key->pubkey, privkey->secret))
|
||||
goto fail_free_secpctx;
|
||||
|
||||
if (!secp256k1_ec_pubkey_serialize(secpctx, key->der, &outlen,
|
||||
&key->pubkey, compressed_flags))
|
||||
goto fail_free_secpctx;
|
||||
assert(outlen == pubkey_derlen(key));
|
||||
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return true;
|
||||
|
||||
fail_free_secpctx:
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pubkey_from_hexstr(const char *derstr, struct pubkey *key)
|
||||
{
|
||||
size_t slen = strlen(derstr), dlen;
|
||||
unsigned char der[65];
|
||||
|
||||
dlen = hex_data_size(slen);
|
||||
if (dlen > sizeof(der))
|
||||
return false;
|
||||
|
||||
if (!hex_decode(derstr, slen, der, dlen))
|
||||
return false;
|
||||
|
||||
return pubkey_from_der(der, dlen, key);
|
||||
}
|
||||
|
||||
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b)
|
||||
{
|
||||
return pubkey_derlen(a) == pubkey_derlen(b)
|
||||
&& memcmp(a->der, b->der, pubkey_derlen(a)) == 0;
|
||||
}
|
||||
|
@ -2,18 +2,31 @@
|
||||
#define LIGHTNING_BITCOIN_PUBKEY_H
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include "secp256k1.h"
|
||||
|
||||
struct privkey;
|
||||
|
||||
struct pubkey {
|
||||
u8 key[65];
|
||||
/* DER-encoded key (as hashed by bitcoin, for addresses) */
|
||||
u8 der[65];
|
||||
/* Unpacked pubkey (as used by libsecp256k1 internally) */
|
||||
secp256k1_pubkey pubkey;
|
||||
};
|
||||
|
||||
/* 33 or 65 bytes? */
|
||||
size_t pubkey_len(const struct pubkey *key);
|
||||
/* Convert from hex string of DER (scriptPubKey from validateaddress) */
|
||||
bool pubkey_from_hexstr(const char *derstr, struct pubkey *key);
|
||||
|
||||
/* Convert from hex string (scriptPubKey from validateaddress) */
|
||||
bool pubkey_from_hexstr(const char *str, struct pubkey *key);
|
||||
/* Pubkey from privkey */
|
||||
bool pubkey_from_privkey(const struct privkey *privkey,
|
||||
struct pubkey *key,
|
||||
unsigned int compressed_flags);
|
||||
|
||||
/* For conversion routines in protobuf_convert.c */
|
||||
bool pubkey_valid(const u8 *first_char, size_t len);
|
||||
/* Pubkey from DER encoding. */
|
||||
bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key);
|
||||
|
||||
/* How many bytes of key->der are valid. */
|
||||
size_t pubkey_derlen(const struct pubkey *key);
|
||||
|
||||
/* Are these keys equal? */
|
||||
bool pubkey_eq(const struct pubkey *a, const struct pubkey *b);
|
||||
#endif /* LIGHTNING_PUBKEY_H */
|
||||
|
@ -94,7 +94,7 @@ static void add_number(u8 **script, u32 num)
|
||||
|
||||
static void add_push_key(u8 **scriptp, const struct pubkey *key)
|
||||
{
|
||||
add_push_bytes(scriptp, key->key, pubkey_len(key));
|
||||
add_push_bytes(scriptp, key->der, pubkey_derlen(key));
|
||||
}
|
||||
|
||||
static void add_push_sig(u8 **scriptp, const struct bitcoin_signature *sig)
|
||||
@ -128,10 +128,10 @@ static void add_push_le32(u8 **scriptp, u32 val)
|
||||
static bool key_less(const struct pubkey *a, const struct pubkey *b)
|
||||
{
|
||||
/* Shorter one wins. */
|
||||
if (pubkey_len(a) != pubkey_len(b))
|
||||
return pubkey_len(a) < pubkey_len(b);
|
||||
if (pubkey_derlen(a) != pubkey_derlen(b))
|
||||
return pubkey_derlen(a) < pubkey_derlen(b);
|
||||
|
||||
return memcmp(a->key, b->key, pubkey_len(a)) < 0;
|
||||
return memcmp(a->der, b->der, pubkey_derlen(a)) < 0;
|
||||
}
|
||||
|
||||
/* tal_count() gives the length of the script. */
|
||||
|
@ -152,26 +152,18 @@ static bool check_signed_hash(const struct sha256_double *hash,
|
||||
{
|
||||
int ret;
|
||||
secp256k1_context *secpctx;
|
||||
/* FIXME: Don't convert here! */
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
if (!secpctx)
|
||||
return false;
|
||||
|
||||
if (!secp256k1_ec_pubkey_parse(secpctx, &pubkey, key->key,
|
||||
pubkey_len(key))) {
|
||||
secp256k1_context_destroy(secpctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_SCHNORR
|
||||
ret = secp256k1_schnorr_verify(secpctx, (unsigned char *)signature,
|
||||
hash->sha.u.u8, &pubkey);
|
||||
hash->sha.u.u8, &key->pubkey);
|
||||
#else
|
||||
ret = secp256k1_ecdsa_verify(secpctx,
|
||||
(secp256k1_ecdsa_signature *)signature,
|
||||
hash->sha.u.u8, &pubkey);
|
||||
hash->sha.u.u8, &key->pubkey);
|
||||
#endif
|
||||
|
||||
secp256k1_context_destroy(secpctx);
|
||||
|
@ -41,22 +41,20 @@ bool proto_to_signature(const Signature *pb, struct signature *sig)
|
||||
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, const struct pubkey *key)
|
||||
{
|
||||
BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
|
||||
struct pubkey check;
|
||||
|
||||
bitcoin_pubkey__init(p);
|
||||
p->key.len = pubkey_len(key);
|
||||
p->key.data = tal_dup_arr(p, u8, key->key, p->key.len, 0);
|
||||
p->key.len = pubkey_derlen(key);
|
||||
p->key.data = tal_dup_arr(p, u8, key->der, p->key.len, 0);
|
||||
|
||||
assert(pubkey_valid(p->key.data, p->key.len));
|
||||
assert(pubkey_from_der(p->key.data, p->key.len, &check));
|
||||
assert(pubkey_eq(&check, key));
|
||||
return p;
|
||||
}
|
||||
|
||||
bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key)
|
||||
{
|
||||
if (!pubkey_valid(pb->key.data, pb->key.len))
|
||||
return false;
|
||||
|
||||
memcpy(key->key, pb->key.data, pb->key.len);
|
||||
return true;
|
||||
return pubkey_from_der(pb->key.data, pb->key.len, key);
|
||||
}
|
||||
|
||||
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash)
|
||||
|
@ -79,8 +79,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
@ -77,8 +77,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->final_key, &pubkey2))
|
||||
errx(1, "Invalid o1 final pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->final_key, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
@ -60,8 +60,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
@ -99,11 +99,9 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->final_key, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
||||
if (pubkey_len(&key) == pubkey_len(&pubkey1)
|
||||
&& memcmp(key.key, pubkey1.key, pubkey_len(&pubkey1)) == 0) {
|
||||
if (pubkey_eq(&key, &pubkey1)) {
|
||||
own_commit_tx = true;
|
||||
} else if (pubkey_len(&key) == pubkey_len(&pubkey2)
|
||||
&& memcmp(key.key, pubkey2.key, pubkey_len(&pubkey2)) == 0) {
|
||||
} else if (pubkey_eq(&key, &pubkey2)) {
|
||||
own_commit_tx = false;
|
||||
} else
|
||||
errx(1, "Privkey doesn't match either key");
|
||||
|
@ -77,8 +77,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->final_key, &pubkey2))
|
||||
errx(1, "Invalid o1 final pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->final_key, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
@ -74,8 +74,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
@ -77,8 +77,7 @@ int main(int argc, char *argv[])
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o1 commit pubkey");
|
||||
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|
||||
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
|
||||
if (!pubkey_eq(&pubkey1, &pubkey2))
|
||||
errx(1, "o1 pubkey != this privkey");
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
Loading…
Reference in New Issue
Block a user