Introduce secp256k1_scalar_t for future constant-time mod order operations

This commit is contained in:
Pieter Wuille 2014-10-28 04:08:15 -07:00
parent b2bfdabdeb
commit a9f5c8b875
14 changed files with 319 additions and 149 deletions

View File

@ -4,6 +4,8 @@ lib_LTLIBRARIES = libsecp256k1.la
noinst_LTLIBRARIES = libsecp256k1_common.la noinst_LTLIBRARIES = libsecp256k1_common.la
include_HEADERS = include/secp256k1.h include_HEADERS = include/secp256k1.h
noinst_HEADERS = noinst_HEADERS =
noinst_HEADERS += src/scalar.h
noinst_HEADERS += src/scalar_impl.h
noinst_HEADERS += src/group.h noinst_HEADERS += src/group.h
noinst_HEADERS += src/group_impl.h noinst_HEADERS += src/group_impl.h
noinst_HEADERS += src/num_openssl.h noinst_HEADERS += src/num_openssl.h

View File

@ -17,7 +17,7 @@ void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r);
int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size); int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a); int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message); int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message);
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid); int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid); int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s); void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);

View File

@ -147,9 +147,7 @@ int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const se
return ret; return ret;
} }
int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid) { int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
secp256k1_gej_t rp; secp256k1_gej_t rp;
secp256k1_ecmult_gen(&rp, nonce); secp256k1_ecmult_gen(&rp, nonce);
secp256k1_ge_t r; secp256k1_ge_t r;
@ -158,28 +156,35 @@ int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_
secp256k1_fe_normalize(&r.x); secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y); secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x); secp256k1_fe_get_b32(b, &r.x);
secp256k1_num_set_bin(&sig->r, b, 32); int overflow = 0;
secp256k1_scalar_t sigr;
secp256k1_scalar_init(&sigr);
secp256k1_scalar_set_bin(&sigr, b, 32, &overflow);
if (recid) if (recid)
*recid = (secp256k1_num_cmp(&sig->r, &c->order) >= 0 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_num_mod(&sig->r, &c->order); secp256k1_scalar_t n;
secp256k1_num_t n; secp256k1_scalar_init(&n);
secp256k1_num_init(&n); secp256k1_scalar_mul(&n, &sigr, seckey);
secp256k1_num_mod_mul(&n, &sig->r, seckey, &c->order); secp256k1_scalar_add(&n, &n, message);
secp256k1_num_add(&n, &n, message); secp256k1_scalar_t sigs;
secp256k1_num_mod(&n, &c->order); secp256k1_scalar_init(&sigs);
secp256k1_num_mod_inverse(&sig->s, nonce, &c->order); secp256k1_scalar_inverse(&sigs, nonce);
secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order); secp256k1_scalar_mul(&sigs, &sigs, &n);
secp256k1_num_clear(&n); secp256k1_scalar_clear(&n);
secp256k1_num_free(&n); secp256k1_scalar_free(&n);
secp256k1_gej_clear(&rp); secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r); secp256k1_ge_clear(&r);
if (secp256k1_num_is_zero(&sig->s)) if (secp256k1_scalar_is_zero(&sigs))
return 0; return 0;
if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) { if (secp256k1_scalar_is_high(&sigs)) {
secp256k1_num_sub(&sig->s, &c->order, &sig->s); secp256k1_scalar_negate(&sigs, &sigs);
if (recid) if (recid)
*recid ^= 1; *recid ^= 1;
} }
secp256k1_scalar_get_num(&sig->s, &sigs);
secp256k1_scalar_get_num(&sig->r, &sigr);
secp256k1_scalar_free(&sigs);
secp256k1_scalar_free(&sigr);
return 1; return 1;
} }

View File

@ -6,17 +6,18 @@
#define _SECP256K1_ECKEY_ #define _SECP256K1_ECKEY_
#include "group.h" #include "group.h"
#include "scalar.h"
#include "num.h" #include "num.h"
int static secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size); int static secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed); void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen); int static secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen);
int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed); int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);
int static secp256k1_eckey_privkey_tweak_add(secp256k1_num_t *key, const secp256k1_num_t *tweak); int static secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
int static secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak); int static secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
int static secp256k1_eckey_privkey_tweak_mul(secp256k1_num_t *key, const secp256k1_num_t *tweak); int static secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
int static secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak); int static secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
#endif #endif

