Merge #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
This commit is contained in:
commit
119949232a
|
@ -487,6 +487,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
|
||||||
const unsigned char *seckey
|
const unsigned char *seckey
|
||||||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||||
|
|
||||||
|
/** Negates a private key in place.
|
||||||
|
*
|
||||||
|
* Returns: 1 always
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate(
|
||||||
|
const secp256k1_context* ctx,
|
||||||
|
unsigned char *seckey
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||||
|
|
||||||
|
/** Negates a public key in place.
|
||||||
|
*
|
||||||
|
* Returns: 1 always
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* In/Out: pubkey: pointer to the public key to be negated (cannot be NULL)
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate(
|
||||||
|
const secp256k1_context* ctx,
|
||||||
|
secp256k1_pubkey *pubkey
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
|
||||||
|
|
||||||
/** Tweak a private key by adding tweak to it.
|
/** Tweak a private key by adding tweak to it.
|
||||||
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
* Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for
|
||||||
* uniformly random 32-byte arrays, or if the resulting private key
|
* uniformly random 32-byte arrays, or if the resulting private key
|
||||||
|
|
|
@ -424,6 +424,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) {
|
||||||
|
secp256k1_scalar sec;
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(seckey != NULL);
|
||||||
|
|
||||||
|
secp256k1_scalar_set_b32(&sec, seckey, NULL);
|
||||||
|
secp256k1_scalar_negate(&sec, &sec);
|
||||||
|
secp256k1_scalar_get_b32(seckey, &sec);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) {
|
||||||
|
int ret = 0;
|
||||||
|
secp256k1_ge p;
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(pubkey != NULL);
|
||||||
|
|
||||||
|
ret = secp256k1_pubkey_load(ctx, &p, pubkey);
|
||||||
|
memset(pubkey, 0, sizeof(*pubkey));
|
||||||
|
if (ret) {
|
||||||
|
secp256k1_ge_neg(&p, &p);
|
||||||
|
secp256k1_pubkey_save(pubkey, &p);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) {
|
||||||
secp256k1_scalar term;
|
secp256k1_scalar term;
|
||||||
secp256k1_scalar sec;
|
secp256k1_scalar sec;
|
||||||
|
|
26
src/tests.c
26
src/tests.c
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -135,6 +136,7 @@ void random_scalar_order(secp256k1_scalar *num) {
|
||||||
|
|
||||||
void run_context_tests(void) {
|
void run_context_tests(void) {
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
|
secp256k1_pubkey zero_pubkey;
|
||||||
secp256k1_ecdsa_signature sig;
|
secp256k1_ecdsa_signature sig;
|
||||||
unsigned char ctmp[32];
|
unsigned char ctmp[32];
|
||||||
int32_t ecount;
|
int32_t ecount;
|
||||||
|
@ -149,6 +151,8 @@ void run_context_tests(void) {
|
||||||
secp256k1_scalar msg, key, nonce;
|
secp256k1_scalar msg, key, nonce;
|
||||||
secp256k1_scalar sigr, sigs;
|
secp256k1_scalar sigr, sigs;
|
||||||
|
|
||||||
|
memset(&zero_pubkey, 0, sizeof(zero_pubkey));
|
||||||
|
|
||||||
ecount = 0;
|
ecount = 0;
|
||||||
ecount2 = 10;
|
ecount2 = 10;
|
||||||
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount);
|
||||||
|
@ -201,12 +205,20 @@ void run_context_tests(void) {
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
|
CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0);
|
||||||
CHECK(ecount2 == 13);
|
CHECK(ecount2 == 13);
|
||||||
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1);
|
||||||
CHECK(ecount == 2);
|
CHECK(ecount == 2);
|
||||||
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
|
CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1);
|
||||||
|
CHECK(ecount == 2);
|
||||||
|
CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0);
|
||||||
|
CHECK(ecount2 == 14);
|
||||||
|
CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0);
|
||||||
CHECK(ecount == 3);
|
CHECK(ecount == 3);
|
||||||
|
CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1);
|
||||||
|
CHECK(ecount == 3);
|
||||||
|
CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0);
|
||||||
|
CHECK(ecount == 4);
|
||||||
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
CHECK(secp256k1_context_randomize(sign, NULL) == 1);
|
||||||
CHECK(ecount2 == 13);
|
CHECK(ecount2 == 14);
|
||||||
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
secp256k1_context_set_illegal_callback(vrfy, NULL, NULL);
|
||||||
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
secp256k1_context_set_illegal_callback(sign, NULL, NULL);
|
||||||
|
|
||||||
|
@ -3436,6 +3448,7 @@ void test_ecdsa_end_to_end(void) {
|
||||||
unsigned char pubkeyc[65];
|
unsigned char pubkeyc[65];
|
||||||
size_t pubkeyclen = 65;
|
size_t pubkeyclen = 65;
|
||||||
secp256k1_pubkey pubkey;
|
secp256k1_pubkey pubkey;
|
||||||
|
secp256k1_pubkey pubkey_tmp;
|
||||||
unsigned char seckey[300];
|
unsigned char seckey[300];
|
||||||
size_t seckeylen = 300;
|
size_t seckeylen = 300;
|
||||||
|
|
||||||
|
@ -3457,6 +3470,13 @@ void test_ecdsa_end_to_end(void) {
|
||||||
memset(&pubkey, 0, sizeof(pubkey));
|
memset(&pubkey, 0, sizeof(pubkey));
|
||||||
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
|
CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1);
|
||||||
|
|
||||||
|
/* Verify negation changes the key and changes it back */
|
||||||
|
memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey));
|
||||||
|
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
|
||||||
|
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0);
|
||||||
|
CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1);
|
||||||
|
CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0);
|
||||||
|
|
||||||
/* Verify private key import and export. */
|
/* Verify private key import and export. */
|
||||||
CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));
|
CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1));
|
||||||
CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
|
CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1);
|
||||||
|
|
Loading…
Reference in New Issue