Browse Source

pubkey: pubkey_eq helper.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 10 years ago
parent
commit
242fa1b2dd
  1. 2
      bitcoin/address.c
  2. 15
      bitcoin/base58.c
  3. 76
      bitcoin/pubkey.c
  4. 27
      bitcoin/pubkey.h
  5. 8
      bitcoin/script.c
  6. 12
      bitcoin/signature.c
  7. 14
      protobuf_convert.c
  8. 3
      test-cli/close-channel.c
  9. 3
      test-cli/create-commit-spend-tx.c
  10. 3
      test-cli/create-commit-tx.c
  11. 6
      test-cli/create-htlc-spend-tx.c
  12. 3
      test-cli/create-steal-tx.c
  13. 3
      test-cli/update-channel-accept.c
  14. 3
      test-cli/update-channel-signature.c

2
bitcoin/address.c

@ -6,6 +6,6 @@ void bitcoin_address(const struct pubkey *key, struct bitcoin_address *addr)
{ {
struct sha256 h; 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)); ripemd160(&addr->addr, h.u.u8, sizeof(h));
} }

15
bitcoin/base58.c

@ -275,7 +275,6 @@ bool key_from_base58(const char *base58, size_t base58_len,
bool compressed; bool compressed;
secp256k1_context *secpctx; secp256k1_context *secpctx;
size_t keylen; size_t keylen;
secp256k1_pubkey pubkey;
BN_init(&bn); BN_init(&bn);
if (!raw_decode_base58(&bn, base58, base58_len)) 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)) if (!secp256k1_ec_seckey_verify(secpctx, priv->secret))
goto fail_free_secpctx; goto fail_free_secpctx;
/* Get public key, too. */ /* Get public key, too, since we know if it's compressed. */
/* FIXME: Don't convert. */ if (!pubkey_from_privkey(priv, key,
if (!secp256k1_ec_pubkey_create(secpctx, &pubkey, priv->secret)) compressed ? SECP256K1_EC_COMPRESSED : 0))
goto fail_free_secpctx; 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); BN_free(&bn);
secp256k1_context_destroy(secpctx); secp256k1_context_destroy(secpctx);
return true; return true;

76
bitcoin/pubkey.c

@ -1,6 +1,7 @@
#include <ccan/str/hex/hex.h> #include <ccan/str/hex/hex.h>
#include <assert.h> #include <assert.h>
#include "pubkey.h" #include "pubkey.h"
#include "privkey.h"
/* Must agree on key validity with bitcoin! Stolen from bitcoin/src/pubkey.h's /* Must agree on key validity with bitcoin! Stolen from bitcoin/src/pubkey.h's
* GetLen: * GetLen:
@ -18,29 +19,76 @@ static unsigned int GetLen(unsigned char chHeader)
return 0; return 0;
} }
bool pubkey_valid(const u8 *first_char, size_t len) size_t pubkey_derlen(const struct pubkey *key)
{ {
if (len < 1) size_t len = GetLen(key->der[0]);
return false;
return (len == GetLen(*first_char)); assert(len);
return len;
} }
size_t pubkey_len(const struct pubkey *key) bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key)
{ {
size_t len = GetLen(key->key[0]); secp256k1_context *secpctx = secp256k1_context_create(0);
assert(len); if (len > sizeof(key->der))
return len; 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;
} }
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)
{ {
size_t slen = strlen(str), dlen; secp256k1_context *secpctx;
dlen = hex_data_size(slen); 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 (dlen != 33 && dlen != 65) 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; return false;
if (!hex_decode(str, slen, key->key, dlen))
if (!hex_decode(derstr, slen, der, dlen))
return false; return false;
return GetLen(key->key[0]) == dlen;
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;
} }

27
bitcoin/pubkey.h

@ -2,18 +2,31 @@
#define LIGHTNING_BITCOIN_PUBKEY_H #define LIGHTNING_BITCOIN_PUBKEY_H
#include <ccan/short_types/short_types.h> #include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h> #include <ccan/tal/tal.h>
#include "secp256k1.h"
struct privkey;
struct pubkey { 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? */ /* Convert from hex string of DER (scriptPubKey from validateaddress) */
size_t pubkey_len(const struct pubkey *key); bool pubkey_from_hexstr(const char *derstr, struct pubkey *key);
/* Pubkey from privkey */
bool pubkey_from_privkey(const struct privkey *privkey,
struct pubkey *key,
unsigned int compressed_flags);
/* Convert from hex string (scriptPubKey from validateaddress) */ /* Pubkey from DER encoding. */
bool pubkey_from_hexstr(const char *str, struct pubkey *key); bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key);
/* For conversion routines in protobuf_convert.c */ /* How many bytes of key->der are valid. */
bool pubkey_valid(const u8 *first_char, size_t len); 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 */ #endif /* LIGHTNING_PUBKEY_H */

8
bitcoin/script.c