View File

@ -44,7 +44,7 @@ void static secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char
} }
} }
int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen) { int static secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen) {
const unsigned char *end = privkey + privkeylen; const unsigned char *end = privkey + privkeylen;
// sequence header // sequence header
if (end < privkey+1 || *privkey != 0x30) if (end < privkey+1 || *privkey != 0x30)
@ -72,11 +72,12 @@ int static secp256k1_eckey_privkey_parse(secp256k1_num_t *key, const unsigned ch
// sequence element 1: octet string, up to 32 bytes // sequence element 1: octet string, up to 32 bytes
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1])
return 0; return 0;
secp256k1_num_set_bin(key, privkey+2, privkey[1]); int overflow = 0;
return 1; secp256k1_scalar_set_bin(key, privkey+2, privkey[1], &overflow);
return !overflow;
} }
int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed) { int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) {
secp256k1_gej_t rp; secp256k1_gej_t rp;
secp256k1_ecmult_gen(&rp, key); secp256k1_ecmult_gen(&rp, key);
secp256k1_ge_t r; secp256k1_ge_t r;
@ -98,7 +99,7 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke
}; };
unsigned char *ptr = privkey; unsigned char *ptr = privkey;
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_num_get_bin(ptr, 32, key); ptr += 32; secp256k1_scalar_get_bin(ptr, 32, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
int pubkeylen = 0; int pubkeylen = 0;
secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen; secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1); ptr += pubkeylen;
@ -122,7 +123,7 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke
}; };
unsigned char *ptr = privkey; unsigned char *ptr = privkey;
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_num_get_bin(ptr, 32, key); ptr += 32; secp256k1_scalar_get_bin(ptr, 32, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
int pubkeylen = 0; int pubkeylen = 0;
secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen; secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen;
@ -131,12 +132,9 @@ int static secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privke
return 1; return 1;
} }
int static secp256k1_eckey_privkey_tweak_add(secp256k1_num_t *key, const secp256k1_num_t *tweak) { int static secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) {
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0) secp256k1_scalar_add(key, key, tweak);
return 0; if (secp256k1_scalar_is_zero(key))
secp256k1_num_add(key, key, tweak);
secp256k1_num_mod(key, &secp256k1_ge_consts->order);
if (secp256k1_num_is_zero(key))
return 0; return 0;
return 1; return 1;
} }
@ -159,13 +157,11 @@ int static secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1
return 1; return 1;
} }
int static secp256k1_eckey_privkey_tweak_mul(secp256k1_num_t *key, const secp256k1_num_t *tweak) { int static secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) {
if (secp256k1_num_is_zero(tweak)) if (secp256k1_scalar_is_zero(tweak))
return 0;
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
return 0; return 0;
secp256k1_num_mod_mul(key, key, tweak, &secp256k1_ge_consts->order); secp256k1_scalar_mul(key, key, tweak);
return 1; return 1;
} }

View File

@ -5,13 +5,13 @@
#ifndef _SECP256K1_ECMULT_GEN_ #ifndef _SECP256K1_ECMULT_GEN_
#define _SECP256K1_ECMULT_GEN_ #define _SECP256K1_ECMULT_GEN_
#include "num.h" #include "scalar.h"
#include "group.h" #include "group.h"
static void secp256k1_ecmult_gen_start(void); static void secp256k1_ecmult_gen_start(void);
static void secp256k1_ecmult_gen_stop(void); static void secp256k1_ecmult_gen_stop(void);
/** Multiply with the generator: R = a*G */ /** Multiply with the generator: R = a*G */
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a); static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *a);
#endif #endif

View File

