Use rfc6979 as default nonce generation function

This commit is contained in:
Pieter Wuille 2014-12-13 18:06:33 +01:00
parent b37fbc280e
commit bbd5ba7cfa
6 changed files with 38 additions and 38 deletions

View File

@ -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

View File

@ -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).

View File

@ -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. */

View File

@ -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));

View File

@ -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);

View File

@ -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);