diff --git a/src/secp256k1/src/gen_context.c b/src/secp256k1/src/gen_context.c index 48b4f98bc..05e7dee17 100644 --- a/src/secp256k1/src/gen_context.c +++ b/src/secp256k1/src/gen_context.c @@ -1,88 +1,88 @@ /*********************************************************************** * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ /* Autotools creates libsecp256k1-config.h, of which ECMULT_GEN_PREC_BITS is needed. ifndef guard so downstream users can define their own if they do not use autotools. */ #if !defined(ECMULT_GEN_PREC_BITS) #include "libsecp256k1-config.h" #endif #define USE_BASIC_CONFIG 1 #include "basic-config.h" #include "include/secp256k1.h" #include "assumptions.h" #include "util.h" #include "field_impl.h" #include "scalar_impl.h" #include "group_impl.h" #include "ecmult_gen_impl.h" static void default_error_callback_fn(const char* str, void* data) { (void)data; fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); abort(); } static const secp256k1_callback default_error_callback = { default_error_callback_fn, NULL }; int main(int argc, char **argv) { secp256k1_ecmult_gen_context ctx; void *prealloc, *base; int inner; int outer; FILE* fp; (void)argc; (void)argv; fp = fopen("src/ecmult_static_context.h","w"); if (fp == NULL) { fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); return -1; } - fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); - fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); + fprintf(fp, "#ifndef SECP256K1_ECMULT_STATIC_CONTEXT_H\n"); + fprintf(fp, "#define SECP256K1_ECMULT_STATIC_CONTEXT_H\n"); fprintf(fp, "#include \"src/group.h\"\n"); fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); fprintf(fp, "#if ECMULT_GEN_PREC_N != %d || ECMULT_GEN_PREC_G != %d\n", ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G); fprintf(fp, " #error configuration mismatch, invalid ECMULT_GEN_PREC_N, ECMULT_GEN_PREC_G. Try deleting ecmult_static_context.h before the build.\n"); fprintf(fp, "#endif\n"); fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[ECMULT_GEN_PREC_N][ECMULT_GEN_PREC_G] = {\n"); base = checked_malloc(&default_error_callback, SECP256K1_ECMULT_GEN_CONTEXT_PREALLOCATED_SIZE); prealloc = base; secp256k1_ecmult_gen_context_init(&ctx); secp256k1_ecmult_gen_context_build(&ctx, &prealloc); for(outer = 0; outer != ECMULT_GEN_PREC_N; outer++) { fprintf(fp,"{\n"); for(inner = 0; inner != ECMULT_GEN_PREC_G; inner++) { fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); if (inner != ECMULT_GEN_PREC_G - 1) { fprintf(fp,",\n"); } else { fprintf(fp,"\n"); } } if (outer != ECMULT_GEN_PREC_N - 1) { fprintf(fp,"},\n"); } else { fprintf(fp,"}\n"); } } fprintf(fp,"};\n"); secp256k1_ecmult_gen_context_clear(&ctx); free(base); fprintf(fp, "#undef SC\n"); fprintf(fp, "#endif\n"); fclose(fp); return 0; } diff --git a/src/secp256k1/src/modules/extrakeys/main_impl.h b/src/secp256k1/src/modules/extrakeys/main_impl.h index 81be7e7d5..7390b2271 100644 --- a/src/secp256k1/src/modules/extrakeys/main_impl.h +++ b/src/secp256k1/src/modules/extrakeys/main_impl.h @@ -1,261 +1,261 @@ /*********************************************************************** * Copyright (c) 2020 Jonas Nick * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_EXTRAKEYS_MAIN_ -#define _SECP256K1_MODULE_EXTRAKEYS_MAIN_ +#ifndef SECP256K1_MODULE_EXTRAKEYS_MAIN_H +#define SECP256K1_MODULE_EXTRAKEYS_MAIN_H #include "include/secp256k1.h" #include "include/secp256k1_extrakeys.h" static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) { return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey); } static SECP256K1_INLINE void secp256k1_xonly_pubkey_save(secp256k1_xonly_pubkey *pubkey, secp256k1_ge *ge) { secp256k1_pubkey_save((secp256k1_pubkey *) pubkey, ge); } int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, const unsigned char *input32) { secp256k1_ge pk; secp256k1_fe x; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(input32 != NULL); if (!secp256k1_fe_set_b32(&x, input32)) { return 0; } if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) { return 0; } if (!secp256k1_ge_is_in_correct_subgroup(&pk)) { return 0; } secp256k1_xonly_pubkey_save(pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output32, const secp256k1_xonly_pubkey *pubkey) { secp256k1_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output32 != NULL); memset(output32, 0, 32); ARG_CHECK(pubkey != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } secp256k1_fe_get_b32(output32, &pk.x); return 1; } /** Keeps a group element as is if it has an even Y and otherwise negates it. * y_parity is set to 0 in the former case and to 1 in the latter case. * Requires that the coordinates of r are normalized. */ static int secp256k1_extrakeys_ge_even_y(secp256k1_ge *r) { int y_parity = 0; VERIFY_CHECK(!secp256k1_ge_is_infinity(r)); if (secp256k1_fe_is_odd(&r->y)) { secp256k1_fe_negate(&r->y, &r->y, 1); y_parity = 1; } return y_parity; } int secp256k1_xonly_pubkey_from_pubkey(const secp256k1_context* ctx, secp256k1_xonly_pubkey *xonly_pubkey, int *pk_parity, const secp256k1_pubkey *pubkey) { secp256k1_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); ARG_CHECK(xonly_pubkey != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_pubkey_load(ctx, &pk, pubkey)) { return 0; } tmp = secp256k1_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } secp256k1_xonly_pubkey_save(xonly_pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *output_pubkey, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { secp256k1_ge pk; VERIFY_CHECK(ctx != NULL); ARG_CHECK(output_pubkey != NULL); memset(output_pubkey, 0, sizeof(*output_pubkey)); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(tweak32 != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { return 0; } secp256k1_pubkey_save(output_pubkey, &pk); return 1; } int secp256k1_xonly_pubkey_tweak_add_check(const secp256k1_context* ctx, const unsigned char *tweaked_pubkey32, int tweaked_pk_parity, const secp256k1_xonly_pubkey *internal_pubkey, const unsigned char *tweak32) { secp256k1_ge pk; unsigned char pk_expected32[32]; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(internal_pubkey != NULL); ARG_CHECK(tweaked_pubkey32 != NULL); ARG_CHECK(tweak32 != NULL); if (!secp256k1_xonly_pubkey_load(ctx, &pk, internal_pubkey) || !secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32)) { return 0; } secp256k1_fe_normalize_var(&pk.x); secp256k1_fe_normalize_var(&pk.y); secp256k1_fe_get_b32(pk_expected32, &pk.x); return secp256k1_memcmp_var(&pk_expected32, tweaked_pubkey32, 32) == 0 && secp256k1_fe_is_odd(&pk.y) == tweaked_pk_parity; } static void secp256k1_keypair_save(secp256k1_keypair *keypair, const secp256k1_scalar *sk, secp256k1_ge *pk) { secp256k1_scalar_get_b32(&keypair->data[0], sk); secp256k1_pubkey_save((secp256k1_pubkey *)&keypair->data[32], pk); } static int secp256k1_keypair_seckey_load(const secp256k1_context* ctx, secp256k1_scalar *sk, const secp256k1_keypair *keypair) { int ret; ret = secp256k1_scalar_set_b32_seckey(sk, &keypair->data[0]); /* We can declassify ret here because sk is only zero if a keypair function * failed (which zeroes the keypair) and its return value is ignored. */ secp256k1_declassify(ctx, &ret, sizeof(ret)); ARG_CHECK(ret); return ret; } /* Load a keypair into pk and sk (if non-NULL). This function declassifies pk * and ARG_CHECKs that the keypair is not invalid. It always initializes sk and * pk with dummy values. */ static int secp256k1_keypair_load(const secp256k1_context* ctx, secp256k1_scalar *sk, secp256k1_ge *pk, const secp256k1_keypair *keypair) { int ret; const secp256k1_pubkey *pubkey = (const secp256k1_pubkey *)&keypair->data[32]; /* Need to declassify the pubkey because pubkey_load ARG_CHECKs if it's * invalid. */ secp256k1_declassify(ctx, pubkey, sizeof(*pubkey)); ret = secp256k1_pubkey_load(ctx, pk, pubkey); if (sk != NULL) { ret = ret && secp256k1_keypair_seckey_load(ctx, sk, keypair); } if (!ret) { *pk = secp256k1_ge_const_g; if (sk != NULL) { *sk = secp256k1_scalar_one; } } return ret; } int secp256k1_keypair_create(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *seckey32) { secp256k1_scalar sk; secp256k1_ge pk; int ret = 0; VERIFY_CHECK(ctx != NULL); ARG_CHECK(keypair != NULL); memset(keypair, 0, sizeof(*keypair)); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(seckey32 != NULL); ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &sk, &pk, seckey32); secp256k1_keypair_save(keypair, &sk, &pk); secp256k1_memczero(keypair, sizeof(*keypair), !ret); secp256k1_scalar_clear(&sk); return ret; } int secp256k1_keypair_sec(const secp256k1_context* ctx, unsigned char *seckey, const secp256k1_keypair *keypair) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(seckey != NULL); memset(seckey, 0, 32); ARG_CHECK(keypair != NULL); memcpy(seckey, &keypair->data[0], 32); return 1; } int secp256k1_keypair_pub(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_keypair *keypair) { VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(keypair != NULL); memcpy(pubkey->data, &keypair->data[32], sizeof(*pubkey)); return 1; } int secp256k1_keypair_xonly_pub(const secp256k1_context* ctx, secp256k1_xonly_pubkey *pubkey, int *pk_parity, const secp256k1_keypair *keypair) { secp256k1_ge pk; int tmp; VERIFY_CHECK(ctx != NULL); ARG_CHECK(pubkey != NULL); memset(pubkey, 0, sizeof(*pubkey)); ARG_CHECK(keypair != NULL); if (!secp256k1_keypair_load(ctx, NULL, &pk, keypair)) { return 0; } tmp = secp256k1_extrakeys_ge_even_y(&pk); if (pk_parity != NULL) { *pk_parity = tmp; } secp256k1_xonly_pubkey_save(pubkey, &pk); return 1; } int secp256k1_keypair_xonly_tweak_add(const secp256k1_context* ctx, secp256k1_keypair *keypair, const unsigned char *tweak32) { secp256k1_ge pk; secp256k1_scalar sk; int y_parity; int ret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(keypair != NULL); ARG_CHECK(tweak32 != NULL); ret = secp256k1_keypair_load(ctx, &sk, &pk, keypair); memset(keypair, 0, sizeof(*keypair)); y_parity = secp256k1_extrakeys_ge_even_y(&pk); if (y_parity == 1) { secp256k1_scalar_negate(&sk, &sk); } ret &= secp256k1_ec_seckey_tweak_add_helper(&sk, tweak32); ret &= secp256k1_ec_pubkey_tweak_add_helper(&ctx->ecmult_ctx, &pk, tweak32); secp256k1_declassify(ctx, &ret, sizeof(ret)); if (ret) { secp256k1_keypair_save(keypair, &sk, &pk); } secp256k1_scalar_clear(&sk); return ret; } #endif diff --git a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h index d78c315b7..0aca4fb72 100644 --- a/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h +++ b/src/secp256k1/src/modules/extrakeys/tests_exhaustive_impl.h @@ -1,68 +1,68 @@ /*********************************************************************** * Copyright (c) 2020 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_ -#define _SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_ +#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H +#define SECP256K1_MODULE_EXTRAKEYS_TESTS_EXHAUSTIVE_H #include "src/modules/extrakeys/main_impl.h" #include "include/secp256k1_extrakeys.h" static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp256k1_ge* group) { secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_pubkey pubkey[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parities[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; int i; for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { secp256k1_fe fe; secp256k1_scalar scalar_i; unsigned char buf[33]; int parity; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_scalar_get_b32(buf, &scalar_i); /* Construct pubkey and keypair. */ CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey[i - 1], buf)); /* Construct serialized xonly_pubkey from keypair. */ CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parities[i - 1], &keypair[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); /* Parse the xonly_pubkey back and verify it matches the previously serialized value. */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey[i - 1], xonly_pubkey_bytes[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Construct the xonly_pubkey from the pubkey, and verify it matches the same. */ CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pubkey[i - 1], &parity, &pubkey[i - 1])); CHECK(parity == parities[i - 1]); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf, &xonly_pubkey[i - 1])); CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0); /* Compare the xonly_pubkey bytes against the precomputed group. */ secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]); CHECK(secp256k1_fe_equal_var(&fe, &group[i].x)); /* Check the parity against the precomputed group. */ fe = group[i].y; secp256k1_fe_normalize_var(&fe); CHECK(secp256k1_fe_is_odd(&fe) == parities[i - 1]); /* Verify that the higher half is identical to the lower half mirrored. */ if (i > EXHAUSTIVE_TEST_ORDER / 2) { CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - i - 1], 32) == 0); CHECK(parities[i - 1] == 1 - parities[EXHAUSTIVE_TEST_ORDER - i - 1]); } } /* TODO: keypair/xonly_pubkey tweak tests */ } #endif diff --git a/src/secp256k1/src/modules/extrakeys/tests_impl.h b/src/secp256k1/src/modules/extrakeys/tests_impl.h index 880543195..9473a7dd4 100644 --- a/src/secp256k1/src/modules/extrakeys/tests_impl.h +++ b/src/secp256k1/src/modules/extrakeys/tests_impl.h @@ -1,549 +1,549 @@ /*********************************************************************** * Copyright (c) 2020 Jonas Nick * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_EXTRAKEYS_TESTS_ -#define _SECP256K1_MODULE_EXTRAKEYS_TESTS_ +#ifndef SECP256K1_MODULE_EXTRAKEYS_TESTS_H +#define SECP256K1_MODULE_EXTRAKEYS_TESTS_H #include "secp256k1_extrakeys.h" static secp256k1_context* api_test_context(int flags, int *ecount) { secp256k1_context *ctx0 = secp256k1_context_create(flags); secp256k1_context_set_error_callback(ctx0, counting_illegal_callback_fn, ecount); secp256k1_context_set_illegal_callback(ctx0, counting_illegal_callback_fn, ecount); return ctx0; } void test_xonly_pubkey(void) { secp256k1_pubkey pk; secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; secp256k1_ge pk1; secp256k1_ge pk2; secp256k1_fe y; unsigned char sk[32]; unsigned char xy_sk[32]; unsigned char buf32[32]; unsigned char ones32[32]; unsigned char zeros64[64] = { 0 }; int pk_parity; int i; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); secp256k1_testrand256(sk); memset(ones32, 0xFF, 32); secp256k1_testrand256(xy_sk); CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); /* Test xonly_pubkey_from_pubkey */ ecount = 0; CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(sign, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, NULL, &pk_parity, &pk) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, NULL) == 0); CHECK(ecount == 2); memset(&pk, 0, sizeof(pk)); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 0); CHECK(ecount == 3); /* Choose a secret key such that the resulting pubkey and xonly_pubkey match. */ memset(sk, 0, sizeof(sk)); sk[0] = 1; CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_memcmp_var(&pk, &xonly_pk, sizeof(pk)) == 0); CHECK(pk_parity == 0); /* Choose a secret key such that pubkey and xonly_pubkey are each others * negation. */ sk[0] = 2; CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &pk, sizeof(xonly_pk)) != 0); CHECK(pk_parity == 1); secp256k1_pubkey_load(ctx, &pk1, &pk); secp256k1_pubkey_load(ctx, &pk2, (secp256k1_pubkey *) &xonly_pk); CHECK(secp256k1_fe_equal(&pk1.x, &pk2.x) == 1); secp256k1_fe_negate(&y, &pk2.y, 1); CHECK(secp256k1_fe_equal(&pk1.y, &y) == 1); /* Test xonly_pubkey_serialize and xonly_pubkey_parse */ ecount = 0; CHECK(secp256k1_xonly_pubkey_serialize(none, NULL, &xonly_pk) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, NULL) == 0); CHECK(secp256k1_memcmp_var(buf32, zeros64, 32) == 0); CHECK(ecount == 2); { /* A pubkey filled with 0s will fail to serialize due to pubkey_load * special casing. */ secp256k1_xonly_pubkey pk_tmp; memset(&pk_tmp, 0, sizeof(pk_tmp)); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &pk_tmp) == 0); } /* pubkey_load called illegal callback */ CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_serialize(none, buf32, &xonly_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_parse(none, NULL, buf32) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, NULL) == 0); CHECK(ecount == 2); /* Serialization and parse roundtrip */ CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, NULL, &pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk_tmp, buf32) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(xonly_pk)) == 0); /* Test parsing invalid field elements */ memset(&xonly_pk, 1, sizeof(xonly_pk)); /* Overflowing field element */ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, ones32) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); memset(&xonly_pk, 1, sizeof(xonly_pk)); /* There's no point with x-coordinate 0 on secp256k1 */ CHECK(secp256k1_xonly_pubkey_parse(none, &xonly_pk, zeros64) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); /* If a random 32-byte string can not be parsed with ec_pubkey_parse * (because interpreted as X coordinate it does not correspond to a point on * the curve) then xonly_pubkey_parse should fail as well. */ for (i = 0; i < count; i++) { unsigned char rand33[33]; secp256k1_testrand256(&rand33[1]); rand33[0] = SECP256K1_TAG_PUBKEY_EVEN; if (!secp256k1_ec_pubkey_parse(ctx, &pk, rand33, 33)) { memset(&xonly_pk, 1, sizeof(xonly_pk)); CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 0); CHECK(secp256k1_memcmp_var(&xonly_pk, zeros64, sizeof(xonly_pk)) == 0); } else { CHECK(secp256k1_xonly_pubkey_parse(ctx, &xonly_pk, &rand33[1]) == 1); } } CHECK(ecount == 2); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_xonly_pubkey_tweak(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; secp256k1_pubkey internal_pk; secp256k1_xonly_pubkey internal_xonly_pk; secp256k1_pubkey output_pk; int pk_parity; unsigned char tweak[32]; int i; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); memset(overflows, 0xff, sizeof(overflows)); secp256k1_testrand256(tweak); secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(none, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(sign, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, NULL, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, NULL, tweak) == 0); CHECK(ecount == 4); /* NULL internal_xonly_pk zeroes the output_pk */ CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, NULL) == 0); CHECK(ecount == 5); /* NULL tweak zeroes the output_pk */ CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* Invalid tweak zeroes the output_pk */ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); /* A zero tweak is fine */ CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, zeros64) == 1); /* Fails if the resulting key was infinity */ for (i = 0; i < count; i++) { secp256k1_scalar scalar_tweak; /* Because sk may be negated before adding, we need to try with tweak = * sk as well as tweak = -sk. */ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak); CHECK((secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, sk) == 0) || (secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0)); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); } /* Invalid pk with a valid tweak */ memset(&internal_xonly_pk, 0, sizeof(internal_xonly_pk)); secp256k1_testrand256(tweak); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_xonly_pubkey_tweak_check(void) { unsigned char zeros64[64] = { 0 }; unsigned char overflows[32]; unsigned char sk[32]; secp256k1_pubkey internal_pk; secp256k1_xonly_pubkey internal_xonly_pk; secp256k1_pubkey output_pk; secp256k1_xonly_pubkey output_xonly_pk; unsigned char output_pk32[32]; unsigned char buf32[32]; int pk_parity; unsigned char tweak[32]; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); memset(overflows, 0xff, sizeof(overflows)); secp256k1_testrand256(tweak); secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &internal_pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &internal_xonly_pk, &pk_parity, &internal_pk) == 1); ecount = 0; CHECK(secp256k1_xonly_pubkey_tweak_add(verify, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(verify, &output_xonly_pk, &pk_parity, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &output_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(none, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(sign, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, NULL, pk_parity, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); /* invalid pk_parity value */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, 2, &internal_xonly_pk, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, NULL, tweak) == 0); CHECK(ecount == 4); CHECK(secp256k1_xonly_pubkey_tweak_add_check(verify, buf32, pk_parity, &internal_xonly_pk, NULL) == 0); CHECK(ecount == 5); memset(tweak, 1, sizeof(tweak)); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &internal_xonly_pk, NULL, &internal_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, tweak) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &output_xonly_pk, &pk_parity, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk32, &output_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, tweak) == 1); /* Wrong pk_parity */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, !pk_parity, &internal_xonly_pk, tweak) == 0); /* Wrong public key */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, buf32, &internal_xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, buf32, pk_parity, &internal_xonly_pk, tweak) == 0); /* Overflowing tweak not allowed */ CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk32, pk_parity, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk, &internal_xonly_pk, overflows) == 0); CHECK(secp256k1_memcmp_var(&output_pk, zeros64, sizeof(output_pk)) == 0); CHECK(ecount == 5); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } /* Starts with an initial pubkey and recursively creates N_PUBKEYS - 1 * additional pubkeys by calling tweak_add. Then verifies every tweak starting * from the last pubkey. */ #define N_PUBKEYS 32 void test_xonly_pubkey_tweak_recursive(void) { unsigned char sk[32]; secp256k1_pubkey pk[N_PUBKEYS]; unsigned char pk_serialized[32]; unsigned char tweak[N_PUBKEYS - 1][32]; int i; secp256k1_testrand256(sk); CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk) == 1); /* Add tweaks */ for (i = 0; i < N_PUBKEYS - 1; i++) { secp256k1_xonly_pubkey xonly_pk; memset(tweak[i], i + 1, sizeof(tweak[i])); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i]) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &pk[i + 1], &xonly_pk, tweak[i]) == 1); } /* Verify tweaks */ for (i = N_PUBKEYS - 1; i > 0; i--) { secp256k1_xonly_pubkey xonly_pk; int pk_parity; CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, &pk_parity, &pk[i]) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk_serialized, &xonly_pk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(ctx, &xonly_pk, NULL, &pk[i - 1]) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk_serialized, pk_parity, &xonly_pk, tweak[i - 1]) == 1); } } #undef N_PUBKEYS void test_keypair(void) { unsigned char sk[32]; unsigned char sk_tmp[32]; unsigned char zeros96[96] = { 0 }; unsigned char overflows[32]; secp256k1_keypair keypair; secp256k1_pubkey pk, pk_tmp; secp256k1_xonly_pubkey xonly_pk, xonly_pk_tmp; int pk_parity, pk_parity_tmp; int ecount; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); CHECK(sizeof(zeros96) == sizeof(keypair)); memset(overflows, 0xFF, sizeof(overflows)); /* Test keypair_create */ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(none, &keypair, sk) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_create(verify, &keypair, sk) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 2); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_create(sign, NULL, sk) == 0); CHECK(ecount == 3); CHECK(secp256k1_keypair_create(sign, &keypair, NULL) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(ecount == 4); /* Invalid secret key */ CHECK(secp256k1_keypair_create(sign, &keypair, zeros96) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); CHECK(secp256k1_keypair_create(sign, &keypair, overflows) == 0); CHECK(secp256k1_memcmp_var(zeros96, &keypair, sizeof(keypair)) == 0); /* Test keypair_pub */ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); CHECK(secp256k1_keypair_pub(none, NULL, &keypair) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_pub(none, &pk, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* Using an invalid keypair is fine for keypair_pub */ memset(&keypair, 0, sizeof(keypair)); CHECK(secp256k1_keypair_pub(none, &pk, &keypair) == 1); CHECK(secp256k1_memcmp_var(zeros96, &pk, sizeof(pk)) == 0); /* keypair holds the same pubkey as pubkey_create */ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_pub(none, &pk_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(&pk, &pk_tmp, sizeof(pk)) == 0); /** Test keypair_xonly_pub **/ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, NULL, &pk_parity, &keypair) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); /* Using an invalid keypair will set the xonly_pk to 0 (first reset * xonly_pk). */ CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 1); memset(&keypair, 0, sizeof(keypair)); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk, &pk_parity, &keypair) == 0); CHECK(secp256k1_memcmp_var(zeros96, &xonly_pk, sizeof(xonly_pk)) == 0); CHECK(ecount == 3); /** keypair holds the same xonly pubkey as pubkey_create **/ CHECK(secp256k1_ec_pubkey_create(sign, &pk, sk) == 1); CHECK(secp256k1_xonly_pubkey_from_pubkey(none, &xonly_pk, &pk_parity, &pk) == 1); CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(none, &xonly_pk_tmp, &pk_parity_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(&xonly_pk, &xonly_pk_tmp, sizeof(pk)) == 0); CHECK(pk_parity == pk_parity_tmp); /* Test keypair_seckey */ ecount = 0; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); CHECK(secp256k1_keypair_sec(none, NULL, &keypair) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_sec(none, sk_tmp, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); /* keypair returns the same seckey it got */ CHECK(secp256k1_keypair_create(sign, &keypair, sk) == 1); CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(sk, sk_tmp, sizeof(sk_tmp)) == 0); /* Using an invalid keypair is fine for keypair_seckey */ memset(&keypair, 0, sizeof(keypair)); CHECK(secp256k1_keypair_sec(none, sk_tmp, &keypair) == 1); CHECK(secp256k1_memcmp_var(zeros96, sk_tmp, sizeof(sk_tmp)) == 0); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void test_keypair_add(void) { unsigned char sk[32]; secp256k1_keypair keypair; unsigned char overflows[32]; unsigned char zeros96[96] = { 0 }; unsigned char tweak[32]; int i; int ecount = 0; secp256k1_context *none = api_test_context(SECP256K1_CONTEXT_NONE, &ecount); secp256k1_context *sign = api_test_context(SECP256K1_CONTEXT_SIGN, &ecount); secp256k1_context *verify = api_test_context(SECP256K1_CONTEXT_VERIFY, &ecount); CHECK(sizeof(zeros96) == sizeof(keypair)); secp256k1_testrand256(sk); secp256k1_testrand256(tweak); memset(overflows, 0xFF, 32); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(none, &keypair, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_keypair_xonly_tweak_add(sign, &keypair, tweak) == 0); CHECK(ecount == 2); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(verify, NULL, tweak) == 0); CHECK(ecount == 3); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, NULL) == 0); CHECK(ecount == 4); /* This does not set the keypair to zeroes */ CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) != 0); /* Invalid tweak zeroes the keypair */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, overflows) == 0); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* A zero tweak is fine */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, zeros96) == 1); /* Fails if the resulting keypair was (sk=0, pk=infinity) */ for (i = 0; i < count; i++) { secp256k1_scalar scalar_tweak; secp256k1_keypair keypair_tmp; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memcpy(&keypair_tmp, &keypair, sizeof(keypair)); /* Because sk may be negated before adding, we need to try with tweak = * sk as well as tweak = -sk. */ secp256k1_scalar_set_b32(&scalar_tweak, sk, NULL); secp256k1_scalar_negate(&scalar_tweak, &scalar_tweak); secp256k1_scalar_get_b32(tweak, &scalar_tweak); CHECK((secp256k1_keypair_xonly_tweak_add(ctx, &keypair, sk) == 0) || (secp256k1_keypair_xonly_tweak_add(ctx, &keypair_tmp, tweak) == 0)); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0 || secp256k1_memcmp_var(&keypair_tmp, zeros96, sizeof(keypair_tmp)) == 0); } /* Invalid keypair with a valid tweak */ memset(&keypair, 0, sizeof(keypair)); secp256k1_testrand256(tweak); ecount = 0; CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 1); CHECK(secp256k1_memcmp_var(&keypair, zeros96, sizeof(keypair)) == 0); /* Only seckey part of keypair invalid */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memset(&keypair, 0, 32); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 2); /* Only pubkey part of keypair invalid */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); memset(&keypair.data[32], 0, 64); CHECK(secp256k1_keypair_xonly_tweak_add(verify, &keypair, tweak) == 0); CHECK(ecount == 3); /* Check that the keypair_tweak_add implementation is correct */ CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); for (i = 0; i < count; i++) { secp256k1_xonly_pubkey internal_pk; secp256k1_xonly_pubkey output_pk; secp256k1_pubkey output_pk_xy; secp256k1_pubkey output_pk_expected; unsigned char pk32[32]; unsigned char sk32[32]; int pk_parity; secp256k1_testrand256(tweak); CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); /* Check that it passes xonly_pubkey_tweak_add_check */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, pk32, &output_pk) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, pk32, pk_parity, &internal_pk, tweak) == 1); /* Check that the resulting pubkey matches xonly_pubkey_tweak_add */ CHECK(secp256k1_keypair_pub(ctx, &output_pk_xy, &keypair) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add(ctx, &output_pk_expected, &internal_pk, tweak) == 1); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); /* Check that the secret key in the keypair is tweaked correctly */ CHECK(secp256k1_keypair_sec(none, sk32, &keypair) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &output_pk_expected, sk32) == 1); CHECK(secp256k1_memcmp_var(&output_pk_xy, &output_pk_expected, sizeof(output_pk_xy)) == 0); } secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(verify); } void run_extrakeys_tests(void) { /* xonly key test cases */ test_xonly_pubkey(); test_xonly_pubkey_tweak(); test_xonly_pubkey_tweak_check(); test_xonly_pubkey_tweak_recursive(); /* keypair tests */ test_keypair(); test_keypair_add(); } #endif diff --git a/src/secp256k1/src/modules/multiset/main_impl.h b/src/secp256k1/src/modules/multiset/main_impl.h index 13986aeef..570c64e4b 100644 --- a/src/secp256k1/src/modules/multiset/main_impl.h +++ b/src/secp256k1/src/modules/multiset/main_impl.h @@ -1,210 +1,210 @@ /*********************************************************************** * Copyright (c) 2017 Tomas van der Wansem * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_MULTISET_MAIN_ -#define _SECP256K1_MODULE_MULTISET_MAIN_ +#ifndef SECP256K1_MODULE_MULTISET_MAIN_H +#define SECP256K1_MODULE_MULTISET_MAIN_H #include "include/secp256k1_multiset.h" #include "hash.h" #include "field.h" #include "group.h" /** Converts a group element (Jacobian) to a multiset. * Requires the field elements to be normalized * Infinite uses special value, z = 0 */ static void multiset_from_gej_var(secp256k1_multiset *target, const secp256k1_gej *input) { if (input->infinity) { memset(&target->d, 0, sizeof(target->d)); } else { secp256k1_fe_get_b32(target->d, &input->x); secp256k1_fe_get_b32(target->d+32, &input->y); secp256k1_fe_get_b32(target->d+64, &input->z); } } /** Converts a multiset to group element (Jacobian) * Infinite uses special value, z = 0 */ static void gej_from_multiset_var(secp256k1_gej *target, const secp256k1_multiset *input) { secp256k1_fe_set_b32(&target->x, input->d); secp256k1_fe_set_b32(&target->y, input->d+32); secp256k1_fe_set_b32(&target->z, input->d+64); target->infinity = secp256k1_fe_is_zero(&target->z) ? 1 : 0; } /** Converts a data element to a group element (affine) * * We use trial-and-rehash which is fast but non-constant time. * Though constant time algo's exist we are not concerned with timing attacks * as we make no attempt to hide the underlying data * * Pass inverse=0 to generate the group element, or inverse=1 to generate its inverse */ static void ge_from_data_var(secp256k1_ge *target, const unsigned char *input, size_t inputLen, int inverse) { secp256k1_sha256 hasher; unsigned char buffer[8+32]; unsigned char trial[32]; uint64_t prefix; /* Hash to buffer, leaving space for 8-byte prefix */ secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, input, inputLen); secp256k1_sha256_finalize(&hasher, buffer+8); /* Loop through trials, with 50% success per loop * We can assume it ends within 2^64. */ for(prefix=0; 1; prefix++) { secp256k1_fe x; /* Set prefix in little-endian */ buffer[0] = prefix & 0xFF; buffer[1] = (prefix>>8) & 0xFF; buffer[2] = (prefix>>16) & 0xFF; buffer[3] = (prefix>>24) & 0xFF; buffer[4] = (prefix>>32) & 0xFF; buffer[5] = (prefix>>40) & 0xFF; buffer[6] = (prefix>>48) & 0xFF; buffer[7] = (prefix>>56) & 0xFF; /* Hash to trial */ secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, buffer, sizeof(buffer)); secp256k1_sha256_finalize(&hasher, trial); if (!secp256k1_fe_set_b32(&x, trial)) { continue; } /* We let y is even be the element and odd be its inverse */ if (!secp256k1_ge_set_xo_var(target, &x, inverse)) { continue; } VERIFY_CHECK(secp256k1_ge_is_valid_var(target)); VERIFY_CHECK(!secp256k1_ge_is_infinity(target)); break; } } /** Adds or removes a data element */ static int multiset_add_remove(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen, int remove) { secp256k1_ge newelm; secp256k1_gej source, target; VERIFY_CHECK(ctx != NULL); ARG_CHECK(multiset != NULL); ARG_CHECK(input != NULL); gej_from_multiset_var(&source, multiset); ge_from_data_var(&newelm, input, inputLen, remove); /* * The `target` group element needs to be initialized. * If the result of the addition is infinity, the field elements won't be * set and the `secp256k1_fe_normalize` calls below will branch on * uninitialized data. */ secp256k1_gej_set_infinity(&target); secp256k1_gej_add_ge_var(&target, &source, &newelm, NULL); secp256k1_fe_normalize(&target.x); secp256k1_fe_normalize(&target.y); secp256k1_fe_normalize(&target.z); multiset_from_gej_var(multiset, &target); return 1; } /** Adds a data element to the multiset */ int secp256k1_multiset_add(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen) { return multiset_add_remove(ctx, multiset, input, inputLen, 0); } /** Removes a data element from the multiset */ int secp256k1_multiset_remove(const secp256k1_context* ctx, secp256k1_multiset *multiset, const unsigned char *input, size_t inputLen) { return multiset_add_remove(ctx, multiset, input, inputLen, 1); } /** Adds input multiset to multiset */ int secp256k1_multiset_combine(const secp256k1_context* ctx, secp256k1_multiset *multiset, const secp256k1_multiset *input) { secp256k1_gej gej_multiset, gej_input, gej_result; VERIFY_CHECK(ctx != NULL); ARG_CHECK(multiset != NULL); ARG_CHECK(input != NULL); gej_from_multiset_var(&gej_multiset, multiset); gej_from_multiset_var(&gej_input, input); /* * The `gej_result` group element needs to be initialized. * If the result of the addition is infinity, the field elements won't be * set and the `secp256k1_fe_normalize` calls below will branch on * uninitialized data. */ secp256k1_gej_set_infinity(&gej_result); secp256k1_gej_add_var(&gej_result, &gej_multiset, &gej_input, NULL); secp256k1_fe_normalize(&gej_result.x); secp256k1_fe_normalize(&gej_result.y); secp256k1_fe_normalize(&gej_result.z); multiset_from_gej_var(multiset, &gej_result); return 1; } /** Hash the multiset into resultHash */ int secp256k1_multiset_finalize(const secp256k1_context* ctx, unsigned char *resultHash, const secp256k1_multiset *multiset) { secp256k1_sha256 hasher; unsigned char buffer[64]; secp256k1_gej gej; secp256k1_ge ge; VERIFY_CHECK(ctx != NULL); ARG_CHECK(resultHash != NULL); ARG_CHECK(multiset != NULL); gej_from_multiset_var(&gej, multiset); if (gej.infinity) { /* empty set is encoded as zeros */ memset(resultHash, 0x00, 32); return 1; } /* we must normalize to affine first */ secp256k1_ge_set_gej(&ge, &gej); secp256k1_fe_normalize(&ge.x); secp256k1_fe_normalize(&ge.y); secp256k1_fe_get_b32(buffer, &ge.x); secp256k1_fe_get_b32(buffer+32, &ge.y); secp256k1_sha256_initialize(&hasher); secp256k1_sha256_write(&hasher, buffer, sizeof(buffer)); secp256k1_sha256_finalize(&hasher, resultHash); return 1; } /** Inits the multiset with the constant for empty data, * represented by the Jacobian GE infinite */ int secp256k1_multiset_init(const secp256k1_context* ctx, secp256k1_multiset *multiset) { const secp256k1_gej inf = SECP256K1_GEJ_CONST_INFINITY; VERIFY_CHECK(ctx != NULL); multiset_from_gej_var(multiset, &inf); return 1; } -#endif /* _SECP256K1_MODULE_MULTISET_MAIN_ */ +#endif /* SECP256K1_MODULE_MULTISET_MAIN_H */ diff --git a/src/secp256k1/src/modules/multiset/tests_impl.h b/src/secp256k1/src/modules/multiset/tests_impl.h index 404b268c9..0e4814fb5 100644 --- a/src/secp256k1/src/modules/multiset/tests_impl.h +++ b/src/secp256k1/src/modules/multiset/tests_impl.h @@ -1,347 +1,347 @@ /*********************************************************************** * Copyright (c) 2017 Tomas van der Wansem * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_MULTISET_TESTS_ -#define _SECP256K1_MODULE_MULTISET_TESTS_ +#ifndef SECP256K1_MODULE_MULTISET_TESTS_H +#define SECP256K1_MODULE_MULTISET_TESTS_H #include "include/secp256k1.h" #include "include/secp256k1_multiset.h" #include "util.h" #include "testrand.h" #define DATALEN 64*3 #define DATACOUNT 100 #define CHECK_EQUAL(a,b) { \ unsigned char hash1[32]; \ unsigned char hash2[32]; \ secp256k1_multiset_finalize(ctx, hash1, (a)); \ secp256k1_multiset_finalize(ctx, hash2, (b)); \ CHECK(memcmp(hash1,hash2,sizeof(hash1))==0); \ } #define CHECK_NOTEQUAL(a,b) { \ unsigned char hash1[32]; \ unsigned char hash2[32]; \ secp256k1_multiset_finalize(ctx, hash1, (a)); \ secp256k1_multiset_finalize(ctx, hash2, (b)); \ CHECK(memcmp(hash1,hash2,sizeof(hash1))!=0); \ } static unsigned char elements[DATACOUNT][DATALEN]; /* Create random data */ static void initdata(void) { int n,m; for(n=0; n < DATACOUNT; n++) { for(m=0; m < DATALEN/4; m++) { uint32_t x = secp256k1_testrand32(); memcpy(&elements[n][m], &x, sizeof(x)); } } } void test_unordered(void) { /* Check if multisets are uneffected by order */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1,&r2); /* M(0,1)!=M() */ secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1)==M(1,0) */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M()==M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[2], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1,2)==M(2,0,1) */ CHECK_EQUAL(&r1,&r3); /* M(0,1,2)==M(1,0,2) */ secp256k1_multiset_combine(ctx, &r3, &empty); CHECK_EQUAL(&r1,&r3); /* M(1,0,2)+M()=M(0,1,2) */ secp256k1_multiset_combine(ctx, &r3, &r2); CHECK_NOTEQUAL(&r1,&r3); /* M(1,0,2)+M(0,1,2)!=M(0,1,2) */ } void test_combine(void) { /* Testing if combining is effectively the same as adding the elements */ secp256k1_multiset empty, r1,r2,r3; secp256k1_gej gej_pos, gej_neg; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1,&r2); /* M(0) != M(1) */ secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(1,0) == M(0,1) */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M() == M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add(ctx, &r1, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1,&r2); /* M(0,1,2) == M(2)+M(0,1) */ secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add(ctx, &r2, elements[2], DATALEN); secp256k1_multiset_add(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add(ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1,&r2); /* M(0,1,2) == M(2,0)+M(1) */ secp256k1_multiset_combine(ctx, &r2, &empty); CHECK_EQUAL(&r1,&r2); /* M(0,1,2)+M() == M(0,1,2) */ secp256k1_multiset_combine(ctx, &r2, &r1); CHECK_NOTEQUAL(&r1,&r2); /* M(0,1,2)+M(0,1,2) != M(0,1,2) */ /* Combine multisets so that the combination representation is infinity */ secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); CHECK_EQUAL(&r1, &r2); /* M() == M() */ secp256k1_multiset_add(ctx, &r1, elements[0], DATALEN); gej_from_multiset_var(&gej_pos, &r1); secp256k1_gej_neg(&gej_neg, &gej_pos); secp256k1_fe_normalize(&gej_neg.x); secp256k1_fe_normalize(&gej_neg.y); secp256k1_fe_normalize(&gej_neg.z); multiset_from_gej_var(&r2, &gej_neg); /* This is equivalent to a removal due to multisets being associative */ secp256k1_multiset_combine(ctx, &r1, &r2); CHECK_EQUAL(&empty, &r1); /* M() == M(X)+M(-X) == M(X)-M(X) */ } void test_remove(void) { /* Testing removal of elements */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); CHECK_EQUAL(&r1,&r2); /* M()==M() */ secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[8], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[11], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[10], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[10], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[8], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[11], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[9], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[15], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[15], DATALEN); secp256k1_multiset_remove(ctx, &r3, elements[9], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[3], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[8], DATALEN); CHECK_EQUAL(&r1,&r2); /* M(0,1,3,9,8)==M(1,9,11,10,9,3,8)-M(10,11) */ CHECK_EQUAL(&r1,&r3); /* M(0,1,3,9,8)==M(9,15,15,1,9,0,3,8)-M(15,15,9) */ CHECK_NOTEQUAL(&r1,&empty); /* M(0,1,3,9,8)!=M() */ secp256k1_multiset_remove(ctx, &r3, elements[8], DATALEN); CHECK_NOTEQUAL(&r1,&r3); /* M(0,1,3,9,8)-M(8)!=M(0,1,3,9,8) */ secp256k1_multiset_remove(ctx, &r2, elements[0], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[9], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[8], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[1], DATALEN); secp256k1_multiset_remove(ctx, &r2, elements[3], DATALEN); CHECK_EQUAL(&r2,&empty); /* M(0,1,3,9,8)-M(0,1,3,9,8)==M() */ } void test_duplicate(void) { /* Test if the multiset properly handles duplicates */ secp256k1_multiset empty, r1,r2,r3; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); CHECK_NOTEQUAL(&r1, &r2); /* M(0,0,1,1)!=M(0,1) */ secp256k1_multiset_add (ctx, &r2, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r2, elements[1], DATALEN); CHECK_EQUAL(&r1, &r2); /* M(0,0,1,1)!=M(0,0,1,1) */ secp256k1_multiset_add (ctx, &r1, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r1, elements[1], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[0], DATALEN); secp256k1_multiset_add (ctx, &r3, elements[1], DATALEN); secp256k1_multiset_combine(ctx, &r2, &r3); CHECK_EQUAL(&r1, &r2); /* M(0,0,0,1,1,1)!=M(0,0,1,1)+M(0,1) */ } void test_empty(void) { /* Test if empty set properties hold */ secp256k1_multiset empty, r1,r2; secp256k1_multiset_init(ctx, &empty); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); CHECK_EQUAL(&empty,&r1); /* M()==M() */ /* empty + empty = empty */ secp256k1_multiset_combine(ctx, &r1, &r2); CHECK_EQUAL(&empty, &r1); /* M()+M()==M() */ } void test_testvector(void) { /* Tests known values from the specification */ const unsigned char d1[113] = { 0x98,0x20,0x51,0xfd,0x1e,0x4b,0xa7,0x44,0xbb,0xbe,0x68,0x0e,0x1f,0xee,0x14,0x67,0x7b,0xa1,0xa3,0xc3,0x54,0x0b,0xf7,0xb1,0xcd,0xb6,0x06,0xe8,0x57,0x23,0x3e,0x0e, 0x00,0x00,0x00,0x00,0x03,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x96,0xb5,0x38,0xe8,0x53,0x51,0x9c,0x72,0x6a,0x2c,0x91,0xe6,0x1e,0xc1,0x16,0x00, 0xae,0x13,0x90,0x81,0x3a,0x62,0x7c,0x66,0xfb,0x8b,0xe7,0x94,0x7b,0xe6,0x3c,0x52,0xda,0x75,0x89,0x37,0x95,0x15,0xd4,0xe0,0xa6,0x04,0xf8,0x14,0x17,0x81,0xe6,0x22, 0x94,0x72,0x11,0x66,0xbf,0x62,0x1e,0x73,0xa8,0x2c,0xbf,0x23,0x42,0xc8,0x58,0xee,0xac }; const unsigned char d2[113] = { 0xd5,0xfd,0xcc,0x54,0x1e,0x25,0xde,0x1c,0x7a,0x5a,0xdd,0xed,0xf2,0x48,0x58,0xb8,0xbb,0x66,0x5c,0x9f,0x36,0xef,0x74,0x4e,0xe4,0x2c,0x31,0x60,0x22,0xc9,0x0f,0x9b, 0x00,0x00,0x00,0x00,0x05,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x72,0x11,0xa8,0x24,0xf5,0x5b,0x50,0x52,0x28,0xe4,0xc3,0xd5,0x19,0x4c,0x1f,0xcf, 0xaa,0x15,0xa4,0x56,0xab,0xdf,0x37,0xf9,0xb9,0xd9,0x7a,0x40,0x40,0xaf,0xc0,0x73,0xde,0xe6,0xc8,0x90,0x64,0x98,0x4f,0x03,0x38,0x52,0x37,0xd9,0x21,0x67,0xc1,0x3e, 0x23,0x64,0x46,0xb4,0x17,0xab,0x79,0xa0,0xfc,0xae,0x41,0x2a,0xe3,0x31,0x6b,0x77,0xac }; const unsigned char d3[113] = { 0x44,0xf6,0x72,0x22,0x60,0x90,0xd8,0x5d,0xb9,0xa9,0xf2,0xfb,0xfe,0x5f,0x0f,0x96,0x09,0xb3,0x87,0xaf,0x7b,0xe5,0xb7,0xfb,0xb7,0xa1,0x76,0x7c,0x83,0x1c,0x9e,0x99, 0x00,0x00,0x00,0x00,0x07,0x00,0xf2,0x05,0x2a,0x01,0x00,0x00,0x00,0x43,0x41,0x04,0x94,0xb9,0xd3,0xe7,0x6c,0x5b,0x16,0x29,0xec,0xf9,0x7f,0xff,0x95,0xd7,0xa4,0xbb, 0xda,0xc8,0x7c,0xc2,0x60,0x99,0xad,0xa2,0x80,0x66,0xc6,0xff,0x1e,0xb9,0x19,0x12,0x23,0xcd,0x89,0x71,0x94,0xa0,0x8d,0x0c,0x27,0x26,0xc5,0x74,0x7f,0x1d,0xb4,0x9e, 0x8c,0xf9,0x0e,0x75,0xdc,0x3e,0x35,0x50,0xae,0x9b,0x30,0x08,0x6f,0x3c,0xd5,0xaa,0xac }; /* Expected resulting multisets */ const unsigned char exp_empty[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; const unsigned char exp_m1[32] = { 0x5e,0x29,0x49,0x84,0xc0,0xb6,0xff,0x1c,0x89,0x7b,0xdb,0xb6,0xf7,0xcf,0x3e,0xf8,0x01,0xe2,0xf1,0x3b,0xc7,0x34,0x28,0xaa,0xcd,0xf8,0xcb,0x8d,0x3b,0xd2,0xf0,0xe5 }; const unsigned char exp_m2[32] = { 0x93,0x70,0x80,0xb6,0x6c,0x2b,0x37,0x2d,0x35,0x39,0x88,0xd6,0xc0,0x92,0x22,0x78,0x8f,0x88,0xa5,0x13,0x0a,0x13,0x32,0xeb,0xc1,0x49,0x5a,0xa3,0xa7,0xfa,0xb4,0xfb }; const unsigned char exp_m3[32] = { 0xdd,0xbf,0x2f,0x18,0xaf,0xe0,0xaf,0xa8,0x87,0x28,0x57,0x93,0xa4,0x82,0xa0,0x7f,0xc2,0x2a,0x46,0x28,0x48,0x36,0x78,0x73,0xd7,0x9d,0x72,0xa7,0x33,0x0a,0x96,0x15 }; const unsigned char exp_m1m2[32] = { 0x48,0x09,0x8f,0x4c,0xa9,0xbb,0x5d,0xac,0x27,0x3e,0x56,0x31,0x6d,0xb6,0x41,0x23,0x69,0xed,0x1f,0xa8,0xbe,0xb5,0x79,0x57,0x05,0x32,0xd1,0x63,0x47,0xfe,0xfc,0xcc }; const unsigned char exp_m1m2m3[32] = { 0x47,0xfb,0xdf,0xf4,0x76,0x7c,0x32,0xa4,0xea,0x74,0xca,0x43,0x86,0x59,0x0f,0x62,0x22,0xee,0x83,0x96,0xb8,0xb4,0xf0,0x0e,0xf5,0x6e,0x9b,0x49,0x43,0xf4,0x24,0x93 }; unsigned char m0[32],m1[32],m2[32],m3[32],m1m2[32],m1m2m3[32]; secp256k1_multiset r0,r1,r2,r3; secp256k1_multiset_init(ctx, &r0); secp256k1_multiset_init(ctx, &r1); secp256k1_multiset_init(ctx, &r2); secp256k1_multiset_init(ctx, &r3); secp256k1_multiset_add (ctx, &r1, d1, sizeof(d1)); secp256k1_multiset_add (ctx, &r2, d2, sizeof(d2)); secp256k1_multiset_add (ctx, &r3, d3, sizeof(d3)); secp256k1_multiset_finalize(ctx, m0, &r0); secp256k1_multiset_finalize(ctx, m1, &r1); secp256k1_multiset_finalize(ctx, m2, &r2); secp256k1_multiset_finalize(ctx, m3, &r3); secp256k1_multiset_combine(ctx, &r1, &r2); secp256k1_multiset_finalize(ctx, m1m2, &r1); secp256k1_multiset_combine(ctx, &r1, &r3); secp256k1_multiset_finalize(ctx, m1m2m3, &r1); CHECK(memcmp(m0,exp_empty,32)==0); CHECK(memcmp(m1,exp_m1,32)==0); CHECK(memcmp(m2,exp_m2,32)==0); CHECK(memcmp(m3,exp_m3,32)==0); CHECK(memcmp(m1m2,exp_m1m2,32)==0); CHECK(memcmp(m1m2m3,exp_m1m2m3,32)==0); } void run_multiset_tests(void) { initdata(); test_unordered(); test_combine(); test_remove(); test_empty(); test_duplicate(); test_testvector(); } -#endif /* _SECP256K1_MODULE_MULTISET_TESTS_ */ +#endif /* SECP256K1_MODULE_MULTISET_TESTS_H */ diff --git a/src/secp256k1/src/modules/schnorr/main_impl.h b/src/secp256k1/src/modules/schnorr/main_impl.h index d7f9cb6be..113d4d308 100644 --- a/src/secp256k1/src/modules/schnorr/main_impl.h +++ b/src/secp256k1/src/modules/schnorr/main_impl.h @@ -1,77 +1,77 @@ /*********************************************************************** * Copyright (c) 2017 Amaury Séchet * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef SECP256K1_MODULE_SCHNORR_MAIN -#define SECP256K1_MODULE_SCHNORR_MAIN +#ifndef SECP256K1_MODULE_SCHNORR_MAIN_H +#define SECP256K1_MODULE_SCHNORR_MAIN_H #include "include/secp256k1_schnorr.h" #include "modules/schnorr/schnorr_impl.h" int secp256k1_schnorr_verify( const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msghash32, const secp256k1_pubkey *pubkey ) { secp256k1_ge q; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(sig64 != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_pubkey_load(ctx, &q, pubkey)) { return 0; } return secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64, &q, msghash32); } int secp256k1_schnorr_sign( const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *msghash32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void *ndata ) { secp256k1_scalar sec; secp256k1_pubkey pubkey; secp256k1_ge p; int overflow; int ret = 0; int pubkeyret; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(msghash32 != NULL); ARG_CHECK(sig64 != NULL); ARG_CHECK(seckey != NULL); pubkeyret = secp256k1_ec_pubkey_create(ctx, &pubkey, seckey); secp256k1_declassify(ctx, &pubkeyret, sizeof(pubkeyret)); if (!pubkeyret) { return 0; } secp256k1_declassify(ctx, &pubkey, sizeof(pubkey)); if (!secp256k1_pubkey_load(ctx, &p, &pubkey)) { return 0; } secp256k1_scalar_set_b32(&sec, seckey, &overflow); overflow |= secp256k1_scalar_is_zero(&sec); secp256k1_scalar_cmov(&sec, &secp256k1_scalar_one, overflow); ret = secp256k1_schnorr_sig_sign(ctx, sig64, msghash32, &sec, &p, noncefp, ndata); if (!ret) { memset(sig64, 0, 64); } secp256k1_scalar_clear(&sec); return !!ret & !overflow; } #endif diff --git a/src/secp256k1/src/modules/schnorr/schnorr.h b/src/secp256k1/src/modules/schnorr/schnorr.h index 14de6d045..55cd1491a 100644 --- a/src/secp256k1/src/modules/schnorr/schnorr.h +++ b/src/secp256k1/src/modules/schnorr/schnorr.h @@ -1,46 +1,46 @@ /*********************************************************************** * Copyright (c) 2017 Amaury SÉCHET * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_SCHNORR_H_ -#define _SECP256K1_MODULE_SCHNORR_H_ +#ifndef SECP256K1_MODULE_SCHNORR_H +#define SECP256K1_MODULE_SCHNORR_H #include "scalar.h" #include "group.h" static int secp256k1_schnorr_sig_verify( const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, const unsigned char *msg32 ); static int secp256k1_schnorr_compute_e( secp256k1_scalar* res, const unsigned char *r, secp256k1_ge *pubkey, const unsigned char *msg32 ); static int secp256k1_schnorr_sig_sign( const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_ge *pubkey, secp256k1_nonce_function noncefp, const void *ndata ); static int secp256k1_schnorr_sig_generate_k( const secp256k1_context* ctx, secp256k1_scalar *k, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_nonce_function noncefp, const void *ndata ); #endif diff --git a/src/secp256k1/src/modules/schnorr/schnorr_impl.h b/src/secp256k1/src/modules/schnorr/schnorr_impl.h index 60511ea8f..99d4993e3 100644 --- a/src/secp256k1/src/modules/schnorr/schnorr_impl.h +++ b/src/secp256k1/src/modules/schnorr/schnorr_impl.h @@ -1,220 +1,220 @@ /*********************************************************************** * Copyright (c) 2017 Amaury SÉCHET * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_SCHNORR_IMPL_H_ -#define _SECP256K1_SCHNORR_IMPL_H_ +#ifndef SECP256K1_MODULE_SCHNORR_IMPL_H +#define SECP256K1_MODULE_SCHNORR_IMPL_H #include #include "schnorr.h" #include "field.h" #include "group.h" #include "hash.h" #include "ecmult.h" #include "ecmult_gen.h" /** * Custom Schnorr-based signature scheme. * * Signing: * Inputs: * 32-byte message m, * 32-byte scalar key x (!=0) * public key point P, * 32-byte scalar nonce k (!=0) * * Compute point R = k * G. Negate nonce if R.y is not a quadratic residue. * Compute scalar e = Hash(R.x || compressed(P) || m) mod n. * Compute scalar s = k + e * x. * The signature is (R.x, s). * * Verification: * Inputs: * 32-byte message m, * public key point P, * signature: (32-byte r, scalar s) * * Signature is invalid if s >= n or r >= p. * Compute scalar e = Hash(r || compressed(P) || m) mod n. * Option 1 (faster for single verification): * Compute point R = s * G - e * P. * Reject if R is infinity or R.y is not a quadratic residue. * Signature is valid if the serialization of R.x equals r. * Option 2 (allows batch validation): * Decompress x coordinate r into point R, with R.y a quadratic residue. * Reject if R is not on the curve. * Signature is valid if R + e * P - s * G == 0. */ static int secp256k1_schnorr_sig_verify( const secp256k1_ecmult_context* ctx, const unsigned char *sig64, secp256k1_ge *pubkey, const unsigned char *msg32 ) { secp256k1_gej Pj, Rj; secp256k1_fe Rx; secp256k1_scalar e, s; int overflow; VERIFY_CHECK(!secp256k1_ge_is_infinity(pubkey)); /* Extract s */ overflow = 0; secp256k1_scalar_set_b32(&s, sig64 + 32, &overflow); if (overflow) { return 0; } /* Extract R.x */ if (!secp256k1_fe_set_b32(&Rx, sig64)) { return 0; } /* Compute e */ secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32); /* Verify the signature */ secp256k1_scalar_negate(&e, &e); secp256k1_gej_set_ge(&Pj, pubkey); secp256k1_ecmult(ctx, &Rj, &Pj, &e, &s); if (secp256k1_gej_is_infinity(&Rj)) { return 0; } /* Check that R.x is what we expect */ if (!secp256k1_gej_eq_x_var(&Rx, &Rj)) { return 0; } /* Check that jacobi(R.y) is 1 */ if (!secp256k1_gej_has_quad_y_var(&Rj)) { return 0; } /* All good, we have a valid signature. */ return 1; } static int secp256k1_schnorr_compute_e( secp256k1_scalar* e, const unsigned char *r, secp256k1_ge *p, const unsigned char *msg32 ) { int overflow = 0; size_t size = 0; secp256k1_sha256 sha; unsigned char buf[33]; secp256k1_sha256_initialize(&sha); /* R.x */ secp256k1_sha256_write(&sha, r, 32); /* compressed P */ secp256k1_eckey_pubkey_serialize(p, buf, &size, 1); VERIFY_CHECK(size == 33); secp256k1_sha256_write(&sha, buf, 33); /* msg */ secp256k1_sha256_write(&sha, msg32, 32); /* compute e */ secp256k1_sha256_finalize(&sha, buf); secp256k1_scalar_set_b32(e, buf, &overflow); return !overflow & !secp256k1_scalar_is_zero(e); } static int secp256k1_schnorr_sig_sign( const secp256k1_context* ctx, unsigned char *sig64, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_ge *pubkey, secp256k1_nonce_function noncefp, const void *ndata ) { secp256k1_ge R; secp256k1_gej Rj; secp256k1_scalar k, e, s; ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); VERIFY_CHECK(!secp256k1_scalar_is_zero(privkey)); VERIFY_CHECK(!secp256k1_ge_is_infinity(pubkey)); if (!secp256k1_schnorr_sig_generate_k(ctx, &k, msg32, privkey, noncefp, ndata)) { return 0; } /* Compute R */ secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Rj, &k); secp256k1_ge_set_gej(&R, &Rj); /* * We declassify R to allow using it as a branch point. * This is fine because R is not a secret. */ secp256k1_declassify(ctx, &R, sizeof(R)); /** Negate the nonce if R.y is not a quadratic residue. */ secp256k1_scalar_cond_negate(&k, !secp256k1_fe_is_quad_var(&R.y)); /* Compute the signature. */ secp256k1_fe_normalize(&R.x); secp256k1_fe_get_b32(sig64, &R.x); secp256k1_schnorr_compute_e(&e, sig64, pubkey, msg32); secp256k1_scalar_mul(&s, &e, privkey); secp256k1_scalar_add(&s, &s, &k); secp256k1_scalar_get_b32(sig64 + 32, &s); /* Cleanup locals that may contain private data. */ secp256k1_scalar_clear(&k); return 1; } static int secp256k1_schnorr_sig_generate_k( const secp256k1_context* ctx, secp256k1_scalar *k, const unsigned char *msg32, const secp256k1_scalar *privkey, secp256k1_nonce_function noncefp, const void *ndata ) { int ret = 0; unsigned int count = 0; unsigned char nonce32[32], seckey[32]; /* Seed used to make sure we generate different values of k for schnorr */ const unsigned char secp256k1_schnorr_algo16[17] = "Schnorr+SHA256 "; if (noncefp == NULL) { noncefp = secp256k1_nonce_function_default; } secp256k1_scalar_get_b32(seckey, privkey); while (1) { int overflow; ret = noncefp(nonce32, msg32, seckey, secp256k1_schnorr_algo16, (void*)ndata, count++); if (!ret) { break; } secp256k1_scalar_set_b32(k, nonce32, &overflow); overflow |= secp256k1_scalar_is_zero(k); /* The nonce is still secret here, but it overflowing or being zero is is less likely than 1:2^255. */ secp256k1_declassify(ctx, &overflow, sizeof(overflow)); if (!overflow) { break; } secp256k1_scalar_clear(k); } /* Cleanup locals that may contain private data. */ memset(seckey, 0, 32); memset(nonce32, 0, 32); return ret; } #endif diff --git a/src/secp256k1/src/modules/schnorr/tests_impl.h b/src/secp256k1/src/modules/schnorr/tests_impl.h index b7daa9801..795778bc6 100644 --- a/src/secp256k1/src/modules/schnorr/tests_impl.h +++ b/src/secp256k1/src/modules/schnorr/tests_impl.h @@ -1,522 +1,522 @@ /*********************************************************************** * Copyright (c) 2017 Amaury SÉCHET * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef SECP256K1_MODULE_SCHNORR_TESTS -#define SECP256K1_MODULE_SCHNORR_TESTS +#ifndef SECP256K1_MODULE_SCHNORR_TESTS_H +#define SECP256K1_MODULE_SCHNORR_TESTS_H #include "include/secp256k1_schnorr.h" void test_schnorr_end_to_end(void) { unsigned char privkey[32]; unsigned char message[32]; unsigned char schnorr_signature[64]; secp256k1_pubkey pubkey; /* Generate a random key and message. */ { secp256k1_scalar key; random_scalar_order_test(&key); secp256k1_scalar_get_b32(privkey, &key); secp256k1_testrand256_test(message); } /* Construct and verify corresponding public key. */ CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); /* Schnorr sign. */ CHECK(secp256k1_schnorr_sign(ctx, schnorr_signature, message, privkey, NULL, NULL) == 1); CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 1); /* Destroy signature and verify again. */ schnorr_signature[secp256k1_testrand_bits(6)] += 1 + secp256k1_testrand_int(255); CHECK(secp256k1_schnorr_verify(ctx, schnorr_signature, message, &pubkey) == 0); } #define SIG_COUNT 32 void test_schnorr_sign_verify(void) { unsigned char msg32[32]; unsigned char sig64[SIG_COUNT][64]; unsigned char ndata[SIG_COUNT][32]; secp256k1_gej pubkeyj[SIG_COUNT]; secp256k1_ge pubkey[SIG_COUNT]; secp256k1_scalar key[SIG_COUNT]; int i, j; secp256k1_testrand256_test(msg32); for (i = 0; i < SIG_COUNT; i++) { random_scalar_order_test(&key[i]); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj[i], &key[i]); secp256k1_ge_set_gej_var(&pubkey[i], &pubkeyj[i]); secp256k1_fe_normalize(&pubkey[i].x); secp256k1_fe_normalize(&pubkey[i].y); do { secp256k1_testrand256_test(ndata[i]); if (secp256k1_schnorr_sig_sign(ctx, sig64[i], msg32, &key[i], &pubkey[i], NULL, &ndata[i])) { break; } } while(1); CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[i], &pubkey[i], msg32)); /* Apply several random modifications to the sig and check that it * doesn't verify anymore. */ for (j = 0; j < count; j++) { int pos = secp256k1_testrand_bits(6); int mod = 1 + secp256k1_testrand_int(255); sig64[i][pos] ^= mod; CHECK(secp256k1_schnorr_sig_verify(&ctx->ecmult_ctx, sig64[i], &pubkey[i], msg32) == 0); sig64[i][pos] ^= mod; } } } #undef SIG_COUNT void run_schnorr_compact_test(void) { { /* Test vector 1 */ static const unsigned char pkbuf[33] = { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, }; static const unsigned char msg[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char sig[64] = { 0x78, 0x7A, 0x84, 0x8E, 0x71, 0x04, 0x3D, 0x28, 0x0C, 0x50, 0x47, 0x0E, 0x8E, 0x15, 0x32, 0xB2, 0xDD, 0x5D, 0x20, 0xEE, 0x91, 0x2A, 0x45, 0xDB, 0xDD, 0x2B, 0xD1, 0xDF, 0xBF, 0x18, 0x7E, 0xF6, 0x70, 0x31, 0xA9, 0x88, 0x31, 0x85, 0x9D, 0xC3, 0x4D, 0xFF, 0xEE, 0xDD, 0xA8, 0x68, 0x31, 0x84, 0x2C, 0xCD, 0x00, 0x79, 0xE1, 0xF9, 0x2A, 0xF1, 0x77, 0xF7, 0xF2, 0x2C, 0xC1, 0xDC, 0xED, 0x05, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 2 */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 3 */ static const unsigned char pkbuf[33] = { 0x03, 0xFA, 0xC2, 0x11, 0x4C, 0x2F, 0xBB, 0x09, 0x15, 0x27, 0xEB, 0x7C, 0x64, 0xEC, 0xB1, 0x1F, 0x80, 0x21, 0xCB, 0x45, 0xE8, 0xE7, 0x80, 0x9D, 0x3C, 0x09, 0x38, 0xE4, 0xB8, 0xC0, 0xE5, 0xF8, 0x4B, }; static const unsigned char msg[32] = { 0x5E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C, }; static const unsigned char sig[64] = { 0x00, 0xDA, 0x9B, 0x08, 0x17, 0x2A, 0x9B, 0x6F, 0x04, 0x66, 0xA2, 0xDE, 0xFD, 0x81, 0x7F, 0x2D, 0x7A, 0xB4, 0x37, 0xE0, 0xD2, 0x53, 0xCB, 0x53, 0x95, 0xA9, 0x63, 0x86, 0x6B, 0x35, 0x74, 0xBE, 0x00, 0x88, 0x03, 0x71, 0xD0, 0x17, 0x66, 0x93, 0x5B, 0x92, 0xD2, 0xAB, 0x4C, 0xD5, 0xC8, 0xA2, 0xA5, 0x83, 0x7E, 0xC5, 0x7F, 0xED, 0x76, 0x60, 0x77, 0x3A, 0x05, 0xF0, 0xDE, 0x14, 0x23, 0x80, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 4 */ static const unsigned char pkbuf[33] = { 0x03, 0xDE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50, 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21, 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34, }; static const unsigned char msg[32] = { 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2, 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24, 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B, 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03, }; static const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F, 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28, 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63, 0x02, 0xA8, 0xDC, 0x32, 0xE6, 0x4E, 0x86, 0xA3, 0x33, 0xF2, 0x0E, 0xF5, 0x6E, 0xAC, 0x9B, 0xA3, 0x0B, 0x72, 0x46, 0xD6, 0xD2, 0x5E, 0x22, 0xAD, 0xB8, 0xC6, 0xBE, 0x1A, 0xEB, 0x08, 0xD4, 0x9D, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 4b */ static const unsigned char pkbuf[33] = { 0x03, 0x1B, 0x84, 0xC5, 0x56, 0x7B, 0x12, 0x64, 0x40, 0x99, 0x5D, 0x3E, 0xD5, 0xAA, 0xBA, 0x05, 0x65, 0xD7, 0x1E, 0x18, 0x34, 0x60, 0x48, 0x19, 0xFF, 0x9C, 0x17, 0xF5, 0xE9, 0xD5, 0xDD, 0x07, 0x8F, }; static const unsigned char msg[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char sig[64] = { 0x52, 0x81, 0x85, 0x79, 0xAC, 0xA5, 0x97, 0x67, 0xE3, 0x29, 0x1D, 0x91, 0xB7, 0x6B, 0x63, 0x7B, 0xEF, 0x06, 0x20, 0x83, 0x28, 0x49, 0x92, 0xF2, 0xD9, 0x5F, 0x56, 0x4C, 0xA6, 0xCB, 0x4E, 0x35, 0x30, 0xB1, 0xDA, 0x84, 0x9C, 0x8E, 0x83, 0x04, 0xAD, 0xC0, 0xCF, 0xE8, 0x70, 0x66, 0x03, 0x34, 0xB3, 0xCF, 0xC1, 0x8E, 0x82, 0x5E, 0xF1, 0xDB, 0x34, 0xCF, 0xAE, 0x3D, 0xFC, 0x5D, 0x81, 0x87, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey)); } { /* Test vector 6: R.y is not a quadratic residue */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0xFA, 0x16, 0xAE, 0xE0, 0x66, 0x09, 0x28, 0x0A, 0x19, 0xB6, 0x7A, 0x24, 0xE1, 0x97, 0x7E, 0x46, 0x97, 0x71, 0x2B, 0x5F, 0xD2, 0x94, 0x39, 0x14, 0xEC, 0xD5, 0xF7, 0x30, 0x90, 0x1B, 0x4A, 0xB7, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 7: Negated message hash, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x03, 0xFA, 0xC2, 0x11, 0x4C, 0x2F, 0xBB, 0x09, 0x15, 0x27, 0xEB, 0x7C, 0x64, 0xEC, 0xB1, 0x1F, 0x80, 0x21, 0xCB, 0x45, 0xE8, 0xE7, 0x80, 0x9D, 0x3C, 0x09, 0x38, 0xE4, 0xB8, 0xC0, 0xE5, 0xF8, 0x4B, }; static const unsigned char msg[32] = { 0x5E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C, }; static const unsigned char sig[64] = { 0x00, 0xDA, 0x9B, 0x08, 0x17, 0x2A, 0x9B, 0x6F, 0x04, 0x66, 0xA2, 0xDE, 0xFD, 0x81, 0x7F, 0x2D, 0x7A, 0xB4, 0x37, 0xE0, 0xD2, 0x53, 0xCB, 0x53, 0x95, 0xA9, 0x63, 0x86, 0x6B, 0x35, 0x74, 0xBE, 0xD0, 0x92, 0xF9, 0xD8, 0x60, 0xF1, 0x77, 0x6A, 0x1F, 0x74, 0x12, 0xAD, 0x8A, 0x1E, 0xB5, 0x0D, 0xAC, 0xCC, 0x22, 0x2B, 0xC8, 0xC0, 0xE2, 0x6B, 0x20, 0x56, 0xDF, 0x2F, 0x27, 0x3E, 0xFD, 0xEC, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 8: Negated s, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98, }; static const unsigned char msg[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static const unsigned char sig[64] = { 0x78, 0x7A, 0x84, 0x8E, 0x71, 0x04, 0x3D, 0x28, 0x0C, 0x50, 0x47, 0x0E, 0x8E, 0x15, 0x32, 0xB2, 0xDD, 0x5D, 0x20, 0xEE, 0x91, 0x2A, 0x45, 0xDB, 0xDD, 0x2B, 0xD1, 0xDF, 0xBF, 0x18, 0x7E, 0xF6, 0x8F, 0xCE, 0x56, 0x77, 0xCE, 0x7A, 0x62, 0x3C, 0xB2, 0x00, 0x11, 0x22, 0x57, 0x97, 0xCE, 0x7A, 0x8D, 0xE1, 0xDC, 0x6C, 0xCD, 0x4F, 0x75, 0x4A, 0x47, 0xDA, 0x6C, 0x60, 0x0E, 0x59, 0x54, 0x3C, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 9: Negated P, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x03, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 10: s * G = e * P, R = 0 */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x8C, 0x34, 0x28, 0x86, 0x9A, 0x66, 0x3E, 0xD1, 0xE9, 0x54, 0x70, 0x5B, 0x02, 0x0C, 0xBB, 0x3E, 0x7B, 0xB6, 0xAC, 0x31, 0x96, 0x5B, 0x9E, 0xA4, 0xC7, 0x3E, 0x22, 0x7B, 0x17, 0xC5, 0xAF, 0x5A, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 11: R.x not on the curve, R.x mismatch */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 12: r = p */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x2F, 0x1E, 0x51, 0xA2, 0x2C, 0xCE, 0xC3, 0x55, 0x99, 0xB8, 0xF2, 0x66, 0x91, 0x22, 0x81, 0xF8, 0x36, 0x5F, 0xFC, 0x2D, 0x03, 0x5A, 0x23, 0x04, 0x34, 0xA1, 0xA6, 0x4D, 0xC5, 0x9F, 0x70, 0x13, 0xFD, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } { /* Test vector 13: s = n */ static const unsigned char pkbuf[33] = { 0x02, 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59, }; static const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, }; static const unsigned char sig[64] = { 0x2A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41, }; secp256k1_pubkey pubkey; CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pkbuf, 33)); CHECK(secp256k1_schnorr_verify(ctx, sig, msg, &pubkey) == 0); } } void run_schnorr_tests(void) { int i; for (i = 0; i < 32 * count; i++) { test_schnorr_end_to_end(); } test_schnorr_sign_verify(); run_schnorr_compact_test(); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/main_impl.h b/src/secp256k1/src/modules/schnorrsig/main_impl.h index 902025cb6..22e1b33a5 100644 --- a/src/secp256k1/src/modules/schnorrsig/main_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/main_impl.h @@ -1,239 +1,239 @@ /*********************************************************************** * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_SCHNORRSIG_MAIN_ -#define _SECP256K1_MODULE_SCHNORRSIG_MAIN_ +#ifndef SECP256K1_MODULE_SCHNORRSIG_MAIN_H +#define SECP256K1_MODULE_SCHNORRSIG_MAIN_H #include "include/secp256k1.h" #include "include/secp256k1_schnorrsig.h" #include "hash.h" /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/nonce")||SHA256("BIP0340/nonce"). */ static void secp256k1_nonce_function_bip340_sha256_tagged(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x46615b35ul; sha->s[1] = 0xf4bfbff7ul; sha->s[2] = 0x9f8dc671ul; sha->s[3] = 0x83627ab3ul; sha->s[4] = 0x60217180ul; sha->s[5] = 0x57358661ul; sha->s[6] = 0x21a29e54ul; sha->s[7] = 0x68b07b4cul; sha->bytes = 64; } /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/aux")||SHA256("BIP0340/aux"). */ static void secp256k1_nonce_function_bip340_sha256_tagged_aux(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x24dd3219ul; sha->s[1] = 0x4eba7e70ul; sha->s[2] = 0xca0fabb9ul; sha->s[3] = 0x0fa3166dul; sha->s[4] = 0x3afbe4b1ul; sha->s[5] = 0x4c44df97ul; sha->s[6] = 0x4aac2739ul; sha->s[7] = 0x249e850aul; sha->bytes = 64; } /* algo16 argument for nonce_function_bip340 to derive the nonce exactly as stated in BIP-340 * by using the correct tagged hash function. */ static const unsigned char bip340_algo16[16] = "BIP0340/nonce\0\0\0"; static int nonce_function_bip340(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { secp256k1_sha256 sha; unsigned char masked_key[32]; int i; if (algo16 == NULL) { return 0; } if (data != NULL) { secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha); secp256k1_sha256_write(&sha, data, 32); secp256k1_sha256_finalize(&sha, masked_key); for (i = 0; i < 32; i++) { masked_key[i] ^= key32[i]; } } /* Tag the hash with algo16 which is important to avoid nonce reuse across * algorithms. If this nonce function is used in BIP-340 signing as defined * in the spec, an optimized tagging implementation is used. */ if (secp256k1_memcmp_var(algo16, bip340_algo16, 16) == 0) { secp256k1_nonce_function_bip340_sha256_tagged(&sha); } else { int algo16_len = 16; /* Remove terminating null bytes */ while (algo16_len > 0 && !algo16[algo16_len - 1]) { algo16_len--; } secp256k1_sha256_initialize_tagged(&sha, algo16, algo16_len); } /* Hash (masked-)key||pk||msg using the tagged hash as per the spec */ if (data != NULL) { secp256k1_sha256_write(&sha, masked_key, 32); } else { secp256k1_sha256_write(&sha, key32, 32); } secp256k1_sha256_write(&sha, xonly_pk32, 32); secp256k1_sha256_write(&sha, msg32, 32); secp256k1_sha256_finalize(&sha, nonce32); return 1; } const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340 = nonce_function_bip340; /* Initializes SHA256 with fixed midstate. This midstate was computed by applying * SHA256 to SHA256("BIP0340/challenge")||SHA256("BIP0340/challenge"). */ static void secp256k1_schnorrsig_sha256_tagged(secp256k1_sha256 *sha) { secp256k1_sha256_initialize(sha); sha->s[0] = 0x9cecba11ul; sha->s[1] = 0x23925381ul; sha->s[2] = 0x11679112ul; sha->s[3] = 0xd1627e0ful; sha->s[4] = 0x97c87550ul; sha->s[5] = 0x003cc765ul; sha->s[6] = 0x90f61164ul; sha->s[7] = 0x33e9b66aul; sha->bytes = 64; } static void secp256k1_schnorrsig_challenge(secp256k1_scalar* e, const unsigned char *r32, const unsigned char *msg32, const unsigned char *pubkey32) { unsigned char buf[32]; secp256k1_sha256 sha; /* tagged hash(r.x, pk.x, msg32) */ secp256k1_schnorrsig_sha256_tagged(&sha); secp256k1_sha256_write(&sha, r32, 32); secp256k1_sha256_write(&sha, pubkey32, 32); secp256k1_sha256_write(&sha, msg32, 32); secp256k1_sha256_finalize(&sha, buf); /* Set scalar e to the challenge hash modulo the curve order as per * BIP340. */ 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, secp256k1_nonce_function_hardened noncefp, void *ndata) { secp256k1_scalar sk; secp256k1_scalar e; secp256k1_scalar k; secp256k1_gej rj; secp256k1_ge pk; secp256k1_ge r; unsigned char buf[32] = { 0 }; unsigned char pk_buf[32]; unsigned char seckey[32]; int ret = 1; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); ARG_CHECK(sig64 != NULL); ARG_CHECK(msg32 != NULL); ARG_CHECK(keypair != NULL); if (noncefp == NULL) { noncefp = secp256k1_nonce_function_bip340; } ret &= secp256k1_keypair_load(ctx, &sk, &pk, keypair); /* Because we are signing for a x-only pubkey, the secret key is negated * before signing if the point corresponding to the secret key does not * have an even Y. */ if (secp256k1_fe_is_odd(&pk.y)) { secp256k1_scalar_negate(&sk, &sk); } secp256k1_scalar_get_b32(seckey, &sk); secp256k1_fe_get_b32(pk_buf, &pk.x); ret &= !!noncefp(buf, msg32, seckey, pk_buf, bip340_algo16, ndata); secp256k1_scalar_set_b32(&k, buf, NULL); ret &= !secp256k1_scalar_is_zero(&k); secp256k1_scalar_cmov(&k, &secp256k1_scalar_one, !ret); secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &rj, &k); secp256k1_ge_set_gej(&r, &rj); /* We declassify r to allow using it as a branch point. This is fine * because r is not a secret. */ secp256k1_declassify(ctx, &r, sizeof(r)); secp256k1_fe_normalize_var(&r.y); if (secp256k1_fe_is_odd(&r.y)) { secp256k1_scalar_negate(&k, &k); } secp256k1_fe_normalize_var(&r.x); secp256k1_fe_get_b32(&sig64[0], &r.x); secp256k1_schnorrsig_challenge(&e, &sig64[0], msg32, pk_buf); secp256k1_scalar_mul(&e, &e, &sk); secp256k1_scalar_add(&e, &e, &k); secp256k1_scalar_get_b32(&sig64[32], &e); secp256k1_memczero(sig64, 64, !ret); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); memset(seckey, 0, sizeof(seckey)); return ret; } int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned char *sig64, const unsigned char *msg32, const secp256k1_xonly_pubkey *pubkey) { secp256k1_scalar s; secp256k1_scalar e; secp256k1_gej rj; secp256k1_ge pk; secp256k1_gej pkj; secp256k1_fe rx; secp256k1_ge r; unsigned char buf[32]; int overflow; VERIFY_CHECK(ctx != NULL); ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); ARG_CHECK(sig64 != NULL); ARG_CHECK(msg32 != NULL); ARG_CHECK(pubkey != NULL); if (!secp256k1_fe_set_b32(&rx, &sig64[0])) { return 0; } secp256k1_scalar_set_b32(&s, &sig64[32], &overflow); if (overflow) { return 0; } if (!secp256k1_xonly_pubkey_load(ctx, &pk, pubkey)) { return 0; } /* Compute e. */ secp256k1_fe_get_b32(buf, &pk.x); secp256k1_schnorrsig_challenge(&e, &sig64[0], msg32, buf); /* Compute rj = s*G + (-e)*pkj */ secp256k1_scalar_negate(&e, &e); secp256k1_gej_set_ge(&pkj, &pk); secp256k1_ecmult(&ctx->ecmult_ctx, &rj, &pkj, &e, &s); secp256k1_ge_set_gej_var(&r, &rj); if (secp256k1_ge_is_infinity(&r)) { return 0; } secp256k1_fe_normalize_var(&r.y); return !secp256k1_fe_is_odd(&r.y) && secp256k1_fe_equal_var(&rx, &r.x); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h index 7e6a1e791..b4a428729 100644 --- a/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/tests_exhaustive_impl.h @@ -1,206 +1,206 @@ /*********************************************************************** * Copyright (c) 2020 Pieter Wuille * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_ -#define _SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_ +#ifndef SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H +#define SECP256K1_MODULE_SCHNORRSIG_TESTS_EXHAUSTIVE_H #include "include/secp256k1_schnorrsig.h" #include "src/modules/schnorrsig/main_impl.h" static const unsigned char invalid_pubkey_bytes[][32] = { /* 0 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* 2 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, /* order */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 24) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 16) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 0UL) >> 8) & 0xFF, (EXHAUSTIVE_TEST_ORDER + 0UL) & 0xFF }, /* order + 1 */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 24) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 16) & 0xFF, ((EXHAUSTIVE_TEST_ORDER + 1UL) >> 8) & 0xFF, (EXHAUSTIVE_TEST_ORDER + 1UL) & 0xFF }, /* field size */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F }, /* field size + 1 (note that 1 is legal) */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }, /* 2^256 - 1 */ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; #define NUM_INVALID_KEYS (sizeof(invalid_pubkey_bytes) / sizeof(invalid_pubkey_bytes[0])) static int secp256k1_hardened_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void* data) { secp256k1_scalar s; int *idata = data; (void)msg32; (void)key32; (void)xonly_pk32; (void)algo16; secp256k1_scalar_set_int(&s, *idata); secp256k1_scalar_get_b32(nonce32, &s); return 1; } static void test_exhaustive_schnorrsig_verify(const secp256k1_context *ctx, const secp256k1_xonly_pubkey* pubkeys, unsigned char (*xonly_pubkey_bytes)[32], const int* parities) { int d; uint64_t iter = 0; /* Iterate over the possible public keys to verify against (through their corresponding DL d). */ for (d = 1; d <= EXHAUSTIVE_TEST_ORDER / 2; ++d) { int actual_d; unsigned k; unsigned char pk32[32]; memcpy(pk32, xonly_pubkey_bytes[d - 1], 32); actual_d = parities[d - 1] ? EXHAUSTIVE_TEST_ORDER - d : d; /* Iterate over the possible valid first 32 bytes in the signature, through their corresponding DL k. Values above EXHAUSTIVE_TEST_ORDER/2 refer to the entries in invalid_pubkey_bytes. */ for (k = 1; k <= EXHAUSTIVE_TEST_ORDER / 2 + NUM_INVALID_KEYS; ++k) { unsigned char sig64[64]; int actual_k = -1; int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; int e_count_done = 0; if (skip_section(&iter)) continue; if (k <= EXHAUSTIVE_TEST_ORDER / 2) { memcpy(sig64, xonly_pubkey_bytes[k - 1], 32); actual_k = parities[k - 1] ? EXHAUSTIVE_TEST_ORDER - k : k; } else { memcpy(sig64, invalid_pubkey_bytes[k - 1 - EXHAUSTIVE_TEST_ORDER / 2], 32); } /* Randomly generate messages until all challenges have been hit. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; unsigned char msg32[32]; secp256k1_testrand256(msg32); secp256k1_schnorrsig_challenge(&e, sig64, msg32, pk32); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { /* Iterate over the possible valid last 32 bytes in the signature. 0..order=that s value; order+1=random bytes */ int count_valid = 0, s; for (s = 0; s <= EXHAUSTIVE_TEST_ORDER + 1; ++s) { int expect_valid, valid; if (s <= EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar s_s; secp256k1_scalar_set_int(&s_s, s); secp256k1_scalar_get_b32(sig64 + 32, &s_s); expect_valid = actual_k != -1 && s != EXHAUSTIVE_TEST_ORDER && (s_s == (actual_k + actual_d * e) % EXHAUSTIVE_TEST_ORDER); } else { secp256k1_testrand256(sig64 + 32); expect_valid = 0; } valid = secp256k1_schnorrsig_verify(ctx, sig64, msg32, &pubkeys[d - 1]); CHECK(valid == expect_valid); count_valid += valid; } /* Exactly one s value must verify, unless R is illegal. */ CHECK(count_valid == (actual_k != -1)); /* Don't retry other messages that result in the same challenge. */ e_done[e] = 1; ++e_count_done; } } } } } 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; uint64_t iter = 0; /* Loop over keys. */ for (d = 1; d < EXHAUSTIVE_TEST_ORDER; ++d) { int actual_d = d; if (parities[d - 1]) actual_d = EXHAUSTIVE_TEST_ORDER - d; /* Loop over nonces. */ for (k = 1; k < EXHAUSTIVE_TEST_ORDER; ++k) { int e_done[EXHAUSTIVE_TEST_ORDER] = {0}; int e_count_done = 0; unsigned char msg32[32]; unsigned char sig64[64]; int actual_k = k; if (skip_section(&iter)) continue; if (parities[k - 1]) actual_k = EXHAUSTIVE_TEST_ORDER - k; /* Generate random messages until all challenges have been tried. */ while (e_count_done < EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar e; secp256k1_testrand256(msg32); secp256k1_schnorrsig_challenge(&e, xonly_pubkey_bytes[k - 1], msg32, xonly_pubkey_bytes[d - 1]); /* Only do work if we hit a challenge we haven't tried before. */ if (!e_done[e]) { secp256k1_scalar expected_s = (actual_k + e * actual_d) % EXHAUSTIVE_TEST_ORDER; unsigned char expected_s_bytes[32]; secp256k1_scalar_get_b32(expected_s_bytes, &expected_s); /* Invoke the real function to construct a signature. */ CHECK(secp256k1_schnorrsig_sign(ctx, sig64, msg32, &keypairs[d - 1], secp256k1_hardened_nonce_function_smallint, &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); /* The last 32 bytes must match the expected s value. */ CHECK(secp256k1_memcmp_var(sig64 + 32, expected_s_bytes, 32) == 0); /* Don't retry other messages that result in the same challenge. */ e_done[e] = 1; ++e_count_done; } } } } } static void test_exhaustive_schnorrsig(const secp256k1_context *ctx) { secp256k1_keypair keypair[EXHAUSTIVE_TEST_ORDER - 1]; secp256k1_xonly_pubkey xonly_pubkey[EXHAUSTIVE_TEST_ORDER - 1]; int parity[EXHAUSTIVE_TEST_ORDER - 1]; unsigned char xonly_pubkey_bytes[EXHAUSTIVE_TEST_ORDER - 1][32]; unsigned i; /* Verify that all invalid_pubkey_bytes are actually invalid. */ for (i = 0; i < NUM_INVALID_KEYS; ++i) { secp256k1_xonly_pubkey pk; CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk, invalid_pubkey_bytes[i])); } /* Construct keypairs and xonly-pubkeys for the entire group. */ for (i = 1; i < EXHAUSTIVE_TEST_ORDER; ++i) { secp256k1_scalar scalar_i; unsigned char buf[32]; secp256k1_scalar_set_int(&scalar_i, i); secp256k1_scalar_get_b32(buf, &scalar_i); CHECK(secp256k1_keypair_create(ctx, &keypair[i - 1], buf)); CHECK(secp256k1_keypair_xonly_pub(ctx, &xonly_pubkey[i - 1], &parity[i - 1], &keypair[i - 1])); CHECK(secp256k1_xonly_pubkey_serialize(ctx, xonly_pubkey_bytes[i - 1], &xonly_pubkey[i - 1])); } test_exhaustive_schnorrsig_sign(ctx, xonly_pubkey_bytes, keypair, parity); test_exhaustive_schnorrsig_verify(ctx, xonly_pubkey, xonly_pubkey_bytes, parity); } #endif diff --git a/src/secp256k1/src/modules/schnorrsig/tests_impl.h b/src/secp256k1/src/modules/schnorrsig/tests_impl.h index e10c45fab..338462fc9 100644 --- a/src/secp256k1/src/modules/schnorrsig/tests_impl.h +++ b/src/secp256k1/src/modules/schnorrsig/tests_impl.h @@ -1,806 +1,806 @@ /*********************************************************************** * Copyright (c) 2018-2020 Andrew Poelstra, Jonas Nick * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_MODULE_SCHNORRSIG_TESTS_ -#define _SECP256K1_MODULE_SCHNORRSIG_TESTS_ +#ifndef SECP256K1_MODULE_SCHNORRSIG_TESTS_H +#define SECP256K1_MODULE_SCHNORRSIG_TESTS_H #include "secp256k1_schnorrsig.h" /* Checks that a bit flip in the n_flip-th argument (that has n_bytes many * bytes) changes the hash function */ void nonce_function_bip340_bitflip(unsigned char **args, size_t n_flip, size_t n_bytes) { unsigned char nonces[2][32]; CHECK(nonce_function_bip340(nonces[0], args[0], args[1], args[2], args[3], args[4]) == 1); secp256k1_testrand_flip(args[n_flip], n_bytes); CHECK(nonce_function_bip340(nonces[1], args[0], args[1], args[2], args[3], args[4]) == 1); CHECK(secp256k1_memcmp_var(nonces[0], nonces[1], 32) != 0); } /* Tests for the equality of two sha256 structs. This function only produces a * correct result if an integer multiple of 64 many bytes have been written * into the hash functions. */ void test_sha256_eq(const secp256k1_sha256 *sha1, const secp256k1_sha256 *sha2) { /* Is buffer fully consumed? */ CHECK((sha1->bytes & 0x3F) == 0); CHECK(sha1->bytes == sha2->bytes); CHECK(secp256k1_memcmp_var(sha1->s, sha2->s, sizeof(sha1->s)) == 0); } void run_nonce_function_bip340_tests(void) { unsigned char tag[13] = "BIP0340/nonce"; unsigned char aux_tag[11] = "BIP0340/aux"; unsigned char algo16[16] = "BIP0340/nonce\0\0\0"; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; unsigned char nonce[32]; unsigned char msg[32]; unsigned char key[32]; unsigned char pk[32]; unsigned char aux_rand[32]; unsigned char *args[5]; int i; /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged has the expected * state. */ secp256k1_sha256_initialize_tagged(&sha, tag, sizeof(tag)); secp256k1_nonce_function_bip340_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); /* Check that hash initialized by * secp256k1_nonce_function_bip340_sha256_tagged_aux has the expected * state. */ secp256k1_sha256_initialize_tagged(&sha, aux_tag, sizeof(aux_tag)); secp256k1_nonce_function_bip340_sha256_tagged_aux(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); secp256k1_testrand256(msg); secp256k1_testrand256(key); secp256k1_testrand256(pk); secp256k1_testrand256(aux_rand); /* Check that a bitflip in an argument results in different nonces. */ args[0] = msg; args[1] = key; args[2] = pk; args[3] = algo16; args[4] = aux_rand; for (i = 0; i < count; i++) { nonce_function_bip340_bitflip(args, 0, 32); nonce_function_bip340_bitflip(args, 1, 32); nonce_function_bip340_bitflip(args, 2, 32); /* Flip algo16 special case "BIP0340/nonce" */ nonce_function_bip340_bitflip(args, 3, 16); /* Flip algo16 again */ nonce_function_bip340_bitflip(args, 3, 16); nonce_function_bip340_bitflip(args, 4, 32); } /* NULL algo16 is disallowed */ CHECK(nonce_function_bip340(nonce, msg, key, pk, NULL, NULL) == 0); /* Empty algo16 is fine */ memset(algo16, 0x00, 16); CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* algo16 with terminating null bytes is fine */ algo16[1] = 65; CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* Other algo16 is fine */ memset(algo16, 0xFF, 16); CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); /* NULL aux_rand argument is allowed. */ CHECK(nonce_function_bip340(nonce, msg, key, pk, algo16, NULL) == 1); } void test_schnorrsig_api(void) { unsigned char sk1[32]; unsigned char sk2[32]; unsigned char sk3[32]; unsigned char msg[32]; secp256k1_keypair keypairs[3]; secp256k1_keypair invalid_keypair = { 0 }; secp256k1_xonly_pubkey pk[3]; secp256k1_xonly_pubkey zero_pk; unsigned char sig[64]; /** 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; secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); secp256k1_testrand256(sk1); secp256k1_testrand256(sk2); secp256k1_testrand256(sk3); secp256k1_testrand256(msg); CHECK(secp256k1_keypair_create(ctx, &keypairs[0], sk1) == 1); CHECK(secp256k1_keypair_create(ctx, &keypairs[1], sk2) == 1); CHECK(secp256k1_keypair_create(ctx, &keypairs[2], sk3) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[0], NULL, &keypairs[0]) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[1], NULL, &keypairs[1]) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk[2], NULL, &keypairs[2]) == 1); memset(&zero_pk, 0, sizeof(zero_pk)); /** main test body **/ ecount = 0; CHECK(secp256k1_schnorrsig_sign(none, sig, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 1); CHECK(secp256k1_schnorrsig_sign(vrfy, sig, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_sign(sign, NULL, msg, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 3); CHECK(secp256k1_schnorrsig_sign(sign, sig, NULL, &keypairs[0], NULL, NULL) == 0); CHECK(ecount == 4); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, NULL, NULL, NULL) == 0); CHECK(ecount == 5); CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &invalid_keypair, NULL, NULL) == 0); CHECK(ecount == 6); ecount = 0; CHECK(secp256k1_schnorrsig_sign(sign, sig, msg, &keypairs[0], NULL, NULL) == 1); CHECK(secp256k1_schnorrsig_verify(none, sig, msg, &pk[0]) == 0); CHECK(ecount == 1); CHECK(secp256k1_schnorrsig_verify(sign, sig, msg, &pk[0]) == 0); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &pk[0]) == 1); CHECK(ecount == 2); CHECK(secp256k1_schnorrsig_verify(vrfy, NULL, msg, &pk[0]) == 0); CHECK(ecount == 3); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, NULL, &pk[0]) == 0); CHECK(ecount == 4); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, NULL) == 0); CHECK(ecount == 5); CHECK(secp256k1_schnorrsig_verify(vrfy, sig, msg, &zero_pk) == 0); CHECK(ecount == 6); secp256k1_context_destroy(none); secp256k1_context_destroy(sign); secp256k1_context_destroy(vrfy); secp256k1_context_destroy(both); } /* Checks that hash initialized by secp256k1_schnorrsig_sha256_tagged has the * expected state. */ void test_schnorrsig_sha256_tagged(void) { char tag[17] = "BIP0340/challenge"; secp256k1_sha256 sha; secp256k1_sha256 sha_optimized; secp256k1_sha256_initialize_tagged(&sha, (unsigned char *) tag, sizeof(tag)); secp256k1_schnorrsig_sha256_tagged(&sha_optimized); test_sha256_eq(&sha, &sha_optimized); } /* Helper function for schnorrsig_bip_vectors * Signs the message and checks that it's the same as expected_sig. */ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, unsigned char *aux_rand, const unsigned char *msg, const unsigned char *expected_sig) { unsigned char sig[64]; secp256k1_keypair keypair; secp256k1_xonly_pubkey pk, pk_expected; CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, aux_rand)); CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0); CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk_expected, pk_serialized)); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair)); CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0); CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &pk)); } /* Helper function for schnorrsig_bip_vectors * Checks that both verify and verify_batch (TODO) return the same value as expected. */ void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) { secp256k1_xonly_pubkey pk; CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk, pk_serialized)); CHECK(expected == secp256k1_schnorrsig_verify(ctx, sig, msg32, &pk)); } /* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See * https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv. */ void test_schnorrsig_bip_vectors(void) { { /* Test vector 0 */ const unsigned char sk[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 }; const unsigned char pk[32] = { 0xF9, 0x30, 0x8A, 0x01, 0x92, 0x58, 0xC3, 0x10, 0x49, 0x34, 0x4F, 0x85, 0xF8, 0x9D, 0x52, 0x29, 0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0, 0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9 }; unsigned char aux_rand[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char msg[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const unsigned char sig[64] = { 0xE9, 0x07, 0x83, 0x1F, 0x80, 0x84, 0x8D, 0x10, 0x69, 0xA5, 0x37, 0x1B, 0x40, 0x24, 0x10, 0x36, 0x4B, 0xDF, 0x1C, 0x5F, 0x83, 0x07, 0xB0, 0x08, 0x4C, 0x55, 0xF1, 0xCE, 0x2D, 0xCA, 0x82, 0x15, 0x25, 0xF6, 0x6A, 0x4A, 0x85, 0xEA, 0x8B, 0x71, 0xE4, 0x82, 0xA7, 0x4F, 0x38, 0x2D, 0x2C, 0xE5, 0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47, 0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 1 */ const unsigned char sk[32] = { 0xB7, 0xE1, 0x51, 0x62, 0x8A, 0xED, 0x2A, 0x6A, 0xBF, 0x71, 0x58, 0x80, 0x9C, 0xF4, 0xF3, 0xC7, 0x62, 0xE7, 0x16, 0x0F, 0x38, 0xB4, 0xDA, 0x56, 0xA7, 0x84, 0xD9, 0x04, 0x51, 0x90, 0xCF, 0xEF }; const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; unsigned char aux_rand[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x68, 0x96, 0xBD, 0x60, 0xEE, 0xAE, 0x29, 0x6D, 0xB4, 0x8A, 0x22, 0x9F, 0xF7, 0x1D, 0xFE, 0x07, 0x1B, 0xDE, 0x41, 0x3E, 0x6D, 0x43, 0xF9, 0x17, 0xDC, 0x8D, 0xCF, 0x8C, 0x78, 0xDE, 0x33, 0x41, 0x89, 0x06, 0xD1, 0x1A, 0xC9, 0x76, 0xAB, 0xCC, 0xB2, 0x0B, 0x09, 0x12, 0x92, 0xBF, 0xF4, 0xEA, 0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C, 0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 2 */ const unsigned char sk[32] = { 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x14, 0xE5, 0xC9 }; const unsigned char pk[32] = { 0xDD, 0x30, 0x8A, 0xFE, 0xC5, 0x77, 0x7E, 0x13, 0x12, 0x1F, 0xA7, 0x2B, 0x9C, 0xC1, 0xB7, 0xCC, 0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9, 0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8 }; unsigned char aux_rand[32] = { 0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE, 0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC, 0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C, 0x4B, 0x0B, 0x62, 0xD7, 0x98, 0xE6, 0xD9, 0x06 }; const unsigned char msg[32] = { 0x7E, 0x2D, 0x58, 0xD8, 0xB3, 0xBC, 0xDF, 0x1A, 0xBA, 0xDE, 0xC7, 0x82, 0x90, 0x54, 0xF9, 0x0D, 0xDA, 0x98, 0x05, 0xAA, 0xB5, 0x6C, 0x77, 0x33, 0x30, 0x24, 0xB9, 0xD0, 0xA5, 0x08, 0xB7, 0x5C }; const unsigned char sig[64] = { 0x58, 0x31, 0xAA, 0xEE, 0xD7, 0xB4, 0x4B, 0xB7, 0x4E, 0x5E, 0xAB, 0x94, 0xBA, 0x9D, 0x42, 0x94, 0xC4, 0x9B, 0xCF, 0x2A, 0x60, 0x72, 0x8D, 0x8B, 0x4C, 0x20, 0x0F, 0x50, 0xDD, 0x31, 0x3C, 0x1B, 0xAB, 0x74, 0x58, 0x79, 0xA5, 0xAD, 0x95, 0x4A, 0x72, 0xC4, 0x5A, 0x91, 0xC3, 0xA5, 0x1D, 0x3C, 0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E, 0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 3 */ const unsigned char sk[32] = { 0x0B, 0x43, 0x2B, 0x26, 0x77, 0x93, 0x73, 0x81, 0xAE, 0xF0, 0x5B, 0xB0, 0x2A, 0x66, 0xEC, 0xD0, 0x12, 0x77, 0x30, 0x62, 0xCF, 0x3F, 0xA2, 0x54, 0x9E, 0x44, 0xF5, 0x8E, 0xD2, 0x40, 0x17, 0x10 }; const unsigned char pk[32] = { 0x25, 0xD1, 0xDF, 0xF9, 0x51, 0x05, 0xF5, 0x25, 0x3C, 0x40, 0x22, 0xF6, 0x28, 0xA9, 0x96, 0xAD, 0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A, 0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17 }; unsigned char aux_rand[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; const unsigned char msg[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; const unsigned char sig[64] = { 0x7E, 0xB0, 0x50, 0x97, 0x57, 0xE2, 0x46, 0xF1, 0x94, 0x49, 0x88, 0x56, 0x51, 0x61, 0x1C, 0xB9, 0x65, 0xEC, 0xC1, 0xA1, 0x87, 0xDD, 0x51, 0xB6, 0x4F, 0xDA, 0x1E, 0xDC, 0x96, 0x37, 0xD5, 0xEC, 0x97, 0x58, 0x2B, 0x9C, 0xB1, 0x3D, 0xB3, 0x93, 0x37, 0x05, 0xB3, 0x2B, 0xA9, 0x82, 0xAF, 0x5A, 0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27, 0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3 }; test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig); test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 4 */ const unsigned char pk[32] = { 0xD6, 0x9C, 0x35, 0x09, 0xBB, 0x99, 0xE4, 0x12, 0xE6, 0x8B, 0x0F, 0xE8, 0x54, 0x4E, 0x72, 0x83, 0x7D, 0xFA, 0x30, 0x74, 0x6D, 0x8B, 0xE2, 0xAA, 0x65, 0x97, 0x5F, 0x29, 0xD2, 0x2D, 0xC7, 0xB9 }; const unsigned char msg[32] = { 0x4D, 0xF3, 0xC3, 0xF6, 0x8F, 0xCC, 0x83, 0xB2, 0x7E, 0x9D, 0x42, 0xC9, 0x04, 0x31, 0xA7, 0x24, 0x99, 0xF1, 0x78, 0x75, 0xC8, 0x1A, 0x59, 0x9B, 0x56, 0x6C, 0x98, 0x89, 0xB9, 0x69, 0x67, 0x03 }; const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0x78, 0xCE, 0x56, 0x3F, 0x89, 0xA0, 0xED, 0x94, 0x14, 0xF5, 0xAA, 0x28, 0xAD, 0x0D, 0x96, 0xD6, 0x79, 0x5F, 0x9C, 0x63, 0x76, 0xAF, 0xB1, 0x54, 0x8A, 0xF6, 0x03, 0xB3, 0xEB, 0x45, 0xC9, 0xF8, 0x20, 0x7D, 0xEE, 0x10, 0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93, 0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1); } { /* Test vector 5 */ const unsigned char pk[32] = { 0xEE, 0xFD, 0xEA, 0x4C, 0xDB, 0x67, 0x77, 0x50, 0xA4, 0x20, 0xFE, 0xE8, 0x07, 0xEA, 0xCF, 0x21, 0xEB, 0x98, 0x98, 0xAE, 0x79, 0xB9, 0x76, 0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A, 0x34 }; secp256k1_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk)); } { /* Test vector 6 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0xFF, 0xF9, 0x7B, 0xD5, 0x75, 0x5E, 0xEE, 0xA4, 0x20, 0x45, 0x3A, 0x14, 0x35, 0x52, 0x35, 0xD3, 0x82, 0xF6, 0x47, 0x2F, 0x85, 0x68, 0xA1, 0x8B, 0x2F, 0x05, 0x7A, 0x14, 0x60, 0x29, 0x75, 0x56, 0x3C, 0xC2, 0x79, 0x44, 0x64, 0x0A, 0xC6, 0x07, 0xCD, 0x10, 0x7A, 0xE1, 0x09, 0x23, 0xD9, 0xEF, 0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E, 0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 7 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x1F, 0xA6, 0x2E, 0x33, 0x1E, 0xDB, 0xC2, 0x1C, 0x39, 0x47, 0x92, 0xD2, 0xAB, 0x11, 0x00, 0xA7, 0xB4, 0x32, 0xB0, 0x13, 0xDF, 0x3F, 0x6F, 0xF4, 0xF9, 0x9F, 0xCB, 0x33, 0xE0, 0xE1, 0x51, 0x5F, 0x28, 0x89, 0x0B, 0x3E, 0xDB, 0x6E, 0x71, 0x89, 0xB6, 0x30, 0x44, 0x8B, 0x51, 0x5C, 0xE4, 0xF8, 0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35, 0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 8 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, 0x96, 0x17, 0x64, 0xB3, 0xAA, 0x9B, 0x2F, 0xFC, 0xB6, 0xEF, 0x94, 0x7B, 0x68, 0x87, 0xA2, 0x26, 0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C, 0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 9 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x3D, 0xDA, 0x83, 0x28, 0xAF, 0x9C, 0x23, 0xA9, 0x4C, 0x1F, 0xEE, 0xCF, 0xD1, 0x23, 0xBA, 0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC, 0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 10 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x76, 0x15, 0xFB, 0xAF, 0x5A, 0xE2, 0x88, 0x64, 0x01, 0x3C, 0x09, 0x97, 0x42, 0xDE, 0xAD, 0xB4, 0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9, 0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 11 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x4A, 0x29, 0x8D, 0xAC, 0xAE, 0x57, 0x39, 0x5A, 0x15, 0xD0, 0x79, 0x5D, 0xDB, 0xFD, 0x1D, 0xCB, 0x56, 0x4D, 0xA8, 0x2B, 0x0F, 0x26, 0x9B, 0xC7, 0x0A, 0x74, 0xF8, 0x22, 0x04, 0x29, 0xBA, 0x1D, 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 12 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F, 0x69, 0xE8, 0x9B, 0x4C, 0x55, 0x64, 0xD0, 0x03, 0x49, 0x10, 0x6B, 0x84, 0x97, 0x78, 0x5D, 0xD7, 0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F, 0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 13 */ const unsigned char pk[32] = { 0xDF, 0xF1, 0xD7, 0x7F, 0x2A, 0x67, 0x1C, 0x5F, 0x36, 0x18, 0x37, 0x26, 0xDB, 0x23, 0x41, 0xBE, 0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8, 0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59 }; const unsigned char msg[32] = { 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E, 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0, 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89 }; const unsigned char sig[64] = { 0x6C, 0xFF, 0x5C, 0x3B, 0xA8, 0x6C, 0x69, 0xEA, 0x4B, 0x73, 0x76, 0xF3, 0x1A, 0x9B, 0xCB, 0x4F, 0x74, 0xC1, 0x97, 0x60, 0x89, 0xB2, 0xD9, 0x96, 0x3D, 0xA2, 0xE5, 0x54, 0x3E, 0x17, 0x77, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41 }; test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0); } { /* Test vector 14 */ const unsigned char pk[32] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x30 }; secp256k1_xonly_pubkey pk_parsed; /* No need to check the signature of the test vector as parsing the pubkey already fails */ CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk_parsed, pk)); } } /* Nonce function that returns constant 0 */ static int nonce_function_failing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; (void) nonce32; return 0; } /* Nonce function that sets nonce to 0 */ static int nonce_function_0(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; memset(nonce32, 0, 32); return 1; } /* Nonce function that sets nonce to 0xFF...0xFF */ static int nonce_function_overflowing(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *xonly_pk32, const unsigned char *algo16, void *data) { (void) msg32; (void) key32; (void) xonly_pk32; (void) algo16; (void) data; memset(nonce32, 0xFF, 32); return 1; } void test_schnorrsig_sign(void) { unsigned char sk[32]; secp256k1_keypair keypair; const unsigned char msg[32] = "this is a msg for a schnorrsig.."; unsigned char sig[64]; unsigned char zeros64[64] = { 0 }; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1); /* Test different nonce functions */ memset(sig, 1, sizeof(sig)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_failing, NULL) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); memset(&sig, 1, sizeof(sig)); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_0, NULL) == 0); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) == 0); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, nonce_function_overflowing, NULL) == 1); CHECK(secp256k1_memcmp_var(sig, zeros64, sizeof(sig)) != 0); } #define N_SIGS 3 /* Creates N_SIGS valid signatures and verifies them with verify and * verify_batch (TODO). Then flips some bits and checks that verification now * fails. */ void test_schnorrsig_sign_verify(void) { unsigned char sk[32]; unsigned char msg[N_SIGS][32]; unsigned char sig[N_SIGS][64]; size_t i; secp256k1_keypair keypair; secp256k1_xonly_pubkey pk; secp256k1_scalar s; secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk)); CHECK(secp256k1_keypair_xonly_pub(ctx, &pk, NULL, &keypair)); for (i = 0; i < N_SIGS; i++) { secp256k1_testrand256(msg[i]); CHECK(secp256k1_schnorrsig_sign(ctx, sig[i], msg[i], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[i], msg[i], &pk)); } { /* Flip a few bits in the signature and in the message and check that * verify and verify_batch (TODO) fail */ size_t sig_idx = secp256k1_testrand_int(N_SIGS); size_t byte_idx = secp256k1_testrand_int(32); unsigned char xorbyte = secp256k1_testrand_int(254)+1; sig[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); sig[sig_idx][byte_idx] ^= xorbyte; byte_idx = secp256k1_testrand_int(32); sig[sig_idx][32+byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); sig[sig_idx][32+byte_idx] ^= xorbyte; byte_idx = secp256k1_testrand_int(32); msg[sig_idx][byte_idx] ^= xorbyte; CHECK(!secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); msg[sig_idx][byte_idx] ^= xorbyte; /* Check that above bitflips have been reversed correctly */ CHECK(secp256k1_schnorrsig_verify(ctx, sig[sig_idx], msg[sig_idx], &pk)); } /* Test overflowing s */ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); memset(&sig[0][32], 0xFF, 32); CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); /* Test negative s */ CHECK(secp256k1_schnorrsig_sign(ctx, sig[0], msg[0], &keypair, NULL, NULL)); CHECK(secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); secp256k1_scalar_set_b32(&s, &sig[0][32], NULL); secp256k1_scalar_negate(&s, &s); secp256k1_scalar_get_b32(&sig[0][32], &s); CHECK(!secp256k1_schnorrsig_verify(ctx, sig[0], msg[0], &pk)); } #undef N_SIGS void test_schnorrsig_taproot(void) { unsigned char sk[32]; secp256k1_keypair keypair; secp256k1_xonly_pubkey internal_pk; unsigned char internal_pk_bytes[32]; secp256k1_xonly_pubkey output_pk; unsigned char output_pk_bytes[32]; unsigned char tweak[32]; int pk_parity; unsigned char msg[32]; unsigned char sig[64]; /* Create output key */ secp256k1_testrand256(sk); CHECK(secp256k1_keypair_create(ctx, &keypair, sk) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &internal_pk, NULL, &keypair) == 1); /* In actual taproot the tweak would be hash of internal_pk */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, tweak, &internal_pk) == 1); CHECK(secp256k1_keypair_xonly_tweak_add(ctx, &keypair, tweak) == 1); CHECK(secp256k1_keypair_xonly_pub(ctx, &output_pk, &pk_parity, &keypair) == 1); CHECK(secp256k1_xonly_pubkey_serialize(ctx, output_pk_bytes, &output_pk) == 1); /* Key spend */ secp256k1_testrand256(msg); CHECK(secp256k1_schnorrsig_sign(ctx, sig, msg, &keypair, NULL, NULL) == 1); /* Verify key spend */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &output_pk, output_pk_bytes) == 1); CHECK(secp256k1_schnorrsig_verify(ctx, sig, msg, &output_pk) == 1); /* Script spend */ CHECK(secp256k1_xonly_pubkey_serialize(ctx, internal_pk_bytes, &internal_pk) == 1); /* Verify script spend */ CHECK(secp256k1_xonly_pubkey_parse(ctx, &internal_pk, internal_pk_bytes) == 1); CHECK(secp256k1_xonly_pubkey_tweak_add_check(ctx, output_pk_bytes, pk_parity, &internal_pk, tweak) == 1); } void run_schnorrsig_tests(void) { int i; run_nonce_function_bip340_tests(); test_schnorrsig_api(); test_schnorrsig_sha256_tagged(); test_schnorrsig_bip_vectors(); for (i = 0; i < count; i++) { test_schnorrsig_sign(); test_schnorrsig_sign_verify(); } test_schnorrsig_taproot(); } #endif diff --git a/src/secp256k1/src/scratch.h b/src/secp256k1/src/scratch.h index bb3172a2e..9dcb7581f 100644 --- a/src/secp256k1/src/scratch.h +++ b/src/secp256k1/src/scratch.h @@ -1,42 +1,42 @@ /*********************************************************************** * Copyright (c) 2017 Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_SCRATCH_ -#define _SECP256K1_SCRATCH_ +#ifndef SECP256K1_SCRATCH_H +#define SECP256K1_SCRATCH_H /* The typedef is used internally; the struct name is used in the public API * (where it is exposed as a different typedef) */ typedef struct secp256k1_scratch_space_struct { /** guard against interpreting this object as other types */ unsigned char magic[8]; /** actual allocated data */ void *data; /** amount that has been allocated (i.e. `data + offset` is the next * available pointer) */ size_t alloc_size; /** maximum size available to allocate */ size_t max_size; } secp256k1_scratch; static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t max_size); static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch); /** Returns an opaque object used to "checkpoint" a scratch space. Used * with `secp256k1_scratch_apply_checkpoint` to undo allocations. */ static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch); /** Applies a check point received from `secp256k1_scratch_checkpoint`, * undoing all allocations since that point. */ static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint); /** Returns the maximum allocation the scratch space will allow */ static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t n_objects); /** Returns a pointer into the most recently allocated frame, or NULL if there is insufficient available space */ static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t n); #endif diff --git a/src/secp256k1/src/scratch_impl.h b/src/secp256k1/src/scratch_impl.h index a2b78f80e..688e18eb6 100644 --- a/src/secp256k1/src/scratch_impl.h +++ b/src/secp256k1/src/scratch_impl.h @@ -1,99 +1,99 @@ /*********************************************************************** * Copyright (c) 2017 Andrew Poelstra * * Distributed under the MIT software license, see the accompanying * * file COPYING or https://www.opensource.org/licenses/mit-license.php.* ***********************************************************************/ -#ifndef _SECP256K1_SCRATCH_IMPL_H_ -#define _SECP256K1_SCRATCH_IMPL_H_ +#ifndef SECP256K1_SCRATCH_IMPL_H +#define SECP256K1_SCRATCH_IMPL_H #include "util.h" #include "scratch.h" static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) { const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch)); void *alloc = checked_malloc(error_callback, base_alloc + size); secp256k1_scratch* ret = (secp256k1_scratch *)alloc; if (ret != NULL) { memset(ret, 0, sizeof(*ret)); memcpy(ret->magic, "scratch", 8); ret->data = (void *) ((char *) alloc + base_alloc); ret->max_size = size; } return ret; } static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) { if (scratch != NULL) { VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return; } memset(scratch->magic, 0, sizeof(scratch->magic)); free(scratch); } } static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return 0; } return scratch->alloc_size; } static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return; } if (checkpoint > scratch->alloc_size) { secp256k1_callback_call(error_callback, "invalid checkpoint"); return; } scratch->alloc_size = checkpoint; } static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) { if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return 0; } /* Ensure that multiplication will not wrap around */ if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { return 0; } if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { return 0; } return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); } static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) { void *ret; size_t rounded_size; rounded_size = ROUND_TO_ALIGN(size); /* Check that rounding did not wrap around */ if (rounded_size < size) { return NULL; } size = rounded_size; if (secp256k1_memcmp_var(scratch->magic, "scratch", 8) != 0) { secp256k1_callback_call(error_callback, "invalid scratch space"); return NULL; } if (size > scratch->max_size - scratch->alloc_size) { return NULL; } ret = (void *) ((char *) scratch->data + scratch->alloc_size); memset(ret, 0, size); scratch->alloc_size += size; return ret; } #endif