bitcoin: signature fixes.

The libsecp change broke signature checking.  Disable it for now,
with a big FIXME.  The next version should have a method for S value
checking, and also compact serialization.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2015-10-12 10:45:02 +10:30
parent 0b50a7c9eb
commit 32fe988fe8
3 changed files with 62 additions and 58 deletions

View File

@ -89,12 +89,12 @@ bool sign_hash(const tal_t *ctx, const struct privkey *privkey,
#ifdef USE_SCHNORR
ok = secp256k1_schnorr_sign(secpctx,
(unsigned char *)s,
s->schnorr,
h->sha.u.u8,
privkey->secret, NULL, NULL);
#else
ok = secp256k1_ecdsa_sign(secpctx,
(secp256k1_ecdsa_signature *)s,
&s->sig,
h->sha.u.u8,
privkey->secret, NULL, NULL);
#endif
@ -158,11 +158,11 @@ static bool check_signed_hash(const struct sha256_double *hash,
return false;
#ifdef USE_SCHNORR
ret = secp256k1_schnorr_verify(secpctx, (unsigned char *)signature,
ret = secp256k1_schnorr_verify(secpctx, signature->schnorr,
hash->sha.u.u8, &key->pubkey);
#else
ret = secp256k1_ecdsa_verify(secpctx,
(secp256k1_ecdsa_signature *)signature,
&signature->sig,
hash->sha.u.u8, &key->pubkey);
#endif
@ -214,6 +214,7 @@ bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
&& check_signed_hash(&hash, &sig2->sig, key2);
}
#ifndef USE_SCHNORR
/* Stolen direct from bitcoin/src/script/sign.cpp:
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
@ -286,55 +287,26 @@ static bool IsValidSignatureEncoding(const unsigned char sig[], size_t len)
return true;
}
/* DER encode a value, return length used. */
static size_t der_encode_val(const u8 *val, u8 *der)
{
size_t len = 0, val_len = 32;
der[len++] = 0x2; /* value type. */
/* Strip leading zeroes. */
while (val_len && val[0] == 0) {
val++;
val_len--;
}
/* Add zero byte if it would otherwise be signed. */
if (val[0] & 0x80) {
der[len++] = 1 + val_len; /* value length */
der[len++] = 0;
} else
der[len++] = val_len; /* value length */
memcpy(der + len, val, val_len);
return len + val_len;
}
size_t signature_to_der(u8 der[72], const struct signature *sig)
{
size_t len = 0;
size_t len = 72;
secp256k1_context *ctx = secp256k1_context_create(0);
der[len++] = 0x30; /* Type */
der[len++] = 0; /* Total length after this: fill it at end. */
len += der_encode_val(sig->r, der + len);
len += der_encode_val(sig->s, der + len);
/* Fix up total length */
der[1] = len - 2;
secp256k1_ecdsa_signature_serialize_der(ctx, der, &len, &sig->sig);
/* IsValidSignatureEncoding() expect extra byte for sighash */
assert(IsValidSignatureEncoding(der, len + 1));
return len;
}
#endif /* USE_SCHNORR */
/* Signature must have low S value. */
bool sig_valid(const struct signature *sig)
{
#ifdef USE_SCHNORR
/* FIXME: Is there some sanity check we can do here? */
return true;
#else
return (sig->s[0] & 0x80) == 0;
/* FIXME! Need libsecp support. */
return true;
#endif
}

View File

@ -2,6 +2,7 @@
#define LIGHTNING_BITCOIN_SIGNATURE_H
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include "secp256k1.h"
enum sighash_type {
SIGHASH_ALL = 1,
@ -12,8 +13,11 @@ enum sighash_type {
/* ECDSA of double SHA256. */
struct signature {
u8 r[32];
u8 s[32];
#ifdef USE_SCHNORR
u8 schnorr[64];
#else
secp256k1_ecdsa_signature sig;
#endif
};
struct sha256_double;
@ -49,7 +53,9 @@ bool check_2of2_sig(struct bitcoin_tx *tx, size_t input_num,
/* Signature must have low S value. */
bool sig_valid(const struct signature *s);
#ifndef USE_SCHNORR
/* Give DER encoding of signature: returns length used (<= 72). */
size_t signature_to_der(u8 der[72], const struct signature *s);
#endif
#endif /* LIGHTNING_BITCOIN_SIGNATURE_H */

View File

@ -10,30 +10,56 @@ Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig)
assert(sig_valid(sig));
#ifdef USE_SCHNORR
memcpy(&pb->r1, sig->schnorr, 8);
memcpy(&pb->r2, sig->schnorr + 8, 8);
memcpy(&pb->r3, sig->schnorr + 16, 8);
memcpy(&pb->r4, sig->schnorr + 24, 8);
memcpy(&pb->s1, sig->schnorr + 32, 8);
memcpy(&pb->s2, sig->schnorr + 40, 8);
memcpy(&pb->s3, sig->schnorr + 48, 8);
memcpy(&pb->s4, sig->schnorr + 56, 8);
#else
/* FIXME: Need a portable way to encode signatures in libsecp! */
/* Kill me now... */
memcpy(&pb->r1, sig->r, 8);
memcpy(&pb->r2, sig->r + 8, 8);
memcpy(&pb->r3, sig->r + 16, 8);
memcpy(&pb->r4, sig->r + 24, 8);
memcpy(&pb->s1, sig->s, 8);
memcpy(&pb->s2, sig->s + 8, 8);
memcpy(&pb->s3, sig->s + 16, 8);
memcpy(&pb->s4, sig->s + 24, 8);
memcpy(&pb->r1, sig->sig.data, 8);
memcpy(&pb->r2, sig->sig.data + 8, 8);
memcpy(&pb->r3, sig->sig.data + 16, 8);
memcpy(&pb->r4, sig->sig.data + 24, 8);
memcpy(&pb->s1, sig->sig.data + 32, 8);
memcpy(&pb->s2, sig->sig.data + 40, 8);
memcpy(&pb->s3, sig->sig.data + 48, 8);
memcpy(&pb->s4, sig->sig.data + 56, 8);
#endif
return pb;
}
bool proto_to_signature(const Signature *pb, struct signature *sig)
{
/* Kill me again. */
memcpy(sig->r, &pb->r1, 8);
memcpy(sig->r + 8, &pb->r2, 8);
memcpy(sig->r + 16, &pb->r3, 8);
memcpy(sig->r + 24, &pb->r4, 8);
memcpy(sig->s, &pb->s1, 8);
memcpy(sig->s + 8, &pb->s2, 8);
memcpy(sig->s + 16, &pb->s3, 8);
memcpy(sig->s + 24, &pb->s4, 8);
#ifdef USE_SCHNORR
memcpy(sig->schnorr, &pb->r1, 8);
memcpy(sig->schnorr + 8, &pb->r2, 8);
memcpy(sig->schnorr + 16, &pb->r3, 8);
memcpy(sig->schnorr + 24, &pb->r4, 8);
memcpy(sig->schnorr + 32, &pb->s1, 8);
memcpy(sig->schnorr + 40, &pb->s2, 8);
memcpy(sig->schnorr + 48, &pb->s3, 8);
memcpy(sig->schnorr + 56, &pb->s4, 8);
#else
/* FIXME: Need a portable way to encode signatures in libsecp! */
memcpy(sig->sig.data, &pb->r1, 8);
memcpy(sig->sig.data + 8, &pb->r2, 8);
memcpy(sig->sig.data + 16, &pb->r3, 8);
memcpy(sig->sig.data + 24, &pb->r4, 8);
memcpy(sig->sig.data + 32, &pb->s1, 8);
memcpy(sig->sig.data + 40, &pb->s2, 8);
memcpy(sig->sig.data + 48, &pb->s3, 8);
memcpy(sig->sig.data + 56, &pb->s4, 8);
#endif
return sig_valid(sig);
}