@ -6,7 +6,7 @@
#define _SECP256K1_ECMULT_GEN_IMPL_H_ #define _SECP256K1_ECMULT_GEN_IMPL_H_
#include <assert.h> #include <assert.h>
#include "num.h" #include "scalar.h"
#include "group.h" #include "group.h"
#include "ecmult_gen.h" #include "ecmult_gen.h"
@ -100,24 +100,19 @@ static void secp256k1_ecmult_gen_stop(void) {
free(c); free(c);
} }
void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *gn) {
secp256k1_num_t n;
secp256k1_num_init(&n);
secp256k1_num_copy(&n, gn);
const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts; const secp256k1_ecmult_gen_consts_t *c = secp256k1_ecmult_gen_consts;
secp256k1_gej_set_infinity(r); secp256k1_gej_set_infinity(r);
secp256k1_ge_t add; secp256k1_ge_t add;
int bits; int bits;
for (int j=0; j<64; j++) { for (int j=0; j<64; j++) {
bits = secp256k1_num_shift(&n, 4); bits = secp256k1_scalar_get_bits(gn, j * 4, 4);
for (int k=0; k<sizeof(secp256k1_ge_t); k++) for (int k=0; k<sizeof(secp256k1_ge_t); k++)
((unsigned char*)(&add))[k] = c->prec[j][k][bits]; ((unsigned char*)(&add))[k] = c->prec[j][k][bits];
secp256k1_gej_add_ge(r, r, &add); secp256k1_gej_add_ge(r, r, &add);
} }
bits = 0; bits = 0;
secp256k1_ge_clear(&add); secp256k1_ge_clear(&add);
secp256k1_num_clear(&n);
secp256k1_num_free(&n);
} }
#endif #endif

View File

@ -100,4 +100,7 @@ void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const
/** Change a number's sign. */ /** Change a number's sign. */
void static secp256k1_num_negate(secp256k1_num_t *r); void static secp256k1_num_negate(secp256k1_num_t *r);
/** Get a bunch of bits from a number. */
int static secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count);
#endif #endif

View File

@ -362,4 +362,12 @@ void static secp256k1_num_negate(secp256k1_num_t *r) {
r->neg ^= 1; r->neg ^= 1;
} }
int static secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) {
int ret = 0;
for (int i = 0; i < count; i++) {
ret |= ((a->data[(offset + i) / GMP_NUMB_BITS] >> ((offset + i) % GMP_NUMB_BITS)) & 1) << i;
}
return ret;
}
#endif #endif

View File

@ -252,4 +252,12 @@ void static secp256k1_num_negate(secp256k1_num_t *r) {
BN_set_negative(&r->bn, !BN_is_negative(&r->bn)); BN_set_negative(&r->bn, !BN_is_negative(&r->bn));
} }
int static secp256k1_num_get_bits(const secp256k1_num_t *a, int offset, int count) {
int ret = 0;
for (int i = 0; i < count; i++) {
ret |= BN_is_bit_set(&a->bn, offset + i) << i;
}
return ret;
}
#endif #endif

54
src/scalar.h Normal file
View File

@ -0,0 +1,54 @@
// Copyright (c) 2014 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef _SECP256K1_SCALAR_
#define _SECP256K1_SCALAR_
#include "num.h"
/** A scalar modulo the group order of the secp256k1 curve. */
typedef struct {
secp256k1_num_t n;
} secp256k1_scalar_t;
/** Initialize a scalar. */
void static secp256k1_scalar_init(secp256k1_scalar_t *r);
/** Clear a scalar to prevent the leak of sensitive data. */
void static secp256k1_scalar_clear(secp256k1_scalar_t *r);
/** Free a scalar. */
void static secp256k1_scalar_free(secp256k1_scalar_t *r);
/** Access bits from a scalar. */
int static secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count);
/** Set a scalar from a big endian byte array. */
void static secp256k1_scalar_set_bin(secp256k1_scalar_t *r, const unsigned char *bin, int len, int *overflow);
/** Convert a scalar to a byte array. */
void static secp256k1_scalar_get_bin(unsigned char *bin, int len, const secp256k1_scalar_t* a);
/** Add two scalars together (modulo the group order). */
void static secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
/** Multiply two scalars (modulo the group order). */
void static secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b);
/** Compute the inverse of a scalar (modulo the group order). */
void static secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
/** Compute the complement of a scalar (modulo the group order). */
void static secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a);
/** Check whether a scalar equals zero. */
int static secp256k1_scalar_is_zero(const secp256k1_scalar_t *a);
/** Check whether a scalar is higher than the group order divided by 2. */
int static secp256k1_scalar_is_high(const secp256k1_scalar_t *a);
/** Convert a scalar to a number. */
void static secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a);
#endif

73
src/scalar_impl.h Normal file
View File

