Skip to content

Commit

Permalink
Add verification of schnorrsig sign-to-contract commitments
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasnick committed Feb 13, 2019
1 parent 6ddb655 commit 8fa102c
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 4 deletions.
27 changes: 24 additions & 3 deletions include/secp256k1_schnorrsig.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ SECP256K1_API int secp256k1_schnorrsig_parse(
* nonce (can be NULL)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_bipschnorr is used
* noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_bipschnorr is used
* ndata: pointer to arbitrary data used by the nonce generation function. If non-NULL must
* be a pointer to a s2c_context object when using the default nonce function
* secp256k1_nonce_function_bipschnorr (can be NULL)
* be a pointer to an s2c_context object when using the default nonce function
* secp256k1_nonce_function_bipschnorr. s2c_context must be initialized with
* secp256k1_s2c_commit_context_create. (can be NULL)
*/
SECP256K1_API int secp256k1_schnorrsig_sign(
const secp256k1_context* ctx,
Expand Down Expand Up @@ -117,4 +119,23 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify_batch
const secp256k1_pubkey *const *pk,
size_t n_sigs
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Verify a sign-to-contract commitment.
*
* Returns: 1: the signature contains a commitment to data32
* 0: incorrect opening
* Args: ctx: a secp256k1 context object, initialized for verification.
* In: sig: the signature containing the sign-to-contract commitment (cannot be NULL)
* data32: the 32-byte data that was committed to (cannot be NULL)
* original_nonce: pointer to the original_nonce created when signing (cannot be NULL)
* negated_nonce: integer indicating if signing algorithm negated the nonce
*/
SECP256K1_API int secp256k1_schnorrsig_verify_s2c_commit(
const secp256k1_context* ctx,
const secp256k1_schnorrsig *sig,
const unsigned char *data32,
const secp256k1_pubkey *original_nonce,
int negated_nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

#endif
23 changes: 23 additions & 0 deletions src/modules/schnorrsig/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ int secp256k1_schnorrsig_parse(const secp256k1_context* ctx, secp256k1_schnorrsi
return 1;
}

int secp256k1_schnorrsig_verify_s2c_commit(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *data32, const secp256k1_pubkey *original_nonce, int negated_nonce) {
secp256k1_fe rx;
secp256k1_ge R;
secp256k1_pubkey pubnonce;

VERIFY_CHECK(ctx != NULL);
ARG_CHECK(sig != NULL);
ARG_CHECK(data32 != NULL);
ARG_CHECK(original_nonce != NULL);

if (!secp256k1_fe_set_b32(&rx, &sig->data[0])) {
return 0;
}
if (!secp256k1_ge_set_xquad(&R, &rx)) {
return 0;
}
if(negated_nonce) {
secp256k1_ge_neg(&R, &R);
}
secp256k1_pubkey_save(&pubnonce, &R);
return secp256k1_ec_commit_verify(ctx, &pubnonce, original_nonce, data32, 32);
}

int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, secp256k1_schnorrsig *sig, int *nonce_is_negated, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, void *ndata) {
secp256k1_scalar x;
secp256k1_scalar e;
Expand Down
76 changes: 75 additions & 1 deletion src/modules/schnorrsig/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,25 @@ void test_schnorrsig_api(secp256k1_scratch_space *scratch) {
unsigned char sk2[32];
unsigned char sk3[32];
unsigned char msg[32];
unsigned char data32[32];
unsigned char sig64[64];
secp256k1_pubkey pk[3];
secp256k1_schnorrsig sig;
secp256k1_s2c_commit_context s2c_ctx;
secp256k1_pubkey s2c_original_nonce;
const secp256k1_schnorrsig *sigptr = &sig;
const unsigned char *msgptr = msg;
const secp256k1_pubkey *pkptr = &pk[0];
int nonce_is_negated;
unsigned char ones[32];

/** setup **/
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
int ecount;
memset(ones, 0xff, 32);

secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount);
secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount);
Expand Down Expand Up @@ -88,6 +93,29 @@ void test_schnorrsig_api(secp256k1_scratch_space *scratch) {
CHECK(secp256k1_schnorrsig_parse(none, &sig, NULL) == 0);
CHECK(ecount == 4);

/* Create sign-to-contract commitment to data32 for testing verify_s2c_commit */
secp256k1_rand256(data32);
CHECK(secp256k1_s2c_commit_context_create(ctx, &s2c_ctx, data32) == 1);
CHECK(secp256k1_schnorrsig_sign(sign, &sig, &nonce_is_negated, msg, sk1, NULL, &s2c_ctx) == 1);
CHECK(secp256k1_s2c_commit_get_original_nonce(ctx, &s2c_original_nonce, &s2c_ctx) == 1);
ecount = 0;
CHECK(secp256k1_schnorrsig_verify_s2c_commit(none, &sig, data32, &s2c_original_nonce, nonce_is_negated) == 0);
CHECK(ecount == 1);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(vrfy, &sig, data32, &s2c_original_nonce, nonce_is_negated) == 1);
CHECK(ecount == 1);
{
/* Overflowing x-coordinate in signature */
secp256k1_schnorrsig sig_tmp = sig;
memcpy(&sig_tmp.data[0], ones, 32);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(vrfy, &sig_tmp, data32, &s2c_original_nonce, nonce_is_negated) == 0);
}
CHECK(secp256k1_schnorrsig_verify_s2c_commit(vrfy, NULL, data32, &s2c_original_nonce, nonce_is_negated) == 0);
CHECK(ecount == 2);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(vrfy, &sig, NULL, &s2c_original_nonce, nonce_is_negated) == 0);
CHECK(ecount == 3);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(vrfy, &sig, data32, NULL, nonce_is_negated) == 0);
CHECK(ecount == 4);

