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:
parent
a0c3fc177f
commit
d8d806aaf3
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue