Skip to content

Commit d8d806a

Browse files
committed
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.
1 parent a0c3fc1 commit d8d806a

File tree

4 files changed

+75
-20
lines changed

4 files changed

+75
-20
lines changed

include/secp256k1_schnorrsig.h

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,35 @@ typedef int (*secp256k1_nonce_function_hardened)(
6363
*/
6464
SECP256K1_API extern const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
6565

66+
/** Data structure that contains additional arguments for schnorrsig_sign_custom.
67+
*
68+
* A schnorrsig_extraparams structure object can be initialized correctly by
69+
* setting it to SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT.
70+
*
71+
* Members:
72+
* magic: set to SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC at initialization
73+
* and has no other function than making sure the object is
74+
* initialized.
75+
* noncefp: pointer to a nonce generation function. If NULL,
76+
* secp256k1_nonce_function_bip340 is used
77+
* ndata: pointer to arbitrary data used by the nonce generation function
78+
* (can be NULL). If it is non-NULL and
79+
* secp256k1_nonce_function_bip340 is used, then ndata must be a
80+
* pointer to 32-byte auxiliary randomness as per BIP-340.
81+
*/
82+
typedef struct {
83+
unsigned char magic[4];
84+
secp256k1_nonce_function_hardened noncefp;
85+
void* ndata;
86+
} secp256k1_schnorrsig_extraparams;
87+
88+
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC "\xda\x6f\xb3\x8c"
89+
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\
90+
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\
91+
NULL,\
92+
NULL\
93+
}
94+
6695
/** Create a Schnorr signature.
6796
*
6897
* Does _not_ strictly follow BIP-340 because it does not verify the resulting
@@ -97,26 +126,23 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
97126
/** Create a Schnorr signature with a more flexible API.
98127
*
99128
* Same arguments as secp256k1_schnorrsig_sign except that it allows signing
100-
* variable length messages and allows providing a different nonce derivation
101-
* function with its own data argument.
129+
* variable length messages and accepts a pointer to an extraparams object that
130+
* allows customizing signing by passing additional arguments.
131+
*
132+
* Creates the same signatures as schnorrsig_sign if msglen is 32 and the
133+
* extraparams.ndata is the same as aux_rand32.
102134
*
103135
* In: msg: the message being signed. Can only be NULL if msglen is 0.
104136
* msglen: length of the message
105-
* noncefp: pointer to a nonce generation function. If NULL,
106-
* secp256k1_nonce_function_bip340 is used.
107-
* ndata: pointer to arbitrary data used by the nonce generation function
108-
* (can be NULL). If it is non-NULL and
109-
* secp256k1_nonce_function_bip340 is used, then ndata must be a
110-
* pointer to 32-byte auxiliary randomness as per BIP-340.
137+
* extraparams: pointer to a extraparams object (can be NULL)
111138
*/
112139
SECP256K1_API int secp256k1_schnorrsig_sign_custom(
113140
const secp256k1_context* ctx,
114141
unsigned char *sig64,
115142
const unsigned char *msg,
116143
size_t msglen,
117144
const secp256k1_keypair *keypair,
118-
secp256k1_nonce_function_hardened noncefp,
119-
void *ndata
145+
secp256k1_schnorrsig_extraparams *extraparams
120146
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5);
121147