@ -0,0 +1,73 @@
// Copyright (c) 2014 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef _SECP256K1_SCALAR_IMPL_H_
#define _SECP256K1_SCALAR_IMPL_H_
#include <string.h>
#include "scalar.h"
#include "group.h"
void static secp256k1_scalar_init(secp256k1_scalar_t *r) {
secp256k1_num_init(&r->n);
}
void static secp256k1_scalar_clear(secp256k1_scalar_t *r) {
secp256k1_num_clear(&r->n);
}
void static secp256k1_scalar_free(secp256k1_scalar_t *r) {
secp256k1_num_free(&r->n);
}
int static secp256k1_scalar_get_bits(const secp256k1_scalar_t *a, int offset, int count) {
return secp256k1_num_get_bits(&a->n, offset, count);
}
void static secp256k1_scalar_set_bin(secp256k1_scalar_t *r, const unsigned char *bin, int len, int *overflow) {
secp256k1_num_set_bin(&r->n, bin, len);
if (overflow) {
*overflow = secp256k1_num_cmp(&r->n, &secp256k1_ge_consts->order) >= 0;
}
secp256k1_num_mod(&r->n, &secp256k1_ge_consts->order);
}
void static secp256k1_scalar_get_bin(unsigned char *bin, int len, const secp256k1_scalar_t* a) {
secp256k1_num_get_bin(bin, len, &a->n);
}
void static secp256k1_scalar_add(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
secp256k1_num_add(&r->n, &a->n, &b->n);
secp256k1_num_mod(&r->n, &secp256k1_ge_consts->order);
}
void static secp256k1_scalar_mul(secp256k1_scalar_t *r, const secp256k1_scalar_t *a, const secp256k1_scalar_t *b) {
secp256k1_num_mod_mul(&r->n, &a->n, &b->n, &secp256k1_ge_consts->order);
}
void static secp256k1_scalar_inverse(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
secp256k1_num_mod_inverse(&r->n, &a->n, &secp256k1_ge_consts->order);
}
void static secp256k1_scalar_negate(secp256k1_scalar_t *r, const secp256k1_scalar_t *a) {
secp256k1_num_sub(&r->n, &secp256k1_ge_consts->order, &a->n);
}
int static secp256k1_scalar_is_zero(const secp256k1_scalar_t *a) {
return secp256k1_num_is_zero(&a->n);
}
int static secp256k1_scalar_is_high(const secp256k1_scalar_t *a) {
return secp256k1_num_cmp(&a->n, &secp256k1_ge_consts->half_order) > 0;
}
void static secp256k1_scalar_get_num(secp256k1_num_t *r, const secp256k1_scalar_t *a) {
unsigned char c[32];
secp256k1_num_get_bin(c, 32, &a->n);
secp256k1_num_set_bin(r, c, 32);
}
#endif

View File

