Browse Source

Explicit pubkey structure.

This checks that the protobuf is the right form, also handles uncompressed
keys (though you shouldn't be using those any more, should you?)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 10 years ago
parent
commit
07c7214edb
  1. 2
      Makefile
  2. 25
      base58.c
  3. 6
      base58.h
  4. 6
      bitcoin_address.c
  5. 9
      bitcoin_address.h
  6. 6
      open-anchor-sig.c
  7. 4
      open-channel.c
  8. 3
      open-commit-sig.c
  9. 11
      pkt.c
  10. 4
      pkt.h
  11. 54
      pubkey.c
  12. 18
      pubkey.h

2
Makefile

@ -5,7 +5,7 @@ PROTOCC:=protoc-c
PROGRAMS := open-channel open-anchor-sig leak-anchor-sigs open-commit-sig
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o commit_tx.o
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o commit_tx.o pubkey.o
CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-read_write_all.o ccan-str-hex.o ccan-tal-grab_file.o ccan-noerr.o

25
base58.c

@ -5,6 +5,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "shadouble.h"
#include "bitcoin_address.h"
#include "pubkey.h"
#include <assert.h>
#include <ccan/build_assert/build_assert.h>
#include <ccan/tal/str/str.h>
@ -299,23 +301,25 @@ static bool EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
}
EC_KEY *key_from_base58(const char *base58, size_t base58_len,
bool *test_net, struct bitcoin_compressed_pubkey *key)
bool *test_net, struct pubkey *key)
{
size_t keylen;
u8 keybuf[1 + 32 + 1 + 4], *pubkey;
u8 keybuf[1 + 32 + 1 + 4], *kptr;
u8 csum[4];
EC_KEY *priv;
BIGNUM bn;
point_conversion_form_t cform;
BN_init(&bn);
if (!raw_decode_base58(&bn, base58, base58_len))
return NULL;
keylen = BN_num_bytes(&bn);
/* FIXME: Handle non-compressed keys! */
if (keylen == 1 + 32 + 4)
goto fail_free_bn;
if (keylen != 1 + 32 + 1 + 4)
cform = POINT_CONVERSION_UNCOMPRESSED;
else if (keylen == 1 + 32 + 1 + 4)
cform = POINT_CONVERSION_COMPRESSED;
else
goto fail_free_bn;
BN_bn2bin(&bn, keybuf);
@ -324,7 +328,7 @@ EC_KEY *key_from_base58(const char *base58, size_t base58_len,
goto fail_free_bn;
/* Byte after key should be 1 to represent a compressed key. */
if (keybuf[1 + 32] != 1)
if (cform == POINT_CONVERSION_COMPRESSED && keybuf[1 + 32] != 1)
goto fail_free_bn;
if (keybuf[0] == 128)
@ -335,8 +339,7 @@ EC_KEY *key_from_base58(const char *base58, size_t base58_len,
goto fail_free_bn;
priv = EC_KEY_new_by_curve_name(NID_secp256k1);
/* We *always* used compressed form keys. */
EC_KEY_set_conv_form(priv, POINT_CONVERSION_COMPRESSED);
EC_KEY_set_conv_form(priv, cform);
BN_free(&bn);
BN_init(&bn);
@ -346,9 +349,9 @@ EC_KEY *key_from_base58(const char *base58, size_t base58_len,
goto fail_free_priv;
/* Save public key */
pubkey = key->key;
keylen = i2o_ECPublicKey(priv, &pubkey);
assert(keylen == sizeof(key->key));
kptr = key->key;
keylen = i2o_ECPublicKey(priv, &kptr);
assert(keylen == pubkey_len(key));
BN_free(&bn);
return priv;

6
base58.h

@ -8,7 +8,9 @@
#include <openssl/ripemd.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bitcoin_address.h"
struct pubkey;
struct bitcoin_address;
/* Encoding is version byte + ripemd160 + 4-byte checksum == 200 bits => 2^200.
*
@ -36,7 +38,7 @@ char *base58_with_check(char dest[BASE58_ADDR_MAX_LEN],
char *key_to_base58(const tal_t *ctx, bool test_net, EC_KEY *key);
EC_KEY *key_from_base58(const char *base58, size_t base58_len,
bool *test_net, struct bitcoin_compressed_pubkey *key);
bool *test_net, struct pubkey *key);
bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base);
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len);

6
bitcoin_address.c

@ -1,11 +1,11 @@
#include "bitcoin_address.h"
#include "pubkey.h"
#include <ccan/crypto/sha256/sha256.h>
void bitcoin_address(const struct bitcoin_compressed_pubkey *key,
struct bitcoin_address *addr)
void bitcoin_address(const struct pubkey *key, struct bitcoin_address *addr)
{
struct sha256 h;
sha256(&h, key, sizeof(*key));
sha256(&h, key->key, pubkey_len(key));
RIPEMD160(h.u.u8, sizeof(h), addr->addr);
}

9
bitcoin_address.h

@ -3,16 +3,13 @@
#include <openssl/ripemd.h>
#include <ccan/short_types/short_types.h>
struct pubkey;
/* An address is the RIPEMD160 of the SHA of the public key. */
struct bitcoin_address {
u8 addr[RIPEMD160_DIGEST_LENGTH]; /* 20 */
};
/* An ECDSA compressed public key. 33 chars long, even on ARM. */
struct bitcoin_compressed_pubkey {
u8 key[33];
} __attribute__((aligned(1)));
void bitcoin_address(const struct bitcoin_compressed_pubkey *key,
void bitcoin_address(const struct pubkey *key,
struct bitcoin_address *addr);
#endif /* LIGHTNING_BITCOIN_ADDRESS_H */

6
open-anchor-sig.c

@ -13,6 +13,7 @@
#include "bitcoin_address.h"
#include "base58.h"
#include "anchor.h"
#include "pubkey.h"
#include <openssl/ec.h>
#include <unistd.h>
@ -23,7 +24,7 @@ static u8 *tx_scriptsig(const tal_t *ctx,
unsigned int i,
const BitcoinInput *input,
EC_KEY *privkey,
const struct bitcoin_compressed_pubkey *pubkey)
const struct pubkey *pubkey)
{
struct signature *sig;
struct bitcoin_address addr;
@ -76,8 +77,7 @@ int main(int argc, char *argv[])
sigs = tal_arr(ctx, u8 *, o1->anchor->n_inputs);
for (i = 0; i < o1->anchor->n_inputs; i++) {
/* FIXME: Support non-compressed keys? */
struct bitcoin_compressed_pubkey pubkey;
struct pubkey pubkey;
EC_KEY *privkey;
bool testnet;

4
open-channel.c

@ -13,6 +13,8 @@
#include "base58.h"
#include "pkt.h"
#include "bitcoin_script.h"
#include "bitcoin_address.h"
#include "pubkey.h"
#include <openssl/ec.h>
#include <unistd.h>
@ -93,7 +95,7 @@ int main(int argc, char *argv[])
bool testnet;
u8 *script_to_me;
size_t i;
struct bitcoin_compressed_pubkey commitkey;
struct pubkey commitkey;
EC_KEY *commitprivkey;
err_set_progname(argv[0]);

3
open-commit-sig.c

@ -17,6 +17,7 @@
#include "permute_tx.h"
#include "signature.h"
#include "commit_tx.h"
#include "pubkey.h"
#include <openssl/ec.h>
#include <unistd.h>
@ -31,7 +32,7 @@ int main(int argc, char *argv[])
size_t *inmap, *outmap;
EC_KEY *privkey;
bool testnet;
struct bitcoin_compressed_pubkey pubkey;
struct pubkey pubkey;
err_set_progname(argv[0]);

11
pkt.c

@ -47,17 +47,6 @@ void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash)
memcpy(hash->u.u8 + 24, &pb->d, 8);
}
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key)
{
BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
bitcoin_pubkey__init(p);
p->key.data = tal_dup_arr(ctx, u8, key->key, sizeof(key->key), 0);
p->key.len = sizeof(key->key);
return p;
}
struct pkt *openchannel_pkt(const tal_t *ctx,
u64 seed,
const struct sha256 *revocation_hash,

4
pkt.h

@ -69,8 +69,4 @@ struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig);
/* Useful helper for allocating & populating a protobuf Sha256Hash */
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash);
void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash);
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key);
#endif /* LIGHTNING_PKT_H */

