mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-26 20:30:59 +01:00
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>
This commit is contained in:
parent
7c977a7633
commit
07c7214edb
12 changed files with 105 additions and 43 deletions
2
Makefile
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
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
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
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
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
Normal file
54
pubkey.c
Normal file
|
@ -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
Normal file
18
pubkey.h
Normal file
|
@ -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…
Add table
Reference in a new issue