Skip to content

Commit 1199492

Browse files
committed
Merge bitcoin#408: Add secp256k1_ec_pubkey_negate and secp256k1_ec_privkey_negate
8e48aa6 Add `secp256k1_ec_pubkey_negate` and `secp256k1_ec_privkey_negate` (Andrew Poelstra) Tree-SHA512: 28eeca0b04001958ad86b3c802e33a13273514e9e9802d5b358fd577dc95421a2cffb5591716bea10300717f742f0941c465b9df71dbb4c66d174c643887e06f
2 parents 6af0871 + 8e48aa6 commit 1199492

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

include/secp256k1.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
487487
const unsigned char *seckey
488488
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
489489

490+
/** Negates a private key in place.
491+
*
492+
* Returns: 1 always
493+
* Args: ctx: pointer to a context object
494+
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
495+
*/
496+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
497+
const secp256k1_context* ctx,
498+
unsigned char *seckey
499+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
500+
501+
/** Negates a public key in place.
502+
*
503+
* Returns: 1 always
504+
* Args: ctx: pointer to a context object
505+
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
506+
*/
507+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
508+
const secp256k1_context* ctx,
509+
secp256k1_pubkey *pubkey
510+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
511+
490512
/** Tweak a private key by adding tweak to it.
491513
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
492514
* uniformly random 32-byte arrays, or if the resulting private key

src/secp256k1.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
424424
return ret;
425425
}
426426

427+
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) {
428+
secp256k1_scalar sec;
429+
VERIFY_CHECK(ctx != NULL);
430+
ARG_CHECK(seckey != NULL);
431+
432+
secp256k1_scalar_set_b32(&sec, seckey, NULL);
433+
secp256k1_scalar_negate(&sec, &sec);
434+
secp256k1_scalar_get_b32(seckey, &sec);
435+
436+
return 1;
437+
}
438+
439+
int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) {
440+
int ret = 0;
441+
secp256k1_ge p;
442+
VERIFY_CHECK(ctx != NULL);
443+
ARG_CHECK(pubkey != NULL);
444+
445+
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
446+
memset(pubkey, 0, sizeof(*pubkey));
447+
if (ret) {
448+
secp256k1_ge_neg(&p, &p);
449+
secp256k1_pubkey_save(pubkey, &p);
450+
}
451+
return ret;
452+
}
453+
427454
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
428455
secp256k1_scalar term;
429456
secp256k1_scalar sec;

src/tests.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <stdio.h>
1212
#include <stdlib.h>
13+
#include <string.h>
1314

1415
#include <time.h>
1516

@@ -135,6 +136,7 @@ void random_scalar_order(secp256k1_scalar *num) {
135136

136137
void run_context_tests(void) {
137138
secp256k1_pubkey pubkey;
139+
secp256k1_pubkey zero_pubkey;
138140
secp256k1_ecdsa_signature sig;
139141
unsigned char ctmp[32];
140142
int32_t ecount;
@@ -149,6 +151,8 @@ void run_context_tests(void) {
149151
secp256k1_scalar msg, key, nonce;
150152
secp256k1_scalar sigr, sigs;
151153

154+
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
155+
152156
ecount = 0;
153157
ecount2 = 10;
154158
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
@@ -201,12 +205,20 @@ void run_context_tests(void) {
201205
CHECK(ecount == 2);
202206
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
203207
CHECK(ecount2 == 13);
204-
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
208+
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
205209
CHECK(ecount == 2);
206-
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
210+
CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
211+
CHECK(ecount == 2);
212+
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
213+
CHECK(ecount2 == 14);
214+
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
215+
CHECK(ecount == 3);
216+
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
207217
CHECK(ecount == 3);
218+
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
219+
CHECK(ecount == 4);
208220
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
209-
CHECK(ecount2 == 13);
221+
CHECK(ecount2 == 14);
210222
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
211223
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
212224

@@ -3436,6 +3448,7 @@ void test_ecdsa_end_to_end(void) {
34363448
unsigned char pubkeyc[65];
34373449
size_t pubkeyclen = 65;
34383450
secp256k1_pubkey pubkey;
3451+
secp256k1_pubkey pubkey_tmp;
34393452
unsigned char seckey[300];
34403453
size_t seckeylen = 300;
34413454

@@ -3457,6 +3470,13 @@ void test_ecdsa_end_to_end(void) {
34573470
memset(&pubkey, 0, sizeof(pubkey));
34583471
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
34593472

3473+
/* Verify negation changes the key and changes it back */
3474+
memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey));
3475+
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
3476+
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0);
3477+
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
3478+
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0);
3479+
34603480
/* Verify private key import and export. */
34613481
CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));
34623482
CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);

0 commit comments

Comments
 (0)