54
pubkey.c

@ -0,0 +1,54 @@
#include "pubkey.h"
#include <openssl/ecdsa.h>
/* Must agree on key validity with bitcoin! Stolen from bitcoin/src/pubkey.h's
* GetLen:
* // Copyright (c) 2009-2010 Satoshi Nakamoto
* // Copyright (c) 2009-2014 The Bitcoin Core developers
* // Distributed under the MIT software license, see the accompanying
* // file COPYING or http://www.opensource.org/licenses/mit-license.php.
*/
static unsigned int GetLen(unsigned char chHeader)
{
if (chHeader == 2 || chHeader == 3)
return 33;
if (chHeader == 4 || chHeader == 6 || chHeader == 7)
return 65;
return 0;
}
static bool valid_pubkey(const BitcoinPubkey *key)
{
if (key->key.len < 1)
return false;
return (key->key.len == GetLen(key->key.data[0]));
}
size_t pubkey_len(const struct pubkey *key)
{
size_t len = GetLen(key->key[0]);
assert(len);
return len;
}
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, const struct pubkey *key)
{
BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
bitcoin_pubkey__init(p);
p->key.len = pubkey_len(key);
p->key.data = tal_dup_arr(p, u8, key->key, p->key.len, 0);
assert(valid_pubkey(p));
return p;
}
bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key)
{
if (!valid_pubkey(pb))
return false;
memcpy(key->key, pb->key.data, pb->key.len);
return true;
}

18
pubkey.h

@ -0,0 +1,18 @@
#ifndef LIGHTNING_PUBKEY_H
#define LIGHTNING_PUBKEY_H
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include "lightning.pb-c.h"
struct pubkey {
u8 key[65];
};
/* Convert to-from protobuf to internal representation. */
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, const struct pubkey *key);
bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key);
/* 33 or 65 bytes? */
size_t pubkey_len(const struct pubkey *key);
#endif /* LIGHTNING_PUBKEY_H */
Loading…
Cancel
Save