From bbd5ba7cfa03db851ae1de6d7be0e4c072cb6a54 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 13 Dec 2014 18:06:33 +0100 Subject: [PATCH] Use rfc6979 as default nonce generation function --- Makefile.am | 2 ++ include/secp256k1.h | 17 ++++++++++++----- src/bench_sign.c | 11 +---------- src/bench_verify.c | 11 +---------- src/secp256k1.c | 22 ++++++++++++++++++++-- src/tests.c | 13 ++----------- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Makefile.am b/Makefile.am index 904aaded..985c172e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,6 +33,8 @@ noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/util.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h +noinst_HEADERS += src/hash.h +noinst_HEADERS += src/hash_impl.h noinst_HEADERS += src/field.h noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h diff --git a/include/secp256k1.h b/include/secp256k1.h index 00129e7d..cfdae31e 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -87,7 +87,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( * data: Arbitrary data pointer that is passed through. * Out: nonce32: pointer to a 32-byte array to be filled by the function. * Except for test cases, this function should compute some cryptographic hash of - * the message, the key and the attempt. It is advised to use RFC6979. + * the message, the key and the attempt. */ typedef int (*secp256k1_nonce_function_t)( unsigned char *nonce32, @@ -97,12 +97,19 @@ typedef int (*secp256k1_nonce_function_t)( const void *data ); +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. */ +extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979; + +/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ +extern const secp256k1_nonce_function_t secp256k1_nonce_function_default; + + /** Create an ECDSA signature. * Returns: 1: signature created * 0: the nonce generation function failed * In: msg32: the 32-byte message hash being signed (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid) - * noncefp:pointer to a nonce generation function (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) * In/Out: siglen: pointer to an int with the length of sig, which will be updated @@ -116,14 +123,14 @@ int secp256k1_ecdsa_sign( const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void *ndata -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Create a compact ECDSA signature (64 byte + recovery id). * Returns: 1: signature created * 0: the nonce generation function failed * In: msg32: the 32-byte message hash being signed (cannot be NULL) * seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid) - * noncefp:pointer to a nonce generation function (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) * Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL) * recid: pointer to an int, which will be updated to contain the recovery id (can be NULL) @@ -136,7 +143,7 @@ int secp256k1_ecdsa_sign_compact( secp256k1_nonce_function_t noncefp, const void *ndata, int *recid -) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); /** Recover an ECDSA public key from a compact signature. * Returns: 1: public key successfully recovered (which guarantees a correct signature). diff --git a/src/bench_sign.c b/src/bench_sign.c index e4cb36c3..2d16defc 100644 --- a/src/bench_sign.c +++ b/src/bench_sign.c @@ -13,15 +13,6 @@ typedef struct { unsigned char key[32]; } bench_sign_t; -/** Very fast but insecure nonce generation function. Do not use for production code. */ -static int insecure_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int count, const void *data) { - (void)data; - for (int i = 0; i < 8; i++) { - ((uint32_t*)nonce32)[i] = ((uint32_t*)msg32)[i] + ((uint32_t*)key32)[i] + count; - } - return 1; -} - static void bench_sign_setup(void* arg) { bench_sign_t *data = (bench_sign_t*)arg; @@ -35,7 +26,7 @@ static void bench_sign(void* arg) { unsigned char sig[64]; for (int i=0; i<20000; i++) { int recid = 0; - secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, insecure_nonce_function, NULL, &recid); + secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, NULL, NULL, &recid); for (int j = 0; j < 32; j++) { data->msg[j] = sig[j]; /* Move former R to message. */ data->key[j] = sig[j + 32]; /* Move former S to key. */ diff --git a/src/bench_verify.c b/src/bench_verify.c index c3d1c39d..a58ca843 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -20,15 +20,6 @@ typedef struct { int pubkeylen; } benchmark_verify_t; -/** Very fast but insecure nonce generation function. Do not use for production code. */ -static int insecure_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int count, const void *data) { - (void)data; - for (int i = 0; i < 8; i++) { - ((uint32_t*)nonce32)[i] = ((uint32_t*)msg32)[i] + ((uint32_t*)key32)[i] + count; - } - return 1; -} - static void benchmark_verify(void* arg) { benchmark_verify_t* data = (benchmark_verify_t*)arg; @@ -51,7 +42,7 @@ int main(void) { for (int i = 0; i < 32; i++) data.msg[i] = 1 + i; for (int i = 0; i < 32; i++) data.key[i] = 33 + i; data.siglen = 72; - secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, insecure_nonce_function, NULL); + secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, NULL, NULL); data.pubkeylen = 33; CHECK(secp256k1_ec_pubkey_create(data.pubkey, &data.pubkeylen, data.key, 1)); diff --git a/src/secp256k1.c b/src/secp256k1.c index 6e95b2b0..58bcd8d0 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -70,13 +70,29 @@ end: return ret; } +static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { + (void)data; + secp256k1_rfc6979_hmac_sha256_t rng; + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32); + for (unsigned int i = 0; i <= counter; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + return 1; +} + +const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; +const secp256k1_nonce_function_t secp256k1_nonce_function_default = nonce_function_rfc6979; + int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata) { DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); DEBUG_CHECK(msg32 != NULL); DEBUG_CHECK(signature != NULL); DEBUG_CHECK(signaturelen != NULL); DEBUG_CHECK(seckey != NULL); - DEBUG_CHECK(noncefp != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } secp256k1_scalar_t sec, non, msg; secp256k1_scalar_set_b32(&sec, seckey, NULL); @@ -114,7 +130,9 @@ int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig6 DEBUG_CHECK(msg32 != NULL); DEBUG_CHECK(sig64 != NULL); DEBUG_CHECK(seckey != NULL); - DEBUG_CHECK(noncefp != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } secp256k1_scalar_t sec, non, msg; secp256k1_scalar_set_b32(&sec, seckey, NULL); diff --git a/src/tests.c b/src/tests.c index a00d6480..84627dda 100644 --- a/src/tests.c +++ b/src/tests.c @@ -1064,15 +1064,6 @@ void run_ecdsa_sign_verify(void) { } } -/** Very fast but insecure nonce generation function. Do not use for production code. */ -static int insecure_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { - (void)data; - for (int i = 0; i < 8; i++) { - ((uint32_t*)nonce32)[i] = ((uint32_t*)msg32)[i] + ((uint32_t*)key32)[i] + counter; - } - return 1; -} - /** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { (void)msg32; @@ -1138,7 +1129,7 @@ void test_ecdsa_end_to_end(void) { /* Sign. */ unsigned char signature[72]; int signaturelen = 72; - CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, insecure_nonce_function, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, NULL, NULL) == 1); /* Verify. */ CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) == 1); /* Destroy signature and verify again. */ @@ -1147,7 +1138,7 @@ void test_ecdsa_end_to_end(void) { /* Compact sign. */ unsigned char csignature[64]; int recid = 0; - CHECK(secp256k1_ecdsa_sign_compact(message, csignature, privkey, insecure_nonce_function, NULL, &recid) == 1); + CHECK(secp256k1_ecdsa_sign_compact(message, csignature, privkey, NULL, NULL, &recid) == 1); /* Recover. */ unsigned char recpubkey[65]; int recpubkeylen = 0; CHECK(secp256k1_ecdsa_recover_compact(message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1);