Skip to content

Commit

Permalink
Expose API for constant time point multiplication
Browse files Browse the repository at this point in the history
  • Loading branch information
apoelstra committed May 15, 2015
1 parent 41f384e commit 6a7c13b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
18 changes: 18 additions & 0 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,24 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);


/** Do an ellitic curve scalar multiplication in constant time.
* Returns: 1: exponentiation was successful
* -1: scalar was zero (cannot serialize output point)
* -2: scalar overflow
* -3: invalid input point
* In: scalar: a 32-byte scalar with which to multiple the point
* In/Out: point: pointer to 33 or 65 byte array containing an EC point
* which will be updated in place
* pointlen: length of the point array, which will be updated by
* the multiplication
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_point_multiply(
unsigned char *point,
int *pointlen,
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
* 0: secret key is invalid
Expand Down
26 changes: 26 additions & 0 deletions src/secp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ int secp256k1_ecdsa_recover_compact(const secp256k1_context_t* ctx, const unsign
return ret;
}

int secp256k1_point_multiply(unsigned char *point, int *pointlen, const unsigned char *scalar) {
int ret = 0;
int overflow = 0;
secp256k1_gej_t res;
secp256k1_ge_t pt;
secp256k1_scalar_t s;
DEBUG_CHECK(point != NULL);
DEBUG_CHECK(pointlen != NULL);
DEBUG_CHECK(scalar != NULL);

if (secp256k1_eckey_pubkey_parse(&pt, point, *pointlen)) {
secp256k1_scalar_set_b32(&s, scalar, &overflow);
if (overflow) {
ret = -2;
} else {
secp256k1_ecdh_point_multiply(&res, &pt, &s);
secp256k1_ge_set_gej(&pt, &res);
ret = secp256k1_eckey_pubkey_serialize(&pt, point, pointlen, *pointlen <= 33);
}
} else {
ret = -3;
}
secp256k1_scalar_clear(&s);
return ret;
}

int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) {
secp256k1_scalar_t sec;
int ret;
Expand Down
46 changes: 46 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,51 @@ void run_ecdh_tests(void) {
ecdh_commutativity();
}

void run_ecdh_api_tests(void) {
const unsigned char scalar[] = {0x49, 0x68, 0xd5, 0x24, 0x2a, 0xbf, 0x9b, 0x7a,
0x46, 0x6a, 0xbb, 0xcf, 0x34, 0xb1, 0x1b, 0x6d,
0xcd, 0x83, 0xd3, 0x07, 0x82, 0x7b, 0xed, 0x62,
0x05, 0xfa, 0xd0, 0xce, 0x18, 0xfa, 0xe6, 0x3b};
const unsigned char expected_uncomp[] = {
0x04,
/* x */
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd,
0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb,
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f,
/* y */
0x5d, 0x19, 0x5d, 0x20, 0xe1, 0x91, 0xbf, 0x7f,
0x1b, 0xe3, 0xe5, 0x5f, 0x56, 0xa8, 0x01, 0x96,
0x60, 0x71, 0xad, 0x01, 0xf1, 0x46, 0x2f, 0x66,
0xc9, 0x97, 0xfa, 0x94, 0xdb, 0x85, 0x84, 0x35
};
const unsigned char expected_comp[] = {
/* y */
0x03,
/* x */
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd,
0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb,
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f
};
unsigned char point[65];
int pointlen = sizeof(point);
secp256k1_ge_t gen = secp256k1_ge_const_g;
int i;
/* uncompressed */
secp256k1_eckey_pubkey_serialize(&gen, point, &pointlen, 0);
for (i = 0; i < 100; ++i) {
CHECK(secp256k1_point_multiply(point, &pointlen, scalar) == 1);
}
CHECK(memcmp(point, expected_uncomp, 65) == 0);
/* compressed */
secp256k1_eckey_pubkey_serialize(&gen, point, &pointlen, 1);
for (i = 0; i < 100; ++i) {
CHECK(secp256k1_point_multiply(point, &pointlen, scalar) == 1);
}
CHECK(memcmp(point, expected_comp, 33) == 0);
}

/***** ECMULT TESTS *****/

void run_ecmult_chain(void) {
Expand Down Expand Up @@ -2299,6 +2344,7 @@ int main(int argc, char **argv) {

/* ecdh tests */
run_ecdh_tests();
run_ecdh_api_tests();

/* ecdsa tests */
run_random_pubkeys();
Expand Down

0 comments on commit 6a7c13b

Please sign in to comment.