@ -94,7 +94,7 @@ static void add_number(u8 **script, u32 num)
static void add_push_key(u8 **scriptp, const struct pubkey *key) 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) 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) static bool key_less(const struct pubkey *a, const struct pubkey *b)
{ {
/* Shorter one wins. */ /* Shorter one wins. */
if (pubkey_len(a) != pubkey_len(b)) if (pubkey_derlen(a) != pubkey_derlen(b))
return pubkey_len(a) < pubkey_len(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. */ /* tal_count() gives the length of the script. */

12
bitcoin/signature.c

@ -152,26 +152,18 @@ static bool check_signed_hash(const struct sha256_double *hash,
{ {
int ret; int ret;
secp256k1_context *secpctx; secp256k1_context *secpctx;
/* FIXME: Don't convert here! */
secp256k1_pubkey pubkey;
secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
if (!secpctx) if (!secpctx)
return false; return false;
if (!secp256k1_ec_pubkey_parse(secpctx, &pubkey, key->key,
pubkey_len(key))) {
secp256k1_context_destroy(secpctx);
return false;
}
#ifdef USE_SCHNORR #ifdef USE_SCHNORR
ret = secp256k1_schnorr_verify(secpctx, (unsigned char *)signature, ret = secp256k1_schnorr_verify(secpctx, (unsigned char *)signature,
hash->sha.u.u8, &pubkey); hash->sha.u.u8, &key->pubkey);
#else #else
ret = secp256k1_ecdsa_verify(secpctx, ret = secp256k1_ecdsa_verify(secpctx,
(secp256k1_ecdsa_signature *)signature, (secp256k1_ecdsa_signature *)signature,
hash->sha.u.u8, &pubkey); hash->sha.u.u8, &key->pubkey);
#endif #endif
secp256k1_context_destroy(secpctx); secp256k1_context_destroy(secpctx);

14
protobuf_convert.c

@ -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 *pubkey_to_proto(const tal_t *ctx, const struct pubkey *key)
{ {
BitcoinPubkey *p = tal(ctx, BitcoinPubkey); BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
struct pubkey check;
bitcoin_pubkey__init(p); bitcoin_pubkey__init(p);
p->key.len = pubkey_len(key); p->key.len = pubkey_derlen(key);
p->key.data = tal_dup_arr(p, u8, key->key, p->key.len, 0); 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; return p;
} }
bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key) bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key)
{ {
if (!pubkey_valid(pb->key.data, pb->key.len)) return pubkey_from_der(pb->key.data, pb->key.len, key);
return false;
memcpy(key->key, pb->key.data, pb->key.len);
return true;
} }
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash) Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash)

3
test-cli/close-channel.c

@ -79,8 +79,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2)) if (!proto_to_pubkey(o1->commit_key, &pubkey2))
errx(1, "Invalid o1 commit pubkey"); errx(1, "Invalid o1 commit pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->commit_key, &pubkey2)) if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey"); errx(1, "Invalid o2 commit pubkey");

3
test-cli/create-commit-spend-tx.c

@ -77,8 +77,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->final_key, &pubkey2)) if (!proto_to_pubkey(o1->final_key, &pubkey2))
errx(1, "Invalid o1 final pubkey"); errx(1, "Invalid o1 final pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->final_key, &pubkey2)) if (!proto_to_pubkey(o2->final_key, &pubkey2))
errx(1, "Invalid o2 final pubkey"); errx(1, "Invalid o2 final pubkey");

3
test-cli/create-commit-tx.c

@ -60,8 +60,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2)) if (!proto_to_pubkey(o1->commit_key, &pubkey2))
errx(1, "Invalid o1 commit pubkey"); errx(1, "Invalid o1 commit pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->commit_key, &pubkey2)) if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey"); errx(1, "Invalid o2 commit pubkey");

6
test-cli/create-htlc-spend-tx.c

@ -99,11 +99,9 @@ int main(int argc, char *argv[])
if (!proto_to_pubkey(o2->final_key, &pubkey2)) if (!proto_to_pubkey(o2->final_key, &pubkey2))
errx(1, "Invalid o2 final pubkey"); errx(1, "Invalid o2 final pubkey");
if (pubkey_len(&key) == pubkey_len(&pubkey1) if (pubkey_eq(&key, &pubkey1)) {
&& memcmp(key.key, pubkey1.key, pubkey_len(&pubkey1)) == 0) {
own_commit_tx = true; own_commit_tx = true;
} else if (pubkey_len(&key) == pubkey_len(&pubkey2) } else if (pubkey_eq(&key, &pubkey2)) {
&& memcmp(key.key, pubkey2.key, pubkey_len(&pubkey2)) == 0) {
own_commit_tx = false; own_commit_tx = false;
} else } else
errx(1, "Privkey doesn't match either key"); errx(1, "Privkey doesn't match either key");

3
test-cli/create-steal-tx.c

@ -77,8 +77,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->final_key, &pubkey2)) if (!proto_to_pubkey(o1->final_key, &pubkey2))
errx(1, "Invalid o1 final pubkey"); errx(1, "Invalid o1 final pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->final_key, &pubkey2)) if (!proto_to_pubkey(o2->final_key, &pubkey2))
errx(1, "Invalid o2 final pubkey"); errx(1, "Invalid o2 final pubkey");

3
test-cli/update-channel-accept.c

@ -74,8 +74,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2)) if (!proto_to_pubkey(o1->commit_key, &pubkey2))
errx(1, "Invalid o1 commit pubkey"); errx(1, "Invalid o1 commit pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->commit_key, &pubkey2)) if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey"); errx(1, "Invalid o2 commit pubkey");

3
test-cli/update-channel-signature.c

@ -77,8 +77,7 @@ int main(int argc, char *argv[])
/* Get pubkeys */ /* Get pubkeys */
if (!proto_to_pubkey(o1->commit_key, &pubkey2)) if (!proto_to_pubkey(o1->commit_key, &pubkey2))
errx(1, "Invalid o1 commit pubkey"); errx(1, "Invalid o1 commit pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) if (!pubkey_eq(&pubkey1, &pubkey2))
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey"); errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->commit_key, &pubkey2)) if (!proto_to_pubkey(o2->commit_key, &pubkey2))
errx(1, "Invalid o2 commit pubkey"); errx(1, "Invalid o2 commit pubkey");

Loading…
Cancel
Save