schnorrsig: add algolen argument to nonce_function_hardened
This avoids having to remove trailing NUL bytes in the nonce function
This commit is contained in:
parent
df3bfa12c3
commit
442cee5baf
@ -23,14 +23,15 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to
|
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to
|
||||||
* return an error.
|
* return an error.
|
||||||
* Out: nonce32: pointer to a 32-byte array to be filled by the function.
|
* Out: nonce32: pointer to a 32-byte array to be filled by the function
|
||||||
* In: msg32: the 32-byte message hash being verified (will not be NULL)
|
* 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)
|
* key32: pointer to a 32-byte secret key (will not be NULL)
|
||||||
* xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32
|
* xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32
|
||||||
* (will not be NULL)
|
* (will not be NULL)
|
||||||
* algo16: pointer to a 16-byte array describing the signature
|
* algo: pointer to an array describing the signature
|
||||||
* algorithm (will not be NULL).
|
* algorithm (will not be NULL)
|
||||||
* data: Arbitrary data pointer that is passed through.
|
* algolen: the length of the algo array
|
||||||
|
* data: arbitrary data pointer that is passed through
|
||||||
*
|
*
|
||||||
* Except for test cases, this function should compute some cryptographic hash of
|
* Except for test cases, this function should compute some cryptographic hash of
|
||||||
* the message, the key, the pubkey, the algorithm description, and data.
|
* the message, the key, the pubkey, the algorithm description, and data.
|
||||||
@ -40,7 +41,8 @@ typedef int (*secp256k1_nonce_function_hardened)(
|
|||||||
const unsigned char *msg32,
|
const unsigned char *msg32,
|
||||||
const unsigned char *key32,
|
const unsigned char *key32,
|
||||||
const unsigned char *xonly_pk32,
|
const unsigned char *xonly_pk32,
|
||||||
const unsigned char *algo16,
|
const unsigned char *algo,
|
||||||
|
size_t algolen,
|
||||||
void *data
|
void *data
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -51,10 +53,10 @@ typedef int (*secp256k1_nonce_function_hardened)(
|
|||||||
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
|
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
|
||||||
* auxiliary random data as defined in BIP-340. If the data pointer is NULL,
|
* auxiliary random data as defined in BIP-340. If the data pointer is NULL,
|
||||||
* the nonce derivation procedure follows BIP-340 by setting the auxiliary
|
* the nonce derivation procedure follows BIP-340 by setting the auxiliary
|
||||||
* random data to zero. The algo16 argument must be non-NULL, otherwise the
|
* random data to zero. The algo argument must be non-NULL, otherwise the
|
||||||
* function will fail and return 0. The hash will be tagged with algo16 after
|
* function will fail and return 0. The hash will be tagged with algo.
|
||||||
* removing all terminating null bytes. Therefore, to create BIP-340 compliant
|
* Therefore, to create BIP-340 compliant signatures, algo must be set to
|
||||||
* signatures, algo16 must be set to "BIP0340/nonce\0\0\0"
|
* "BIP0340/nonce" and algolen to 13.
|
||||||
*/
|
*/
|
||||||
SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
|
SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
|
||||||
|
|
||||||
|
@ -43,16 +43,16 @@ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *
|
|||||||
sha->bytes = 64;
|
sha->bytes = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* algo16 argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
|
/* algo argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340
|
||||||
* by using the correct tagged hash function. */
|
* by using the correct tagged hash function. */
|
||||||
static const unsigned char bip340_algo16[16] = "BIP0340/nonce\0\0\0";
|
static const unsigned char bip340_algo[13] = "BIP0340/nonce";
|
||||||
|
|
||||||
static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
|
static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
|
||||||
secp256k1_sha256 sha;
|
secp256k1_sha256 sha;
|
||||||
unsigned char masked_key[32];
|
unsigned char masked_key[32];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (algo16 == NULL) {
|
if (algo == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,18 +65,14 @@ static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *ms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tag the hash with algo16 which is important to avoid nonce reuse across
|
/* Tag the hash with algo which is important to avoid nonce reuse across
|
||||||
* algorithms. If this nonce function is used in BIP-340 signing as defined
|
* algorithms. If this nonce function is used in BIP-340 signing as defined
|
||||||
* in the spec, an optimized tagging implementation is used. */
|
* in the spec, an optimized tagging implementation is used. */
|
||||||
if (secp256k1_memcmp_var(algo16, bip340_algo16, 16) == 0) {
|
if (algolen == sizeof(bip340_algo)
|
||||||
|
&& secp256k1_memcmp_var(algo, bip340_algo, algolen) == 0) {
|
||||||
secp256k1_nonce_function_bip340_sha256_tagged(&sha);
|
secp256k1_nonce_function_bip340_sha256_tagged(&sha);
|
||||||
} else {
|
} else {
|
||||||
int algo16_len = 16;
|
secp256k1_sha256_initialize_tagged(&sha, algo, algolen);
|
||||||
/* Remove terminating null bytes */
|
|
||||||
while (algo16_len > 0 && !algo16[algo16_len - 1]) {
|
|
||||||
algo16_len--;
|
|
||||||
}
|
|
||||||
secp256k1_sha256_initialize_tagged(&sha, algo16, algo16_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hash (masked-)key||pk||msg using the tagged hash as per the spec */
|
/* Hash (masked-)key||pk||msg using the tagged hash as per the spec */
|
||||||
@ -156,7 +152,7 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64
|
|||||||
|
|
||||||
secp256k1_scalar_get_b32(seckey, &sk);
|
secp256k1_scalar_get_b32(seckey, &sk);
|
||||||
secp256k1_fe_get_b32(pk_buf, &pk.x);
|
secp256k1_fe_get_b32(pk_buf, &pk.x);
|
||||||
ret &= !!noncefp(buf, msg32, seckey, pk_buf, bip340_algo16, ndata);
|
ret &= !!noncefp(buf, msg32, seckey, pk_buf, bip340_algo, sizeof(bip340_algo), ndata);
|
||||||
secp256k1_scalar_set_b32(&k, buf, NULL);
|
secp256k1_scalar_set_b32(&k, buf, NULL);
|
||||||
ret &= !secp256k1_scalar_is_zero(&k);
|
ret &= !secp256k1_scalar_is_zero(&k);
|
||||||
secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
|
secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret);
|
||||||
|
@ -60,13 +60,15 @@ static const unsigned char invalid_pubkey_bytes[][32] = {
|
|||||||
|
|
||||||
static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32,
|
static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32,
|
||||||
const unsigned char *key32, const unsigned char *xonly_pk32,
|
const unsigned char *key32, const unsigned char *xonly_pk32,
|
||||||
const unsigned char *algo16, void* data) {
|
const unsigned char *algo, size_t algolen,
|
||||||
|
void* data) {
|
||||||
secp256k1_scalar s;
|
secp256k1_scalar s;
|
||||||
int *idata = data;
|
int *idata = data;
|
||||||
(void)msg32;
|
(void)msg32;
|
||||||
(void)key32;
|
(void)key32;
|
||||||
(void)xonly_pk32;
|
(void)xonly_pk32;
|
||||||
(void)algo16;
|
(void)algo;
|
||||||
|
(void)algolen;
|
||||||
secp256k1_scalar_set_int(&s, *idata);
|
secp256k1_scalar_set_int(&s, *idata);
|
||||||
secp256k1_scalar_get_b32(nonce32, &s);
|
secp256k1_scalar_get_b32(nonce32, &s);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
|
/* Checks that a bit flip in the n_flip-th argument (that has n_bytes many
|
||||||
* bytes) changes the hash function
|
* bytes) changes the hash function
|
||||||
*/
|
*/
|
||||||
void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) {
|
void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes, size_t algolen) {
|
||||||
unsigned char nonces[2][32];
|
unsigned char nonces[2][32];
|
||||||
CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1);
|
CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], algolen, args[4]) == 1);
|
||||||
secp256k1_testrand_flip(args[n_flip], n_bytes);
|
secp256k1_testrand_flip(args[n_flip], n_bytes);
|
||||||
CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1);
|
CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], algolen, args[4]) == 1);
|
||||||
CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0);
|
CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,8 @@ void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2)
|
|||||||
void run_nonce_function_bip340_tests(void) {
|
void run_nonce_function_bip340_tests(void) {
|
||||||
unsigned char tag[13] = "BIP0340/nonce";
|
unsigned char tag[13] = "BIP0340/nonce";
|
||||||
unsigned char aux_tag[11] = "BIP0340/aux";
|
unsigned char aux_tag[11] = "BIP0340/aux";
|
||||||
unsigned char algo16[16] = "BIP0340/nonce\0\0\0";
|
unsigned char algo[13] = "BIP0340/nonce";
|
||||||
|
size_t algolen = sizeof(algo);
|
||||||
secp256k1_sha256 sha;
|
secp256k1_sha256 sha;
|
||||||
secp256k1_sha256 sha_optimized;
|
secp256k1_sha256 sha_optimized;
|
||||||
unsigned char nonce[32];
|
unsigned char nonce[32];
|
||||||
@ -68,33 +69,37 @@ void run_nonce_function_bip340_tests(void) {
|
|||||||
args[0] = msg;
|
args[0] = msg;
|
||||||
args[1] = key;
|
args[1] = key;
|
||||||
args[2] = pk;
|
args[2] = pk;
|
||||||
args[3] = algo16;
|
args[3] = algo;
|
||||||
args[4] = aux_rand;
|
args[4] = aux_rand;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
nonce_function_bip340_bitflip(args, 0, 32);
|
nonce_function_bip340_bitflip(args, 0, 32, algolen);
|
||||||
nonce_function_bip340_bitflip(args, 1, 32);
|
nonce_function_bip340_bitflip(args, 1, 32, algolen);
|
||||||
nonce_function_bip340_bitflip(args, 2, 32);
|
nonce_function_bip340_bitflip(args, 2, 32, algolen);
|
||||||
/* Flip algo16 special case "BIP0340/nonce" */
|
/* Flip algo special case "BIP0340/nonce" */
|
||||||
nonce_function_bip340_bitflip(args, 3, 16);
|
nonce_function_bip340_bitflip(args, 3, algolen, algolen);
|
||||||
/* Flip algo16 again */
|
/* Flip algo again */
|
||||||
nonce_function_bip340_bitflip(args, 3, 16);
|
nonce_function_bip340_bitflip(args, 3, algolen, algolen);
|
||||||
nonce_function_bip340_bitflip(args, 4, 32);
|
nonce_function_bip340_bitflip(args, 4, 32, algolen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NULL algo16 is disallowed */
|
/* NULL algo is disallowed */
|
||||||
CHECK(nonce_function_bip340(nonce, msg, key, pk, NULL, NULL) == 0);
|
CHECK(nonce_function_bip340(nonce, msg, key, pk, NULL, 0, NULL) == 0);
|
||||||
/* Empty algo16 is fine */
|
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo, algolen, NULL) == 1);
|
||||||
memset(algo16, 0x00, 16);
|
/* Other algo is fine */
|
||||||
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
|
secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, algo, algolen);
|
||||||
/* algo16 with terminating null bytes is fine */
|
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo, algolen, NULL) == 1);
|
||||||
algo16[1] = 65;
|
|
||||||
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
|
for (i = 0; i < count; i++) {
|
||||||
/* Other algo16 is fine */
|
unsigned char nonce2[32];
|
||||||
memset(algo16, 0xFF, 16);
|
/* Different algolen gives different nonce */
|
||||||
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
|
uint32_t offset = secp256k1_testrand_int(algolen - 1);
|
||||||
|
size_t algolen_tmp = (algolen + offset) % algolen;
|
||||||
|
CHECK(nonce_function_bip340(nonce2, msg, key, pk, algo, algolen_tmp, NULL) == 1);
|
||||||
|
CHECK(secp256k1_memcmp_var(nonce, nonce2, 32) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* NULL aux_rand argument is allowed. */
|
/* NULL aux_rand argument is allowed. */
|
||||||
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1);
|
CHECK(nonce_function_bip340(nonce, msg, key, pk, algo, algolen, NULL) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_schnorrsig_api(void) {
|
void test_schnorrsig_api(void) {
|
||||||
@ -634,22 +639,24 @@ void test_schnorrsig_bip_vectors(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Nonce function that returns constant 0 */
|
/* Nonce function that returns constant 0 */
|
||||||
static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
|
static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
|
||||||
(void) msg32;
|
(void) msg32;
|
||||||
(void) key32;
|
(void) key32;
|
||||||
(void) xonly_pk32;
|
(void) xonly_pk32;
|
||||||
(void) algo16;
|
(void) algo;
|
||||||
|
(void) algolen;
|
||||||
(void) data;
|
(void) data;
|
||||||
(void) nonce32;
|
(void) nonce32;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nonce function that sets nonce to 0 */
|
/* Nonce function that sets nonce to 0 */
|
||||||
static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
|
static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
|
||||||
(void) msg32;
|
(void) msg32;
|
||||||
(void) key32;
|
(void) key32;
|
||||||
(void) xonly_pk32;
|
(void) xonly_pk32;
|
||||||
(void) algo16;
|
(void) algo;
|
||||||
|
(void) algolen;
|
||||||
(void) data;
|
(void) data;
|
||||||
|
|
||||||
memset(nonce32, 0, 32);
|
memset(nonce32, 0, 32);
|
||||||
@ -657,11 +664,12 @@ static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Nonce function that sets nonce to 0xFF...0xFF */
|
/* Nonce function that sets nonce to 0xFF...0xFF */
|
||||||
static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) {
|
static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
|
||||||
(void) msg32;
|
(void) msg32;
|
||||||
(void) key32;
|
(void) key32;
|
||||||
(void) xonly_pk32;
|
(void) xonly_pk32;
|
||||||
(void) algo16;
|
(void) algo;
|
||||||
|
(void) algolen;
|
||||||
(void) data;
|
(void) data;
|
||||||
|
|
||||||
memset(nonce32, 0xFF, 32);
|
memset(nonce32, 0xFF, 32);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user