From 5324f8942dd322448fae6c9b225ecac2854fa7e2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sat, 30 Oct 2021 13:03:55 -0400 Subject: [PATCH] Make aux_rnd32==NULL behave identical to 0x0000..00. BIP340's default signing algorithm always requires an aux_rnd argument, but permits using an all-zero one when no randomness is available. Make secp256k1_schnorrsig_sign follow this even when aux_rnd32==NULL, by treating the same as if an all-zero byte array was provided as input. --- include/secp256k1_schnorrsig.h | 3 ++- src/modules/schnorrsig/main_impl.h | 19 +++++++++++++------ src/modules/schnorrsig/tests_impl.h | 7 +++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/include/secp256k1_schnorrsig.h b/include/secp256k1_schnorrsig.h index dad7ed7c428de..e971ddc2aa8f2 100644 --- a/include/secp256k1_schnorrsig.h +++ b/include/secp256k1_schnorrsig.h @@ -111,7 +111,8 @@ typedef struct { * In: msg32: the 32-byte message being signed. * keypair: pointer to an initialized keypair. * aux_rand32: 32 bytes of fresh randomness. While recommended to provide - * this, it is only supplemental to security and can be NULL. See + * this, it is only supplemental to security and can be NULL. A + * NULL argument is treated the same as an all-zero one. See * BIP-340 "Default Signing" for a full explanation of this * argument and for guidance if randomness is expensive. */ diff --git a/src/modules/schnorrsig/main_impl.h b/src/modules/schnorrsig/main_impl.h index 0409b9e3bda50..94e3ee414d6d1 100644 --- a/src/modules/schnorrsig/main_impl.h +++ b/src/modules/schnorrsig/main_impl.h @@ -65,6 +65,17 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } + } else { + /* Precomputed TaggedHash("BIP0340/aux", 0x0000...00); */ + static const unsigned char ZERO_MASK[32] = { + 84, 241, 105, 207, 201, 226, 229, 114, + 116, 128, 68, 31, 144, 186, 37, 196, + 136, 244, 97, 199, 11, 94, 165, 220, + 170, 247, 175, 105, 39, 10, 165, 20 + }; + for (i = 0; i < 32; i++) { + masked_key[i] = key32[i] ^ ZERO_MASK[i]; + } } /* Tag the hash with algo which is important to avoid nonce reuse across @@ -77,12 +88,8 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms secp256k1_sha256_initialize_tagged(&sha, algo, algolen); } - /* Hash (masked-)key||pk||msg using the tagged hash as per the spec */ - if (data != NULL) { - secp256k1_sha256_write(&sha, masked_key, 32); - } else { - secp256k1_sha256_write(&sha, key32, 32); - } + /* Hash masked-key||pk||msg using the tagged hash as per the spec */ + secp256k1_sha256_write(&sha, masked_key, 32); secp256k1_sha256_write(&sha, xonly_pk32, 32); secp256k1_sha256_write(&sha, msg, msglen); secp256k1_sha256_finalize(&sha, nonce32); diff --git a/src/modules/schnorrsig/tests_impl.h b/src/modules/schnorrsig/tests_impl.h index 067fd06b57e7d..d301abee51b97 100644 --- a/src/modules/schnorrsig/tests_impl.h +++ b/src/modules/schnorrsig/tests_impl.h @@ -38,7 +38,7 @@ void run_nonce_function_bip340_tests(void) { size_t algolen = sizeof(algo); secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; - unsigned char nonce[32]; + unsigned char nonce[32], nonce_z[32]; unsigned char msg[32]; size_t msglen = sizeof(msg); unsigned char key[32]; @@ -107,8 +107,11 @@ void run_nonce_function_bip340_tests(void) { CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0); } - /* NULL aux_rand argument is allowed. */ + /* NULL aux_rand argument is allowed, and identical to passing all zero aux_rand. */ + memset(aux_rand, 0, 32); + CHECK(nonce_function_bip340(nonce_z, msg, msglen, key, pk, algo, algolen, &aux_rand) == 1); CHECK(nonce_function_bip340(nonce, msg, msglen, key, pk, algo, algolen, NULL) == 1); + CHECK(secp256k1_memcmp_var(nonce_z, nonce, 32) == 0); } void test_schnorrsig_api(void) {