ecount = 0;
CHECK(secp256k1_schnorrsig_verify(none, &sig, msg, &pk[0]) == 0);
CHECK(ecount == 1);
Expand Down Expand Up @@ -713,15 +741,61 @@ void test_schnorrsig_sign_verify(secp256k1_scratch_space *scratch) {
}
#undef N_SIGS

void test_schnorrsig_s2c_commit_verify(void) {
secp256k1_s2c_commit_context s2c_ctx;
unsigned char data32[32];
secp256k1_schnorrsig sig;
int nonce_is_negated;
unsigned char msg[32];
unsigned char sk[32];
secp256k1_pubkey pk;
secp256k1_pubkey s2c_original_nonce;

secp256k1_rand256(data32);
secp256k1_rand256(msg);
secp256k1_rand256(sk);
CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1);

/* Create and verify correct commitment */
CHECK(secp256k1_s2c_commit_context_create(ctx, &s2c_ctx, data32) == 1);
CHECK(secp256k1_schnorrsig_sign(ctx, &sig, &nonce_is_negated, msg, sk, NULL, &s2c_ctx) == 1);
CHECK(secp256k1_schnorrsig_verify(ctx, &sig, msg, &pk));

CHECK(secp256k1_s2c_commit_get_original_nonce(ctx, &s2c_original_nonce, &s2c_ctx) == 1);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(ctx, &sig, data32, &s2c_original_nonce, nonce_is_negated) == 1);
/* verify_s2c_commit fails if nonce_is_negated is wrong */
CHECK(secp256k1_schnorrsig_verify_s2c_commit(ctx, &sig, data32, &s2c_original_nonce, !nonce_is_negated) == 0);

{
/* verify_s2c_commit fails if given data does not match committed data */
unsigned char data32_tmp[32];
memcpy(data32_tmp, data32, sizeof(data32_tmp));
data32_tmp[31] ^= 1;
CHECK(secp256k1_schnorrsig_verify_s2c_commit(ctx, &sig, data32_tmp, &s2c_original_nonce, nonce_is_negated) == 0);
}
{
/* verify_s2c_commit fails if signature does not commit to data */
secp256k1_schnorrsig sig_tmp;
sig_tmp = sig;
secp256k1_rand256(&sig_tmp.data[0]);
CHECK(secp256k1_schnorrsig_verify_s2c_commit(ctx, &sig_tmp, data32, &s2c_original_nonce, nonce_is_negated) == 0);
}
}

void run_schnorrsig_tests(void) {
int i;
secp256k1_scratch_space *scratch = secp256k1_scratch_space_create(ctx, 1024 * 1024);

test_schnorrsig_serialize();
test_schnorrsig_api(scratch);
test_schnorrsig_bip_vectors(scratch);
test_schnorrsig_sign();
test_schnorrsig_sign_verify(scratch);

for (i = 0; i < count; i++) {
/* Run multiple times to increase probability that the nonce is negated in
* a test. */
test_schnorrsig_s2c_commit_verify();
}
secp256k1_scratch_space_destroy(scratch);
}

Expand Down

0 comments on commit 8fa102c

Please sign in to comment.