Skip to content

Commit

Permalink
use the magic in the schnorrsig extraparams struct for versioning
Browse files Browse the repository at this point in the history
This ensures compatibility in that it makes sure that the
`secp256k1_schnorrsig_sign_custom()` works for users using an older
version of the headers but linking against a newer version of the
library.
  • Loading branch information
benma committed Jul 29, 2023
1 parent 82557b4 commit d74f77a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 9 deletions.
31 changes: 26 additions & 5 deletions include/secp256k1_schnorrsig.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,22 @@ typedef int (*secp256k1_nonce_function_hardened)(
*/
SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;

/** First version of the extraparams struct. See `secp256k1_schnorrsig_extraparams` for the
latest version and its documentation.
*/
typedef struct {
unsigned char magic[4];
secp256k1_nonce_function_hardened noncefp;
void *ndata;
} secp256k1_schnorrsig_extraparams_v0;

/** 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
* 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,
Expand All @@ -150,16 +159,28 @@ typedef struct {
void *ndata;
secp256k1_schnorrsig_s2c_opening* s2c_opening;
const unsigned char* s2c_data32;
} secp256k1_schnorrsig_extraparams;
} secp256k1_schnorrsig_extraparams_v1;

typedef secp256k1_schnorrsig_extraparams_v1 secp256k1_schnorrsig_extraparams;

#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0 { 0xda, 0x6f, 0xb3, 0x8c }
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1 { 0x05, 0x96, 0x5b, 0x5c }
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1

#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V0 {\
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0,\
NULL,\
NULL\
}

#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c }
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V1 {\
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1,\
NULL,\
NULL,\
NULL,\
NULL\
}
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V1

/** Create a Schnorr signature.
*
Expand Down
16 changes: 12 additions & 4 deletions src/modules/schnorrsig/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *
* by using the correct tagged hash function. */
static const unsigned char bip340_algo[13] = "BIP0340/nonce";

static const unsigned char schnorrsig_extraparams_magic[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC;
static const unsigned char schnorrsig_extraparams_magic_v0[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V0;
static const unsigned char schnorrsig_extraparams_magic_v1[4] = SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC_V1;

static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg, size_t msglen, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo, size_t algolen, void *data) {
secp256k1_sha256 sha;
Expand Down Expand Up @@ -309,12 +310,19 @@ int secp256k1_schnorrsig_sign_custom(const secp256k1_context* ctx, unsigned char

if (extraparams != NULL) {
ARG_CHECK(secp256k1_memcmp_var(extraparams->magic,
schnorrsig_extraparams_magic,
schnorrsig_extraparams_magic_v0,
sizeof(extraparams->magic)) == 0 ||
secp256k1_memcmp_var(extraparams->magic,
schnorrsig_extraparams_magic_v1,
sizeof(extraparams->magic)) == 0);
noncefp = extraparams->noncefp;
ndata = extraparams->ndata;
s2c_opening = extraparams->s2c_opening;
s2c_data32 = extraparams->s2c_data32;
if (secp256k1_memcmp_var(extraparams->magic,
schnorrsig_extraparams_magic_v1,
sizeof(extraparams->magic)) == 0) {
s2c_opening = extraparams->s2c_opening;
s2c_data32 = extraparams->s2c_data32;
}
}
return secp256k1_schnorrsig_sign_internal(ctx, sig64, msg, msglen, keypair, noncefp, ndata, s2c_opening, s2c_data32);
}
Expand Down
6 changes: 6 additions & 0 deletions src/modules/schnorrsig/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ void test_schnorrsig_sign(void) {
unsigned char sig[64];
unsigned char sig2[64];
unsigned char zeros64[64] = { 0 };
secp256k1_schnorrsig_extraparams_v0 extraparams_v0 = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT_V0;
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
unsigned char aux_rand[32];

Expand Down Expand Up @@ -917,6 +918,11 @@ void test_schnorrsig_sign(void) {
CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, &extraparams) == 1);
CHECK(secp256k1_schnorrsig_sign32(CTX, sig2, msg, &keypair, extraparams.ndata) == 1);
CHECK(secp256k1_memcmp_var(sig, sig2, sizeof(sig)) == 0);

/* Test extraparams v0 to simulate users using old headers linking against a new version of the library */
memset(sig, 1, sizeof(sig));
CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, sizeof(msg), &keypair, (secp256k1_schnorrsig_extraparams*)&extraparams_v0) == 1);
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, sizeof(msg), &pk));
}

#define N_SIGS 3
Expand Down

0 comments on commit d74f77a

Please sign in to comment.