122148
/** Verify a Schnorr signature.

src/modules/schnorrsig/main_impl.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,7 @@ static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned c
120120
secp256k1_scalar_set_b32(e, buf, NULL);
121121
}
122122

123-
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, unsigned char *aux_rand32) {
124-
return secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, 32, keypair, NULL, aux_rand32);
125-
}
126-
127-
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) {
123+
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) {
128124
secp256k1_scalar sk;
129125
secp256k1_scalar e;
130126
secp256k1_scalar k;
@@ -187,6 +183,25 @@ int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char
187183
return ret;
188184
}
189185

186+
int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_keypair *keypair, unsigned char *aux_rand32) {
187+
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg32, 32, keypair, secp256k1_nonce_function_bip340, aux_rand32);
188+
}
189+
190+
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) {
191+
secp256k1_nonce_function_hardened noncefp = NULL;
192+
void *ndata = NULL;
193+
VERIFY_CHECK(ctx != NULL);
194+
195+
if (extraparams != NULL) {
196+
ARG_CHECK(secp256k1_memcmp_var(extraparams->magic,
197+
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,
198+
sizeof(extraparams->magic)) == 0);
199+
noncefp = extraparams->noncefp;
200+
ndata = extraparams->ndata;
201+
}
202+
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata);
203+
}
204+
190205
int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg, size_t msglen, const secp256k1_xonly_pubkey *pubkey) {
191206
secp256k1_scalar s;
192207
secp256k1_scalar e;

src/modules/schnorrsig/tests_exhaustive_impl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, cons
141141
static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsigned char (*xonly_pubkey_bytes)[32], const secp256k1_keypair* keypairs, const int* parities) {
142142
int d, k;
143143
uint64_t iter = 0;
144+
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
145+
144146
/* Loop over keys. */
145147
for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) {
146148
int actual_d = d;
@@ -153,6 +155,8 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
153155
unsigned char sig64[64];
154156
int actual_k = k;
155157
if (skip_section(&iter)) continue;
158+
extraparams.noncefp = secp256k1_hardened_nonce_function_smallint;
159+
extraparams.ndata = &k;
156160
if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k;
157161
/* Generate random messages until all challenges have been tried. */
158162
while (e_count_done < EXHAUSTIVE_TEST_ORDER) {
@@ -165,7 +169,7 @@ static void test_exhaustive_schnorrsig_sign(const secp256k1_context *ctx, unsign
165169
unsigned char expected_s_bytes[32];
166170
secp256k1_scalar_get_b32(expected_s_bytes, &expected_s);
167171
/* Invoke the real function to construct a signature. */
168-
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &k));
172+
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig64, msg32, sizeof(msg32), &keypairs[d - 1], &extraparams));
169173
/* The first 32 bytes must match the xonly pubkey for the specified k. */
170174
CHECK(secp256k1_memcmp_var(sig64, xonly_pubkey_bytes[k - 1], 32) == 0);
171175
/* The last 32 bytes must match the expected s value. */

src/modules/schnorrsig/tests_impl.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -690,24 +690,34 @@ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned cha
690690

691691
void test_schnorrsig_sign(void) {
692692
unsigned char sk[32];
693+
secp256k1_xonly_pubkey pk;
693694
secp256k1_keypair keypair;
694695
const unsigned char msg[32] = "this is a msg for a schnorrsig..";
695696
unsigned char sig[64];
696697
unsigned char zeros64[64] = { 0 };
698+
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
697699

698700
secp256k1_testrand256(sk);
699701
CHECK(secp256k1_keypair_create(ctx, &keypair, sk));
702+
CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair));
700703
CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL) == 1);
704+
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
701705

702706
/* Test different nonce functions */
707+
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
708+
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
703709
memset(sig, 1, sizeof(sig));
704-
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_failing, NULL) == 0);
710+
extraparams.noncefp = nonce_function_failing;
711+
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 0);
705712
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
706713
memset(&sig, 1, sizeof(sig));
707-
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_0, NULL) == 0);
714+
extraparams.noncefp = nonce_function_0;
715+
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 0);
708716
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0);
709-
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, nonce_function_overflowing, NULL) == 1);
710-
CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) != 0);
717+
memset(&sig, 1, sizeof(sig));
718+
extraparams.noncefp = nonce_function_overflowing;
719+
CHECK(secp256k1_schnorrsig_sign_custom(ctx, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
720+
CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, sizeof(msg), &pk));
711721
}
712722

713723
#define N_SIGS 3

0 commit comments

Comments
 (0)