@ -8,6 +8,7 @@
#include "util.h" #include "util.h"
#include "num_impl.h" #include "num_impl.h"
#include "field_impl.h" #include "field_impl.h"
#include "scalar_impl.h"
#include "group_impl.h" #include "group_impl.h"
#include "ecmult_impl.h" #include "ecmult_impl.h"
#include "ecmult_gen_impl.h" #include "ecmult_gen_impl.h"
@ -75,15 +76,15 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(nonce != NULL); DEBUG_CHECK(nonce != NULL);
secp256k1_num_t sec, non, msg; secp256k1_scalar_t sec, non, msg;
secp256k1_num_init(&sec); secp256k1_scalar_init(&sec);
secp256k1_num_init(&non); secp256k1_scalar_init(&non);
secp256k1_num_init(&msg); secp256k1_scalar_init(&msg);
secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_scalar_set_bin(&sec, seckey, 32, NULL);
secp256k1_num_set_bin(&non, nonce, 32); int overflow = 0;
secp256k1_num_set_bin(&msg, message, messagelen); secp256k1_scalar_set_bin(&non, nonce, 32, &overflow);
int ret = !secp256k1_num_is_zero(&non) && secp256k1_scalar_set_bin(&msg, message, messagelen, NULL);
(secp256k1_num_cmp(&non, &secp256k1_ge_consts->order) < 0); int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
secp256k1_ecdsa_sig_init(&sig); secp256k1_ecdsa_sig_init(&sig);
if (ret) { if (ret) {
@ -93,12 +94,12 @@ int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned
secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
} }
secp256k1_ecdsa_sig_free(&sig); secp256k1_ecdsa_sig_free(&sig);
secp256k1_num_clear(&msg); secp256k1_scalar_clear(&msg);
secp256k1_num_clear(&non); secp256k1_scalar_clear(&non);
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_free(&msg); secp256k1_scalar_free(&msg);
secp256k1_num_free(&non); secp256k1_scalar_free(&non);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
return ret; return ret;
} }
@ -110,15 +111,15 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(nonce != NULL); DEBUG_CHECK(nonce != NULL);
secp256k1_num_t sec, non, msg; secp256k1_scalar_t sec, non, msg;
secp256k1_num_init(&sec); secp256k1_scalar_init(&sec);
secp256k1_num_init(&non); secp256k1_scalar_init(&non);
secp256k1_num_init(&msg); secp256k1_scalar_init(&msg);
secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_scalar_set_bin(&sec, seckey, 32, NULL);
secp256k1_num_set_bin(&non, nonce, 32); int overflow = 0;
secp256k1_num_set_bin(&msg, message, messagelen); secp256k1_scalar_set_bin(&non, nonce, 32, &overflow);
int ret = !secp256k1_num_is_zero(&non) && secp256k1_scalar_set_bin(&msg, message, messagelen, NULL);
(secp256k1_num_cmp(&non, &secp256k1_ge_consts->order) < 0); int ret = !secp256k1_scalar_is_zero(&non) && !overflow;
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
secp256k1_ecdsa_sig_init(&sig); secp256k1_ecdsa_sig_init(&sig);
if (ret) { if (ret) {
@ -129,12 +130,12 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, u
secp256k1_num_get_bin(sig64 + 32, 32, &sig.s); secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
} }
secp256k1_ecdsa_sig_free(&sig); secp256k1_ecdsa_sig_free(&sig);
secp256k1_num_clear(&msg); secp256k1_scalar_clear(&msg);
secp256k1_num_clear(&non); secp256k1_scalar_clear(&non);
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_free(&msg); secp256k1_scalar_free(&msg);
secp256k1_num_free(&non); secp256k1_scalar_free(&non);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
return ret; return ret;
} }
@ -169,13 +170,13 @@ int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const
int secp256k1_ec_seckey_verify(const unsigned char *seckey) { int secp256k1_ec_seckey_verify(const unsigned char *seckey) {
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
secp256k1_num_t sec; secp256k1_scalar_t sec;
secp256k1_num_init(&sec); secp256k1_scalar_init(&sec);
secp256k1_num_set_bin(&sec, seckey, 32); int overflow;
int ret = !secp256k1_num_is_zero(&sec) && secp256k1_scalar_set_bin(&sec, seckey, 32, &overflow);
(secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0); int ret = !secp256k1_scalar_is_zero(&sec) && !overflow;
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
return ret; return ret;
} }
@ -192,13 +193,13 @@ int secp256k1_ec_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsi
DEBUG_CHECK(pubkeylen != NULL); DEBUG_CHECK(pubkeylen != NULL);
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
secp256k1_num_t sec; secp256k1_scalar_t sec;
secp256k1_num_init(&sec); secp256k1_scalar_init(&sec);
secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_scalar_set_bin(&sec, seckey, 32, NULL);
secp256k1_gej_t pj; secp256k1_gej_t pj;
secp256k1_ecmult_gen(&pj, &sec); secp256k1_ecmult_gen(&pj, &sec);
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
secp256k1_ge_t p; secp256k1_ge_t p;
secp256k1_ge_set_gej(&p, &pj); secp256k1_ge_set_gej(&p, &pj);
secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed); secp256k1_eckey_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
@ -220,22 +221,23 @@ int secp256k1_ec_privkey_tweak_add(unsigned char *seckey, const unsigned char *t
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL); DEBUG_CHECK(tweak != NULL);
secp256k1_num_t term; secp256k1_scalar_t term;
secp256k1_num_init(&term); secp256k1_scalar_init(&term);
secp256k1_num_set_bin(&term, tweak, 32); int overflow = 0;
secp256k1_num_t sec; secp256k1_scalar_set_bin(&term, tweak, 32, &overflow);
secp256k1_num_init(&sec); secp256k1_scalar_t sec;
secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_scalar_init(&sec);
secp256k1_scalar_set_bin(&sec, seckey, 32, NULL);
int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term); int ret = secp256k1_eckey_privkey_tweak_add(&sec, &term) && !overflow;
if (ret) { if (ret) {
secp256k1_num_get_bin(seckey, 32, &sec); secp256k1_scalar_get_bin(seckey, 32, &sec);
} }
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_clear(&term); secp256k1_scalar_clear(&term);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
secp256k1_num_free(&term); secp256k1_scalar_free(&term);
return ret; return ret;
} }
@ -266,21 +268,22 @@ int secp256k1_ec_privkey_tweak_mul(unsigned char *seckey, const unsigned char *t
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(tweak != NULL); DEBUG_CHECK(tweak != NULL);
secp256k1_num_t factor; secp256k1_scalar_t factor;
secp256k1_num_init(&factor); secp256k1_scalar_init(&factor);
secp256k1_num_set_bin(&factor, tweak, 32); int overflow = 0;
secp256k1_num_t sec; secp256k1_scalar_set_bin(&factor, tweak, 32, &overflow);
secp256k1_num_init(&sec); secp256k1_scalar_t sec;
secp256k1_num_set_bin(&sec, seckey, 32); secp256k1_scalar_init(&sec);
int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor); secp256k1_scalar_set_bin(&sec, seckey, 32, NULL);
int ret = secp256k1_eckey_privkey_tweak_mul(&sec, &factor) && !overflow;
if (ret) { if (ret) {
secp256k1_num_get_bin(seckey, 32, &sec); secp256k1_scalar_get_bin(seckey, 32, &sec);
} }
secp256k1_num_clear(&sec); secp256k1_scalar_clear(&sec);
secp256k1_num_clear(&factor); secp256k1_scalar_clear(&factor);
secp256k1_num_free(&sec); secp256k1_scalar_free(&sec);
secp256k1_num_free(&factor); secp256k1_scalar_free(&factor);
return ret; return ret;
} }
@ -312,11 +315,12 @@ int secp256k1_ec_privkey_export(const unsigned char *seckey, unsigned char *priv
DEBUG_CHECK(privkey != NULL); DEBUG_CHECK(privkey != NULL);
DEBUG_CHECK(privkeylen != NULL); DEBUG_CHECK(privkeylen != NULL);
secp256k1_num_t key; secp256k1_scalar_t key;
secp256k1_num_init(&key); secp256k1_scalar_init(&key);
secp256k1_num_set_bin(&key, seckey, 32); secp256k1_scalar_set_bin(&key, seckey, 32, NULL);
int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed); int ret = secp256k1_eckey_privkey_serialize(privkey, privkeylen, &key, compressed);
secp256k1_num_free(&key); secp256k1_scalar_clear(&key);
secp256k1_scalar_free(&key);
return ret; return ret;
} }
@ -324,11 +328,12 @@ int secp256k1_ec_privkey_import(unsigned char *seckey, const unsigned char *priv
DEBUG_CHECK(seckey != NULL); DEBUG_CHECK(seckey != NULL);
DEBUG_CHECK(privkey != NULL); DEBUG_CHECK(privkey != NULL);
secp256k1_num_t key; secp256k1_scalar_t key;
secp256k1_num_init(&key); secp256k1_scalar_init(&key);
int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen); int ret = secp256k1_eckey_privkey_parse(&key, privkey, privkeylen);
if (ret) if (ret)
secp256k1_num_get_bin(seckey, 32, &key); secp256k1_scalar_get_bin(seckey, 32, &key);
secp256k1_num_free(&key); secp256k1_scalar_clear(&key);
secp256k1_scalar_free(&key);
return ret; return ret;
} }

