From c6e7f4e8d8df56a719411d5e8af09f3386c45cea Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 12 Dec 2014 18:11:39 +0100 Subject: [PATCH 1/3] [API BREAK] Use a nonce-generation function instead of a nonce --- include/secp256k1.h | 40 +++++++++++++++++++++++++++------- src/bench_sign.c | 14 ++++++++---- src/bench_verify.c | 13 +++++++++--- src/secp256k1.c | 52 +++++++++++++++++++++++++++++++++------------ src/tests.c | 39 +++++++++++++++++++--------------- 5 files changed, 112 insertions(+), 46 deletions(-) diff --git a/include/secp256k1.h b/include/secp256k1.h index dca7ca00e7e..00129e7d2c4 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -77,40 +77,64 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( int pubkeylen ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4); +/** A pointer to a function to deterministically generate a nonce. + * Returns: 1 if a nonce was succesfully generated. 0 will cause signing to fail. + * In: msg32: the 32-byte message hash being verified (will not be NULL) + * key32: pointer to a 32-byte secret key (will not be NULL) + * attempt: how many iterations we have tried to find a nonce. + * This will almost always be 0, but different attempt values + * are required to result in a different nonce. + * 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. + */ +typedef int (*secp256k1_nonce_function_t)( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + unsigned int attempt, + const void *data +); + /** Create an ECDSA signature. * Returns: 1: signature created - * 0: nonce invalid, try another one + * 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) - * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG) + * noncefp:pointer to a nonce generation function (cannot be NULL) + * 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 * to contain the actual signature length (<=72). * Requires starting using SECP256K1_START_SIGN. */ -SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign( +int secp256k1_ecdsa_sign( const unsigned char *msg32, unsigned char *sig, int *siglen, const unsigned char *seckey, - const unsigned char *nonce + 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); /** Create a compact ECDSA signature (64 byte + recovery id). * Returns: 1: signature created - * 0: nonce invalid, try another one + * 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) - * nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG) + * noncefp:pointer to a nonce generation function (cannot be NULL) + * 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) * Requires starting using SECP256K1_START_SIGN. */ -SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact( +int secp256k1_ecdsa_sign_compact( const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, - const unsigned char *nonce, + 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); diff --git a/src/bench_sign.c b/src/bench_sign.c index 66e71e1ac42..e4cb36c38a6 100644 --- a/src/bench_sign.c +++ b/src/bench_sign.c @@ -10,15 +10,22 @@ typedef struct { unsigned char msg[32]; - unsigned char nonce[32]; 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; for (int i = 0; i < 32; i++) data->msg[i] = i + 1; - for (int i = 0; i < 32; i++) data->nonce[i] = i + 33; for (int i = 0; i < 32; i++) data->key[i] = i + 65; } @@ -28,9 +35,8 @@ static void bench_sign(void* arg) { unsigned char sig[64]; for (int i=0; i<20000; i++) { int recid = 0; - CHECK(secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, data->nonce, &recid)); + secp256k1_ecdsa_sign_compact(data->msg, sig, data->key, insecure_nonce_function, NULL, &recid); for (int j = 0; j < 32; j++) { - data->nonce[j] = data->key[j]; /* Move former key to nonce */ 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 b123c4087d6..c3d1c39d864 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -14,13 +14,21 @@ typedef struct { unsigned char msg[32]; unsigned char key[32]; - unsigned char nonce[32]; unsigned char sig[72]; int siglen; unsigned char pubkey[33]; 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; @@ -42,9 +50,8 @@ 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; - for (int i = 0; i < 32; i++) data.nonce[i] = 65 + i; data.siglen = 72; - CHECK(secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, data.nonce)); + secp256k1_ecdsa_sign(data.msg, data.sig, &data.siglen, data.key, insecure_nonce_function, 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 4fb2d0aaba7..d1db6460298 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -69,23 +69,35 @@ end: return ret; } -int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) { +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(nonce != NULL); + DEBUG_CHECK(noncefp != NULL); secp256k1_scalar_t sec, non, msg; secp256k1_scalar_set_b32(&sec, seckey, NULL); - int overflow = 0; - secp256k1_scalar_set_b32(&non, nonce, &overflow); secp256k1_scalar_set_b32(&msg, msg32, NULL); - int ret = !secp256k1_scalar_is_zero(&non) && !overflow; + int overflow = 0; + int ret = 0; + unsigned int count = 0; secp256k1_ecdsa_sig_t sig; - if (ret) { - ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL); + while (1) { + unsigned char nonce32[32]; + ret = noncefp(nonce32, msg32, seckey, count, noncedata); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + memset(nonce32, 0, 32); + if (!secp256k1_scalar_is_zero(&non) && !overflow) { + if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL)) { + break; + } + } + count++; } if (ret) { ret = secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig); @@ -96,22 +108,34 @@ int secp256k1_ecdsa_sign(const unsigned char *msg32, unsigned char *signature, i return ret; } -int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) { +int secp256k1_ecdsa_sign_compact(const unsigned char *msg32, unsigned char *sig64, const unsigned char *seckey, secp256k1_nonce_function_t noncefp, const void* noncedata, int *recid) { DEBUG_CHECK(secp256k1_ecmult_gen_consts != NULL); DEBUG_CHECK(msg32 != NULL); DEBUG_CHECK(sig64 != NULL); DEBUG_CHECK(seckey != NULL); - DEBUG_CHECK(nonce != NULL); + DEBUG_CHECK(noncefp != NULL); secp256k1_scalar_t sec, non, msg; secp256k1_scalar_set_b32(&sec, seckey, NULL); - int overflow = 0; - secp256k1_scalar_set_b32(&non, nonce, &overflow); secp256k1_scalar_set_b32(&msg, msg32, NULL); - int ret = !secp256k1_scalar_is_zero(&non) && !overflow; + int overflow = 0; + int ret = 0; + unsigned int count = 0; secp256k1_ecdsa_sig_t sig; - if (ret) { - ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid); + while (1) { + unsigned char nonce32[32]; + ret = noncefp(nonce32, msg32, seckey, count, noncedata); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + memset(nonce32, 0, 32); + if (!secp256k1_scalar_is_zero(&non) && !overflow) { + if (secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid)) { + break; + } + } + count++; } if (ret) { secp256k1_scalar_get_b32(sig64, &sig.r); diff --git a/src/tests.c b/src/tests.c index 8ba1f28682b..8b2b223ef8f 100644 --- a/src/tests.c +++ b/src/tests.c @@ -949,6 +949,23 @@ 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; + (void)key32; + memcpy(nonce32, data, 32); + return (counter == 0); +} + void test_ecdsa_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; @@ -1006,13 +1023,7 @@ void test_ecdsa_end_to_end(void) { /* Sign. */ unsigned char signature[72]; int signaturelen = 72; - while(1) { - unsigned char rnd[32]; - secp256k1_rand256_test(rnd); - if (secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, rnd) == 1) { - break; - } - } + CHECK(secp256k1_ecdsa_sign(message, signature, &signaturelen, privkey, insecure_nonce_function, NULL) == 1); /* Verify. */ CHECK(secp256k1_ecdsa_verify(message, signature, signaturelen, pubkey, pubkeylen) == 1); /* Destroy signature and verify again. */ @@ -1021,13 +1032,7 @@ void test_ecdsa_end_to_end(void) { /* Compact sign. */ unsigned char csignature[64]; int recid = 0; - while(1) { - unsigned char rnd[32]; - secp256k1_rand256_test(rnd); - if (secp256k1_ecdsa_sign_compact(message, csignature, privkey, rnd, &recid) == 1) { - break; - } - } + CHECK(secp256k1_ecdsa_sign_compact(message, csignature, privkey, insecure_nonce_function, NULL, &recid) == 1); /* Recover. */ unsigned char recpubkey[65]; int recpubkeylen = 0; CHECK(secp256k1_ecdsa_recover_compact(message, csignature, recpubkey, &recpubkeylen, pubkeylen == 33, recid) == 1); @@ -1294,12 +1299,12 @@ void test_ecdsa_edge_cases(void) { }; unsigned char sig[72]; int siglen = 72; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce) == 0); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 0); msg[31] = 0xaa; siglen = 72; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce) == 1); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) == 1); siglen = 10; - CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, nonce) != 1); + CHECK(secp256k1_ecdsa_sign(msg, sig, &siglen, key, precomputed_nonce_function, nonce) != 1); } /* Privkey export where pubkey is the point at infinity. */ From b37fbc280e2c1bd25c642fcc0099aa4d269ef24e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 13 Dec 2014 17:02:30 +0100 Subject: [PATCH 2/3] Implement SHA256 / HMAC-SHA256 / RFC6979. --- src/hash.h | 41 +++++++ src/hash_impl.h | 291 ++++++++++++++++++++++++++++++++++++++++++++++++ src/secp256k1.c | 1 + src/tests.c | 119 ++++++++++++++++++++ 4 files changed, 452 insertions(+) create mode 100644 src/hash.h create mode 100644 src/hash_impl.h diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 00000000000..d1e65b968a9 --- /dev/null +++ b/src/hash.h @@ -0,0 +1,41 @@ +/********************************************************************** + * 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_HASH_ +#define _SECP256K1_HASH_ + +#include +#include + +typedef struct { + uint32_t s[32]; + unsigned char buf[64]; + size_t bytes; +} secp256k1_sha256_t; + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); + +typedef struct { + secp256k1_sha256_t inner, outer; +} secp256k1_hmac_sha256_t; + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); + +typedef struct { + unsigned char v[32]; + unsigned char k[32]; + 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_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); + +#endif diff --git a/src/hash_impl.h b/src/hash_impl.h new file mode 100644 index 00000000000..f35c5f7a821 --- /dev/null +++ b/src/hash_impl.h @@ -0,0 +1,291 @@ +/********************************************************************** + * 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_HASH_IMPL_H_ +#define _SECP256K1_HASH_IMPL_H_ + +#include "hash.h" + +#include +#include + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) +#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) +#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) +#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) + +#define Round(a,b,c,d,e,f,g,h,k,w) do { \ + uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ + uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ + (d) += t1; \ + (h) = t1 + t2; \ +} while(0) + +#define ReadBE32(p) (((uint32_t)((p)[0])) << 24 | ((uint32_t)((p)[1])) << 16 | ((uint32_t)((p)[2])) << 8 | ((uint32_t)((p)[3]))) +#define WriteBE32(p, v) do { (p)[0] = (v) >> 24; (p)[1] = (v) >> 16; (p)[2] = (v) >> 8; (p)[3] = (v); } while(0) + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { + hash->s[0] = 0x6a09e667ul; + hash->s[1] = 0xbb67ae85ul; + hash->s[2] = 0x3c6ef372ul; + hash->s[3] = 0xa54ff53aul; + hash->s[4] = 0x510e527ful; + hash->s[5] = 0x9b05688cul; + hash->s[6] = 0x1f83d9abul; + hash->s[7] = 0x5be0cd19ul; + hash->bytes = 0; +} + +/** Perform one SHA-256 transformation, processing a 64-byte chunk. */ +static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0)); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4)); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8)); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12)); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16)); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20)); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24)); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28)); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32)); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36)); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40)); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44)); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48)); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52)); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56)); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60)); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { + const unsigned char* end = data + len; + size_t bufsize = hash->bytes % 64; + if (bufsize && bufsize + len >= 64) { + // Fill the buffer, and process it. + memcpy(hash->buf + bufsize, data, 64 - bufsize); + hash->bytes += 64 - bufsize; + data += 64 - bufsize; + secp256k1_sha256_transform(hash->s, hash->buf); + bufsize = 0; + } + while (end >= data + 64) { + // Process full chunks directly from the source. + secp256k1_sha256_transform(hash->s, data); + hash->bytes += 64; + data += 64; + } + if (end > data) { + // Fill the buffer with what remains. + memcpy(hash->buf + bufsize, data, end - data); + hash->bytes += end - data; + } +} + +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { + static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char sizedesc[8]; + WriteBE32(sizedesc, hash->bytes >> 29); + WriteBE32(sizedesc + 4, hash->bytes << 3); + secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + secp256k1_sha256_write(hash, sizedesc, 8); + WriteBE32(out32, hash->s[0]); + hash->s[0] = 0; + WriteBE32(out32 + 4, hash->s[1]); + hash->s[1] = 0; + WriteBE32(out32 + 8, hash->s[2]); + hash->s[2] = 0; + WriteBE32(out32 + 12, hash->s[3]); + hash->s[3] = 0; + WriteBE32(out32 + 16, hash->s[4]); + hash->s[4] = 0; + WriteBE32(out32 + 20, hash->s[5]); + hash->s[5] = 0; + WriteBE32(out32 + 24, hash->s[6]); + hash->s[6] = 0; + WriteBE32(out32 + 28, hash->s[7]); + hash->s[7] = 0; +} + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { + unsigned char rkey[64]; + if (keylen <= 64) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 64 - keylen); + } else { + secp256k1_sha256_t sha256; + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, key, keylen); + secp256k1_sha256_finalize(&sha256, rkey); + memset(rkey + 32, 0, 32); + } + + secp256k1_sha256_initialize(&hash->outer); + for (int n = 0; n < 64; n++) + rkey[n] ^= 0x5c; + secp256k1_sha256_write(&hash->outer, rkey, 64); + + secp256k1_sha256_initialize(&hash->inner); + for (int n = 0; n < 64; n++) + rkey[n] ^= 0x5c ^ 0x36; + secp256k1_sha256_write(&hash->inner, rkey, 64); + memset(rkey, 0, 64); +} + +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { + secp256k1_sha256_write(&hash->inner, data, size); +} + +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { + unsigned char temp[32]; + secp256k1_sha256_finalize(&hash->inner, temp); + secp256k1_sha256_write(&hash->outer, temp, 32); + memset(temp, 0, 32); + secp256k1_sha256_finalize(&hash->outer, out32); +} + + +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 const unsigned char zero[1] = {0x00}; + static const unsigned char one[1] = {0x01}; + + memset(rng->v, 0x01, 32); + memset(rng->k, 0x00, 32); + + secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_write(&hmac, msg, msglen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, one, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_write(&hmac, msg, msglen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + rng->retry = 0; +} + +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { + static const unsigned char zero[1] = {0x00}; + if (rng->retry) { + secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + } + + while (outlen > 0) { + secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + int now = outlen; + if (now > 32) { + now = 32; + } + memcpy(out, rng->v, now); + out += now; + outlen -= now; + } + + rng->retry = 1; +} + +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { + memset(rng->k, 0, 32); + memset(rng->v, 0, 32); + rng->retry = 0; +} + + +#undef Round +#undef sigma0 +#undef sigma1 +#undef Sigma0 +#undef Sigma1 +#undef Ch +#undef Maj +#undef ReadBE32 +#undef WriteBE32 + +#endif diff --git a/src/secp256k1.c b/src/secp256k1.c index d1db6460298..6e95b2b0a70 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -17,6 +17,7 @@ #include "ecmult_gen_impl.h" #include "ecdsa_impl.h" #include "eckey_impl.h" +#include "hash_impl.h" void secp256k1_start(unsigned int flags) { secp256k1_fe_start(); diff --git a/src/tests.c b/src/tests.c index 8b2b223ef8f..a00d6480939 100644 --- a/src/tests.c +++ b/src/tests.c @@ -91,6 +91,121 @@ void random_scalar_order(secp256k1_scalar_t *num) { } while(1); } +/***** HASH TESTS *****/ + +void run_sha256_tests(void) { + static const char *inputs[8] = { + "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "For this sample, this 63-byte string will be used as input data", + "This is exactly 64 bytes long, not counting the terminating byte" + }; + static const unsigned char outputs[8][32] = { + {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, + {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, + {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, + {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, + {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, + {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, + {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, + {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} + }; + for (int i = 0; i < 8; i++) { + secp256k1_sha256_t hasher; + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + unsigned char out[32]; + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + secp256k1_sha256_initialize(&hasher); + int split = secp256k1_rand32() % strlen(inputs[i]); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_hmac_sha256_tests(void) { + static const char *keys[6] = { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x4a\x65\x66\x65", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + }; + static const char *inputs[6] = { + "\x48\x69\x20\x54\x68\x65\x72\x65", + "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", + "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" + }; + static const unsigned char outputs[6][32] = { + {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, + {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, + {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, + {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, + {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, + {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} + }; + for (int i = 0; i < 6; i++) { + secp256k1_hmac_sha256_t hasher; + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + unsigned char out[32]; + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + int split = secp256k1_rand32() % strlen(inputs[i]); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_rfc6979_hmac_sha256_tests(void) { + static const unsigned char key1[32] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00}; + static const unsigned char msg1[32] = {0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a}; + static const unsigned char out1[3][32] = { + {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, + {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, + {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} + }; + + static const unsigned char key2[32] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + static const unsigned char msg2[32] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; + static const unsigned char out2[3][32] = { + {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, + {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, + {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} + }; + + secp256k1_rfc6979_hmac_sha256_t rng; + unsigned char out[32]; + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 32, msg1, 32); + for (int 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); + for (int i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out2[i], 32) == 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); +} + /***** NUM TESTS *****/ #ifndef USE_NUM_NONE @@ -1412,6 +1527,10 @@ int main(int argc, char **argv) { secp256k1_scalar_start(); secp256k1_ecdsa_start(); + run_sha256_tests(); + run_hmac_sha256_tests(); + run_rfc6979_hmac_sha256_tests(); + #ifndef USE_NUM_NONE /* num tests */ run_num_smalltests(); From bbd5ba7cfa03db851ae1de6d7be0e4c072cb6a54 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 13 Dec 2014 18:06:33 +0100 Subject: [PATCH 3/3] 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 904aaded22a..985c172eba2 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 00129e7d2c4..cfdae31eaf8 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 e4cb36c38a6..2d16defca1c 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 c3d1c39d864..a58ca84347b 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 6e95b2b0a70..58bcd8d009e 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 a00d6480939..84627dda78a 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);