From 1573a102c096918ab092f34843c2931ab3f023f1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 20 Mar 2015 09:19:38 -0700 Subject: [PATCH 1/2] Add ability to pass extra entropy to rfc6979 Suggested by Greg Maxwell. --- include/secp256k1.h | 5 ++++- src/bench_internal.c | 2 +- src/hash.h | 2 +- src/hash_impl.h | 8 +++++++- src/secp256k1.c | 3 +-- src/testrand_impl.h | 2 +- src/tests.c | 12 ++++++++++-- 7 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index 79477fa403..a6e39d13db 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -97,7 +97,10 @@ typedef int (*secp256k1_nonce_function_t)( const void *data ); -/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. */ +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * extra entropy. + */ extern const secp256k1_nonce_function_t secp256k1_nonce_function_rfc6979; /** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ diff --git a/src/bench_internal.c b/src/bench_internal.c index 6e3c556544..a960549b94 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -265,7 +265,7 @@ void bench_rfc6979_hmac_sha256(void* arg) { secp256k1_rfc6979_hmac_sha256_t rng; for (i = 0; i < 20000; i++) { - secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 32, data->data, 32); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 32, data->data, 32, NULL, 0); secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); } } diff --git a/src/hash.h b/src/hash.h index ee625b8e58..843423d7f7 100644 --- a/src/hash.h +++ b/src/hash.h @@ -34,7 +34,7 @@ typedef struct { int retry; } secp256k1_rfc6979_hmac_sha256_t; -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen); +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen, const unsigned char *rnd, size_t rndlen); static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); diff --git a/src/hash_impl.h b/src/hash_impl.h index 6ceb9aa13e..60fdbf7718 100644 --- a/src/hash_impl.h +++ b/src/hash_impl.h @@ -200,7 +200,7 @@ static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsign } -static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen) { +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen, const unsigned char *msg, size_t msglen, const unsigned char *rnd, size_t rndlen) { secp256k1_hmac_sha256_t hmac; static const unsigned char zero[1] = {0x00}; static const unsigned char one[1] = {0x01}; @@ -213,6 +213,9 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 secp256k1_hmac_sha256_write(&hmac, zero, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_write(&hmac, msg, msglen); + if (rnd && rndlen) { + secp256k1_hmac_sha256_write(&hmac, rnd, rndlen); + } secp256k1_hmac_sha256_finalize(&hmac, rng->k); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); @@ -223,6 +226,9 @@ static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha2 secp256k1_hmac_sha256_write(&hmac, one, 1); secp256k1_hmac_sha256_write(&hmac, key, keylen); secp256k1_hmac_sha256_write(&hmac, msg, msglen); + if (rnd && rndlen) { + secp256k1_hmac_sha256_write(&hmac, rnd, rndlen); + } secp256k1_hmac_sha256_finalize(&hmac, rng->k); secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); secp256k1_hmac_sha256_write(&hmac, rng->v, 32); diff --git a/src/secp256k1.c b/src/secp256k1.c index b940917c04..8c4eca4b62 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -66,8 +66,7 @@ int secp256k1_ecdsa_verify(const unsigned char *msg32, const unsigned char *sig, static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, unsigned int counter, const void *data) { secp256k1_rfc6979_hmac_sha256_t rng; unsigned int i; - (void)data; - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key32, 32, msg32, 32, data, data != NULL ? 32 : 0); for (i = 0; i <= counter; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); } diff --git a/src/testrand_impl.h b/src/testrand_impl.h index 36b05344cf..21c69f1c51 100644 --- a/src/testrand_impl.h +++ b/src/testrand_impl.h @@ -18,7 +18,7 @@ static uint32_t secp256k1_test_rng_precomputed[8]; static int secp256k1_test_rng_precomputed_used = 8; SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) { - secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, (const unsigned char*)"TestRNG", 7, seed16, 16); + secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, (const unsigned char*)"TestRNG", 7, seed16, 16, NULL, 0); } SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { diff --git a/src/tests.c b/src/tests.c index e8ec2daf08..a51747a247 100644 --- a/src/tests.c +++ b/src/tests.c @@ -200,16 +200,24 @@ void run_rfc6979_hmac_sha256_tests(void) { secp256k1_rfc6979_hmac_sha256_t rng; unsigned char out[32]; + unsigned char zero[1] = {0}; int i; - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32, NULL, 1); for (i = 0; i < 3; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out1[i], 32) == 0); } secp256k1_rfc6979_hmac_sha256_finalize(&rng); - secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 32, msg2, 32); + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32, zero, 1); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out1[i], 32) != 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 32, msg2, 32, zero, 0); for (i = 0; i < 3; i++) { secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); CHECK(memcmp(out, out2[i], 32) == 0); From efc571ceea14b22fff04deaa2f243c9ee5209fbb Mon Sep 17 00:00:00 2001 From: Gregory Maxwell Date: Fri, 27 Mar 2015 11:55:17 +0000 Subject: [PATCH 2/2] Add simple testcases for signing with rfc6979 extra entropy. --- src/tests.c | 59 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/tests.c b/src/tests.c index a51747a247..f7f1acac64 100644 --- a/src/tests.c +++ b/src/tests.c @@ -1226,15 +1226,22 @@ int is_empty_compact_signature(const unsigned char *sig64) { } void test_ecdsa_end_to_end(void) { + unsigned char extra[32] = {0x00}; unsigned char privkey[32]; unsigned char message[32]; unsigned char privkey2[32]; unsigned char csignature[64]; unsigned char signature[72]; + unsigned char signature2[72]; + unsigned char signature3[72]; + unsigned char signature4[72]; unsigned char pubkey[65]; unsigned char recpubkey[65]; unsigned char seckey[300]; int signaturelen = 72; + int signaturelen2 = 72; + int signaturelen3 = 72; + int signaturelen4 = 72; int recid = 0; int recpubkeylen = 0; int pubkeylen = 65; @@ -1297,8 +1304,26 @@ void test_ecdsa_end_to_end(void) { /* Sign. */ CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, NULL, NULL) == 1); CHECK(signaturelen > 0); + CHECK(secp256k1_ecdsa_sign(message, signature2, &signaturelen2, privkey, NULL, extra) == 1); + CHECK(signaturelen2 > 0); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign(message, signature3, &signaturelen3, privkey, NULL, extra) == 1); + CHECK(signaturelen3 > 0); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign(message, signature4, &signaturelen4, privkey, NULL, extra) == 1); + CHECK(signaturelen3 > 0); + CHECK((signaturelen != signaturelen2) || (memcmp(signature, signature2, signaturelen) != 0)); + CHECK((signaturelen != signaturelen3) || (memcmp(signature, signature3, signaturelen) != 0)); + CHECK((signaturelen3 != signaturelen2) || (memcmp(signature3, signature2, signaturelen3) != 0)); + CHECK((signaturelen4 != signaturelen3) || (memcmp(signature4, signature3, signaturelen4) != 0)); + CHECK((signaturelen4 != signaturelen2) || (memcmp(signature4, signature2, signaturelen4) != 0)); + CHECK((signaturelen4 != signaturelen) || (memcmp(signature4, signature, signaturelen4) != 0)); /* Verify. */ CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) == 1); + CHECK(secp256k1_ecdsa_verify(message, signature2, signaturelen2, pubkey, pubkeylen) == 1); + CHECK(secp256k1_ecdsa_verify(message, signature3, signaturelen3, pubkey, pubkeylen) == 1); + CHECK(secp256k1_ecdsa_verify(message, signature4, signaturelen4, pubkey, pubkeylen) == 1); /* Destroy signature and verify again. */ signature[signaturelen - 1 - secp256k1_rand32() % 20] += 1 + (secp256k1_rand32() % 255); CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) != 1); @@ -1405,6 +1430,7 @@ void test_ecdsa_edge_cases(void) { 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 }; unsigned char pubkey[65]; + int t; int pubkeylen = 65; /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ const unsigned char sigb64[64] = { @@ -1601,7 +1627,8 @@ void test_ecdsa_edge_cases(void) { } /* Nonce function corner cases. */ - { + for (t = 0; t < 2; t++) { + static const unsigned char zero[32] = {0x00}; int i; unsigned char key[32]; unsigned char msg[32]; @@ -1611,45 +1638,47 @@ void test_ecdsa_edge_cases(void) { int siglen = 72; int siglen2 = 72; int recid2; + const unsigned char *extra; + extra = t == 0 ? NULL : zero; memset(msg, 0, 32); msg[31] = 1; /* High key results in signature failure. */ memset(key, 0xFF, 32); - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 0); CHECK(siglen == 0); /* Zero key results in signature failure. */ memset(key, 0, 32); - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 0); CHECK(siglen == 0); /* Nonce function failure results in signature failure. */ key[31] = 1; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_fail, NULL) == 0); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_fail, extra) == 0); CHECK(siglen == 0); - CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_fail, NULL, &recid) == 0); + CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_fail, extra, &recid) == 0); CHECK(is_empty_compact_signature(sig)); /* The retry loop successfully makes its way to the first good value. */ siglen = 72; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_retry, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce_function_test_retry, extra) == 1); CHECK(siglen > 0); - CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, nonce_function_rfc6979, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, nonce_function_rfc6979, extra) == 1); CHECK(siglen > 0); CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0)); - CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_retry, NULL, &recid) == 1); + CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, nonce_function_test_retry, extra, &recid) == 1); CHECK(!is_empty_compact_signature(sig)); - CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, nonce_function_rfc6979, NULL, &recid2) == 1); + CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, nonce_function_rfc6979, extra, &recid2) == 1); CHECK(!is_empty_compact_signature(sig2)); CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0)); /* The default nonce function is determinstic. */ siglen = 72; siglen2 = 72; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, NULL, extra) == 1); CHECK(siglen > 0); - CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1); CHECK(siglen2 > 0); CHECK((siglen == siglen2) && (memcmp(sig, sig2, siglen) == 0)); - CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, NULL, NULL, &recid) == 1); + CHECK(secp256k1_ecdsa_sign_compact(msg, sig, key, NULL, extra, &recid) == 1); CHECK(!is_empty_compact_signature(sig)); - CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, NULL, NULL, &recid2) == 1); + CHECK(secp256k1_ecdsa_sign_compact(msg, sig2, key, NULL, extra, &recid2) == 1); CHECK(!is_empty_compact_signature(sig)); CHECK((recid == recid2) && (memcmp(sig, sig2, 64) == 0)); /* The default nonce function changes output with different messages. */ @@ -1657,7 +1686,7 @@ void test_ecdsa_edge_cases(void) { int j; siglen2 = 72; msg[0] = i; - CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1); CHECK(!is_empty_compact_signature(sig)); CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2)); for (j = 0; j < i; j++) { @@ -1671,7 +1700,7 @@ void test_ecdsa_edge_cases(void) { int j; siglen2 = 72; key[0] = i - 256; - CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig2, &siglen2, key, NULL, extra) == 1); CHECK(secp256k1_ecdsa_sig_parse(&s[i], sig2, siglen2)); for (j = 0; j < i; j++) { CHECK(!secp256k1_scalar_eq(&s[i].r, &s[j].r));