View File

@ -41,6 +41,18 @@ void random_num_order_test(secp256k1_num_t *num) {
} while(1); } while(1);
} }
void random_scalar_order_test(secp256k1_scalar_t *num) {
do {
unsigned char b32[32];
secp256k1_rand256_test(b32);
int overflow = 0;
secp256k1_scalar_set_bin(num, b32, 32, &overflow);
if (overflow || secp256k1_scalar_is_zero(num))
continue;
break;
} while(1);
}
void random_num_order(secp256k1_num_t *num) { void random_num_order(secp256k1_num_t *num) {
do { do {
unsigned char b32[32]; unsigned char b32[32];
@ -507,33 +519,37 @@ void run_wnaf() {
secp256k1_num_free(&n); secp256k1_num_free(&n);
} }
void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *key, const secp256k1_num_t *msg, int *recid) { void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *key, const secp256k1_scalar_t *msg, int *recid) {
secp256k1_num_t nonce; secp256k1_scalar_t nonce;
secp256k1_num_init(&nonce); secp256k1_scalar_init(&nonce);
do { do {
random_num_order_test(&nonce); random_scalar_order_test(&nonce);
} while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid)); } while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid));
secp256k1_num_free(&nonce); secp256k1_scalar_free(&nonce);
} }
void test_ecdsa_sign_verify() { void test_ecdsa_sign_verify() {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
secp256k1_num_t msg, key; secp256k1_scalar_t msg, key;
secp256k1_num_init(&msg); secp256k1_scalar_init(&msg);
random_num_order_test(&msg); random_scalar_order_test(&msg);
secp256k1_num_init(&key); secp256k1_scalar_init(&key);
random_num_order_test(&key); random_scalar_order_test(&key);
secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key); secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key);
secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj); secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
secp256k1_ecdsa_sig_init(&sig); secp256k1_ecdsa_sig_init(&sig);
random_sign(&sig, &key, &msg, NULL); random_sign(&sig, &key, &msg, NULL);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); secp256k1_num_t msg_num;
secp256k1_num_inc(&msg); secp256k1_num_init(&msg_num);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg)); secp256k1_scalar_get_num(&msg_num, &msg);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
secp256k1_num_inc(&msg_num);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg_num));
secp256k1_ecdsa_sig_free(&sig); secp256k1_ecdsa_sig_free(&sig);
secp256k1_num_free(&msg); secp256k1_num_free(&msg_num);
secp256k1_num_free(&key); secp256k1_scalar_free(&msg);
secp256k1_scalar_free(&key);
} }
void run_ecdsa_sign_verify() { void run_ecdsa_sign_verify() {
@ -643,7 +659,7 @@ void run_ecdsa_end_to_end() {
#ifdef ENABLE_OPENSSL_TESTS #ifdef ENABLE_OPENSSL_TESTS
EC_KEY *get_openssl_key(const secp256k1_num_t *key) { EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) {
unsigned char privkey[300]; unsigned char privkey[300];
int privkeylen; int privkeylen;
int compr = secp256k1_rand32() & 1; int compr = secp256k1_rand32() & 1;
@ -657,13 +673,13 @@ EC_KEY *get_openssl_key(const secp256k1_num_t *key) {
void test_ecdsa_openssl() { void test_ecdsa_openssl() {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts; const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
secp256k1_num_t key, msg; secp256k1_scalar_t key, msg;
secp256k1_num_init(&msg); secp256k1_scalar_init(&msg);
unsigned char message[32]; unsigned char message[32];
secp256k1_rand256_test(message); secp256k1_rand256_test(message);
secp256k1_num_set_bin(&msg, message, 32); secp256k1_scalar_set_bin(&msg, message, 32, NULL);
secp256k1_num_init(&key); secp256k1_scalar_init(&key);
random_num_order_test(&key); random_scalar_order_test(&key);
secp256k1_gej_t qj; secp256k1_gej_t qj;
secp256k1_ecmult_gen(&qj, &key); secp256k1_ecmult_gen(&qj, &key);
secp256k1_ge_t q; secp256k1_ge_t q;
@ -676,9 +692,13 @@ void test_ecdsa_openssl() {
secp256k1_ecdsa_sig_t sig; secp256k1_ecdsa_sig_t sig;
secp256k1_ecdsa_sig_init(&sig); secp256k1_ecdsa_sig_init(&sig);
CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize)); CHECK(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); secp256k1_num_t msg_num;
secp256k1_num_init(&msg_num);
secp256k1_scalar_get_num(&msg_num, &msg);
CHECK(secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
secp256k1_num_inc(&sig.r); secp256k1_num_inc(&sig.r);
CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg)); CHECK(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg_num));
secp256k1_num_free(&msg_num);
random_sign(&sig, &key, &msg, NULL); random_sign(&sig, &key, &msg, NULL);
sigsize = 80; sigsize = 80;
@ -687,8 +707,8 @@ void test_ecdsa_openssl() {
secp256k1_ecdsa_sig_free(&sig); secp256k1_ecdsa_sig_free(&sig);
EC_KEY_free(ec_key); EC_KEY_free(ec_key);
secp256k1_num_free(&key); secp256k1_scalar_free(&key);
secp256k1_num_free(&msg); secp256k1_scalar_free(&msg);
} }
void run_ecdsa_openssl() { void run_ecdsa_openssl() {