schnorrsig: add extra parameter struct for sign_custom

This simplifies the interface of sign_custom and allows adding more parameters
later in a backward compatible way.
This commit is contained in:
Jonas Nick 2020-11-02 14:41:25 +00:00
parent a0c3fc177f
commit d8d806aaf3
4 changed files with 75 additions and 20 deletions

View File

@ -63,6 +63,35 @@ typedef int (*secp256k1_nonce_function_hardened)(
*/ */
SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340; SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
/** Data structure that contains additional arguments for schnorrsig_sign_custom.
*
* A schnorrsig_extraparams structure object can be initialized correctly by
* setting it to SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT.
*
* Members:
* magic: set to SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC at initialization
* and has no other function than making sure the object is
* initialized.
* noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_bip340 is used
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL). If it is non-NULL and
* secp256k1_nonce_function_bip340 is used, then ndata must be a
* pointer to 32-byte auxiliary randomness as per BIP-340.
*/
typedef struct {
unsigned char magic[4];
secp256k1_nonce_function_hardened noncefp;
void* ndata;
} secp256k1_schnorrsig_extraparams;
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC "\xda\x6f\xb3\x8c"
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\
NULL,\
NULL\
}
/** Create a Schnorr signature. /** Create a Schnorr signature.
* *
* Does _not_ strictly follow BIP-340 because it does not verify the resulting * Does _not_ strictly follow BIP-340 because it does not verify the resulting
@ -97,17 +126,15 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
/** Create a Schnorr signature with a more flexible API. /** Create a Schnorr signature with a more flexible API.
* *
* Same arguments as secp256k1_schnorrsig_sign except that it allows signing * Same arguments as secp256k1_schnorrsig_sign except that it allows signing
* variable length messages and allows providing a different nonce derivation * variable length messages and accepts a pointer to an extraparams object that
* function with its own data argument. * allows customizing signing by passing additional arguments.
*
* Creates the same signatures as schnorrsig_sign if msglen is 32 and the
* extraparams.ndata is the same as aux_rand32.
* *
* In: msg: the message being signed. Can only be NULL if msglen is 0. * In: msg: the message being signed. Can only be NULL if msglen is 0.
* msglen: length of the message * msglen: length of the message
* noncefp: pointer to a nonce generation function. If NULL, * extraparams: pointer to a extraparams object (can be NULL)
* secp256k1_nonce_function_bip340 is used.
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL). If it is non-NULL and
* secp256k1_nonce_function_bip340 is used, then ndata must be a
* pointer to 32-byte auxiliary randomness as per BIP-340.
*/ */
SECP256K1_API int secp256k1_schnorrsig_sign_custom( SECP256K1_API int secp256k1_schnorrsig_sign_custom(
const secp256k1_context* ctx, const secp256k1_context* ctx,
@ -115,8 +142,7 @@ SECP256K1_API int secp256k1_schnorrsig_sign_custom(
const unsigned char *msg, const unsigned char *msg,
size_t msglen, size_t msglen,
const secp256k1_keypair *keypair, const secp256k1_keypair *keypair,
secp256k1_nonce_function_hardened noncefp, secp256k1_schnorrsig_extraparams *extraparams
void *ndata
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5); ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5);
/** Verify a Schnorr signature. /** Verify a Schnorr signature.

View File

@ -120,11 +120,7 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c
secp256k1_scalar_set_b32(e, buf, NULL); secp256k1_scalar_set_b32(e, buf, NULL);
} }
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, unsigned char *aux_rand32) { int secp256k1_schnorrsig_sign_internal(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
return secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, 32, keypair, NULL, aux_rand32);
}
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_nonce_function_hardened noncefp, void *ndata) {
secp256k1_scalar sk; secp256k1_scalar sk;
secp256k1_scalar e; secp256k1_scalar e;
secp256k1_scalar k; secp256k1_scalar k;
@ -187,6 +183,25 @@ int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char
return ret; return ret;
} }
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, unsigned char *aux_rand32) {
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, aux_rand32);
}
int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_keypair *keypair, secp256k1_schnorrsig_extraparams *extraparams) {
secp256k1_nonce_function_hardened noncefp = NULL;
void *ndata = NULL;
VERIFY_CHECK(ctx != NULL);
if (extraparams != NULL) {
ARG_CHECK(secp256k1_memcmp_var(extraparams->magic,
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,
sizeof(extraparams->magic)) == 0);
noncefp = extraparams->noncefp;
ndata = extraparams->ndata;
}
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata);
}
int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey) { int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey) {
secp256k1_scalar s; secp256k1_scalar s;
secp256k1_scalar e; secp256k1_scalar e;

View File

@ -141,6 +141,8 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons
static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) { static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) {
int d, k; int d, k;
uint64_t iter = 0; uint64_t iter = 0;
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
/* Loop over keys. */ /* Loop over keys. */
for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) {
int actual_d = d; int actual_d = d;
@ -153,6 +155,8 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
unsigned char sig64[64]; unsigned char sig64[64];
int actual_k = k; int actual_k = k;
if (skip_section(&iter)) continue; if (skip_section(&iter)) continue;
extraparams.noncefp = secp256k1_hardened_nonce_function_smallint;
extraparams.ndata = &k;
if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k;
/* Generate random messages until all challenges have been tried. */ /* Generate random messages until all challenges have been tried. */
while (e_count_done < EXHAUSTIVE_TEST_ORDER) { while (e_count_done < EXHAUSTIVE_TEST_ORDER) {
@ -165,7 +169,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
unsigned char expected_s_bytes[32]; unsigned char expected_s_bytes[32];
secp256k1_scalar_get_b32(expected_s_bytes, &expected_s); secp256k1_scalar_get_b32(expected_s_bytes, &expected_s);
/* Invoke the real function to construct a signature. */ /* Invoke the real function to construct a signature. */
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &k)); CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams));
/* The first 32 bytes must match the xonly pubkey for the specified k. */ /* The first 32 bytes must match the xonly pubkey for the specified k. */
CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0); CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0);
/* The last 32 bytes must match the expected s value. */ /* The last 32 bytes must match the expected s value. */

View File

@ -690,24 +690,34 @@ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned cha
void test_schnorrsig_sign(void) { void test_schnorrsig_sign(void) {
unsigned char sk[32]; unsigned char sk[32];
secp256k1_xonly_pubkey pk;
secp256k1_keypair keypair; secp256k1_keypair keypair;
const unsigned char msg[32] = "this is a msg for a schnorrsig.."; const unsigned char msg[32] = "this is a msg for a schnorrsig..";
unsigned char sig[64]; unsigned char sig[64];
unsigned char zeros64[64] = { 0 }; unsigned char zeros64[64] = { 0 };
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
secp256k1_testrand256(sk); secp256k1_testrand256(sk);
CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL) == 1); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
/* Test different nonce functions */ /* Test different nonce functions */
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
memset(sig, 1, sizeof(sig)); memset(sig, 1, sizeof(sig));
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_failing, NULL) == 0); extraparams.noncefp = nonce_function_failing;
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 0);
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
memset(&sig, 1, sizeof(sig)); memset(&sig, 1, sizeof(sig));
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_0, NULL) == 0); extraparams.noncefp = nonce_function_0;
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 0);
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_overflowing, NULL) == 1); memset(&sig, 1, sizeof(sig));
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) != 0); extraparams.noncefp = nonce_function_overflowing;
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
} }
#define N_SIGS 3 #define N_SIGS 3