diff --git a/include/secp256k1.h b/include/secp256k1.h index 3c53c8ffbae..a6a1ae1356c 100644 --- a/include/secp256k1.h +++ b/include/secp256k1.h @@ -137,6 +137,9 @@ typedef int (*secp256k1_nonce_function_t)( # define SECP256K1_CONTEXT_VERIFY (1 << 0) # define SECP256K1_CONTEXT_SIGN (1 << 1) +/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ +# define SECP256K1_EC_COMPRESSED (1 << 0) + /** Create a secp256k1 context object. * * Returns: a newly created context object. @@ -243,14 +246,15 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( * size. * In: pubkey: a pointer to a secp256k1_pubkey_t containing an initialized * public key. - * compressed: whether to serialize in compressed format. + * flags: SECP256K1_EC_COMPRESSED if serialization should be in + * compressed format. */ int secp256k1_ec_pubkey_serialize( const secp256k1_context_t* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey_t* pubkey, - int compressed + unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Parse a DER ECDSA signature. @@ -396,7 +400,8 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( * privkeylen: Pointer to an int where the length of the private key in * privkey will be stored. * In: seckey: pointer to a 32-byte secret key to export. - * compressed: whether the key should be exported in compressed format. + * flags: SECP256K1_EC_COMPRESSED if the key should be exported in + * compressed format. * * This function is purely meant for compatibility with applications that * require BER encoded keys. When working with secp256k1-specific code, the @@ -410,7 +415,7 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export( unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, - int compressed + unsigned int flags ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Import a private key in DER format. diff --git a/src/bench_recover.c b/src/bench_recover.c index f59b0a2712d..6fb66226b54 100644 --- a/src/bench_recover.c +++ b/src/bench_recover.c @@ -27,7 +27,7 @@ void bench_recover(void* arg) { secp256k1_ecdsa_recoverable_signature_t sig; CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, 1)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); for (j = 0; j < 32; j++) { data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ data->msg[j] = data->sig[j]; /* Move former R to message. */ diff --git a/src/bench_schnorr_verify.c b/src/bench_schnorr_verify.c index 251a1741926..4487cda7ac7 100644 --- a/src/bench_schnorr_verify.c +++ b/src/bench_schnorr_verify.c @@ -37,7 +37,7 @@ static void benchmark_schnorr_init(void* arg) { secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); data->sigs[k].pubkeylen = 33; CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, 1)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); } } diff --git a/src/bench_verify.c b/src/bench_verify.c index 99fe3a5b825..296385fffbb 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -54,7 +54,7 @@ int main(void) { CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); - CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, 1) == 1); + CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); diff --git a/src/eckey.h b/src/eckey.h index 1357013f1b9..bf8e8cf5363 100644 --- a/src/eckey.h +++ b/src/eckey.h @@ -15,10 +15,10 @@ #include "ecmult_gen.h" static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, size_t size); -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, size_t *size, int compressed); +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, size_t *size, unsigned int flags); static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, size_t privkeylen); -static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar_t *key, int compressed); +static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar_t *key, unsigned int flags); static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak); static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context_t *ctx, secp256k1_ge_t *key, const secp256k1_scalar_t *tweak); diff --git a/src/eckey_impl.h b/src/eckey_impl.h index 18935719013..d46120600f1 100644 --- a/src/eckey_impl.h +++ b/src/eckey_impl.h @@ -33,14 +33,14 @@ static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned cha } } -static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, size_t *size, int compressed) { +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, size_t *size, unsigned int flags) { if (secp256k1_ge_is_infinity(elem)) { return 0; } secp256k1_fe_normalize_var(&elem->x); secp256k1_fe_normalize_var(&elem->y); secp256k1_fe_get_b32(&pub[1], &elem->x); - if (compressed) { + if (flags & SECP256K1_EC_COMPRESSED) { *size = 33; pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); } else { @@ -94,13 +94,13 @@ static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned return !overflow; } -static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar_t *key, int compressed) { +static int secp256k1_eckey_privkey_serialize(const secp256k1_ecmult_gen_context_t *ctx, unsigned char *privkey, size_t *privkeylen, const secp256k1_scalar_t *key, unsigned int flags) { secp256k1_gej_t rp; secp256k1_ge_t r; size_t pubkeylen = 0; secp256k1_ecmult_gen(ctx, &rp, key); secp256k1_ge_set_gej(&r, &rp); - if (compressed) { + if (flags & SECP256K1_EC_COMPRESSED) { static const unsigned char begin[] = { 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 }; diff --git a/src/modules/ecdh/tests_impl.h b/src/modules/ecdh/tests_impl.h index 84f95ea65fc..b2f37682c9c 100644 --- a/src/modules/ecdh/tests_impl.h +++ b/src/modules/ecdh/tests_impl.h @@ -31,7 +31,7 @@ void test_ecdh_generator_basepoint(void) { CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); /* compute "explicitly" */ CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); - CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], 1) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); CHECK(point_ser_len == sizeof(point_ser)); secp256k1_sha256_initialize(&sha); secp256k1_sha256_write(&sha, point_ser, point_ser_len); diff --git a/src/secp256k1.c b/src/secp256k1.c index b54b525914a..0d94f082338 100644 --- a/src/secp256k1.c +++ b/src/secp256k1.c @@ -154,12 +154,12 @@ int secp256k1_ec_pubkey_parse(const secp256k1_context_t* ctx, secp256k1_pubkey_t return 1; } -int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey_t* pubkey, int compressed) { +int secp256k1_ec_pubkey_serialize(const secp256k1_context_t* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey_t* pubkey, unsigned int flags) { secp256k1_ge_t Q; (void)ctx; return (secp256k1_pubkey_load(ctx, &Q, pubkey) && - secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, compressed)); + secp256k1_eckey_pubkey_serialize(&Q, output, outputlen, flags)); } static void secp256k1_ecdsa_signature_load(const secp256k1_context_t* ctx, secp256k1_scalar_t* r, secp256k1_scalar_t* s, const secp256k1_ecdsa_signature_t* sig) { @@ -438,7 +438,7 @@ int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context_t* ctx, secp256k1_pubk return ret; } -int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, int compressed) { +int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *seckey, unsigned int flags) { secp256k1_scalar_t key; int ret = 0; VERIFY_CHECK(ctx != NULL); @@ -448,7 +448,7 @@ int secp256k1_ec_privkey_export(const secp256k1_context_t* ctx, unsigned char *p ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); secp256k1_scalar_set_b32(&key, seckey, NULL); - ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, compressed); + ret = secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, privkeylen, &key, flags); secp256k1_scalar_clear(&key); return ret; } diff --git a/src/tests.c b/src/tests.c index 342cb07b42e..8bdff02ba25 100644 --- a/src/tests.c +++ b/src/tests.c @@ -1871,7 +1871,7 @@ void test_ecdsa_end_to_end(void) { CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); /* Verify private key import and export. */ - CHECK(secp256k1_ec_privkey_export(ctx, seckey, &seckeylen, privkey, secp256k1_rand32() % 2) == 1); + CHECK(secp256k1_ec_privkey_export(ctx, seckey, &seckeylen, privkey, (secp256k1_rand32() % 2) == 1) ? SECP256K1_EC_COMPRESSED : 0); CHECK(secp256k1_ec_privkey_import(ctx, privkey2, seckey, seckeylen) == 1); CHECK(memcmp(privkey, privkey2, 32) == 0); @@ -1979,7 +1979,7 @@ void test_random_pubkeys(void) { size_t size = len; firstb = in[0]; /* If the pubkey can be parsed, it should round-trip... */ - CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, (len == 33) ? SECP256K1_EC_COMPRESSED : 0)); CHECK(size == len); CHECK(memcmp(&in[1], &out[1], len-1) == 0); /* ... except for the type of hybrid inputs. */ @@ -2156,7 +2156,7 @@ void test_ecdsa_edge_cases(void) { size_t outlen = 300; CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, 0)); outlen = 300; - CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, 1)); + CHECK(!secp256k1_ec_privkey_export(ctx, privkey, &outlen, seckey, SECP256K1_EC_COMPRESSED)); } } @@ -2171,7 +2171,7 @@ EC_KEY *get_openssl_key(const secp256k1_scalar_t *key) { const unsigned char* pbegin = privkey; int compr = secp256k1_rand32() & 1; EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); - CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr)); + CHECK(secp256k1_eckey_privkey_serialize(&ctx->ecmult_gen_ctx, privkey, &privkeylen, key, compr ? SECP256K1_EC_COMPRESSED : 0)); CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); CHECK(EC_KEY_check_key(ec_key)); return ec_key;