Browse Source

pubkey: pubkey_eq helper.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 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;
sha256(&h, key->key, pubkey_len(key));
sha256(&h, key->der, pubkey_derlen(key));
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;
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;

76
bitcoin/pubkey.c

@ -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 len = GetLen(key->der[0]);
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);
return len;
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;
}
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;
dlen = hex_data_size(slen);
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 (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;
if (!hex_decode(str, slen, key->key, dlen))
if (!hex_decode(derstr, slen, der, dlen))
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
#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);
/* 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) */
bool pubkey_from_hexstr(const char *str, struct pubkey *key);
/* Pubkey from DER encoding. */
bool pubkey_from_der(const u8 *der, size_t len, struct pubkey *key);
/* For conversion routines in protobuf_convert.c */
bool pubkey_valid(const u8 *first_char, size_t len);
/* 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 */

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)
{
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. */

12
bitcoin/signature.c

@ -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);

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 *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)

3
test-cli/close-channel.c

@ -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");

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

@ -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");

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

@ -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");

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))
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");

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

@ -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");

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

@ -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");

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

@ -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…
Cancel
Save