Skip to content

Commit

Permalink
Demo code for x-only ECDH
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdettman committed Jul 1, 2015
1 parent 48dc8e3 commit 6e6a1d6
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
bench_inv
bench_ecdh
bench_ecdh_xo
bench_sign
bench_verify
bench_recover
Expand Down
6 changes: 5 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ libsecp256k1_la_LIBADD = $(SECP_LIBS)

noinst_PROGRAMS =
if USE_BENCHMARK
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal bench_ecdh
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal bench_ecdh bench_ecdh_xo
bench_verify_SOURCES = src/bench_verify.c
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_verify_LDFLAGS = -static
Expand All @@ -69,6 +69,10 @@ bench_ecdh_SOURCES = src/bench_ecdh.c
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_ecdh_LDFLAGS = -static
bench_ecdh_CPPFLAGS = $(SECP_INCLUDES)
bench_ecdh_xo_SOURCES = src/bench_ecdh_xo.c
bench_ecdh_xo_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_ecdh_xo_LDFLAGS = -static
bench_ecdh_xo_CPPFLAGS = $(SECP_INCLUDES)
endif

if USE_TESTS
Expand Down
6 changes: 6 additions & 0 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh_xo(
unsigned char *result,
const unsigned char *x,
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
50 changes: 50 additions & 0 deletions src/bench_ecdh_xo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**********************************************************************
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#include <string.h>

#include "include/secp256k1.h"
#include "util.h"
#include "bench.h"

typedef struct {
unsigned char point[33];
int pointlen;
unsigned char scalar[32];
} bench_multiply_t;

static void bench_multiply_setup(void* arg) {
int i;
bench_multiply_t *data = (bench_multiply_t*)arg;
const unsigned char point[] = {
0x03,
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
};

for (i = 0; i < 32; i++) data->scalar[i] = i + 1;
data->pointlen = sizeof(point);
memcpy(data->point, point, data->pointlen);
}

static void bench_multiply(void* arg) {
int i;
unsigned char res[32];
bench_multiply_t *data = (bench_multiply_t*)arg;

for (i = 0; i < 20000; i++) {
CHECK(secp256k1_ecdh_xo(res, data->point+1, data->scalar) == 1);
}
}

int main(void) {
bench_multiply_t data;

run_benchmark("ecdh_mult_xo", bench_multiply, bench_multiply_setup, NULL, &data, 10, 20000);
return 0;
}
2 changes: 2 additions & 0 deletions src/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, cons
* for Y. Return value indicates whether the result is valid. */
static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd);

static int secp256k1_ge_set_xo_iso_var(secp256k1_ge_t *r, secp256k1_fe_t *rk, const secp256k1_fe_t *x);

/** Check whether a group element is the point at infinity. */
static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a);

Expand Down
15 changes: 15 additions & 0 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,21 @@ static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, i
return 1;
}

static int secp256k1_ge_set_xo_iso_var(secp256k1_ge_t *r, secp256k1_fe_t *rk, const secp256k1_fe_t *x) {
secp256k1_fe_t t;
secp256k1_fe_sqr(&t, x);
secp256k1_fe_mul(&t, &t, x);
secp256k1_fe_set_int(rk, 7);
secp256k1_fe_add(rk, &t); /* K = X^3 + 7 (2) */

/* TODO Jacobi symbol test to make sure K is a square */

r->infinity = 0;
secp256k1_fe_mul(&r->x, rk, x); /* r->x = K*X (1) */
secp256k1_fe_sqr(&r->y, rk); /* r->y = K^2 (1) */
return 1;
}

static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
r->infinity = a->infinity;
r->x = a->x;
Expand Down
41 changes: 41 additions & 0 deletions src/secp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,47 @@ int secp256k1_ecdh(unsigned char *result, unsigned char *point, int *pointlen, c
return ret;
}

int secp256k1_ecdh_xo(unsigned char *result, const unsigned char *x, const unsigned char *scalar) {
int ret = 0;
int overflow = 0;
secp256k1_fe_t k, t;
secp256k1_gej_t res;
secp256k1_ge_t pt;
secp256k1_scalar_t s;
unsigned char input[32];
secp256k1_sha256_t sha;
DEBUG_CHECK(result != NULL);
DEBUG_CHECK(x != NULL);
DEBUG_CHECK(scalar != NULL);

secp256k1_scalar_set_b32(&s, scalar, &overflow);
if (secp256k1_scalar_is_zero(&s)) {
ret = -1;
} else if (overflow) {
ret = -2;
} else if (secp256k1_fe_set_b32(&t, x) && secp256k1_ge_set_xo_iso_var(&pt, &k, &t)) {
secp256k1_point_multiply(&res, &pt, &s);
if (!res.infinity) {
secp256k1_fe_sqr(&t, &res.z);
secp256k1_fe_mul(&t, &t, &k);
secp256k1_fe_inv(&k, &t);
secp256k1_fe_mul(&t, &res.x, &k);
secp256k1_fe_normalize(&t);

/* secp256k1_fe_get_b32(result, &t); */
secp256k1_fe_get_b32(input, &t);
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, input, sizeof(input));
secp256k1_sha256_finalize(&sha, result);
ret = 1;
}
} 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
14 changes: 14 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,19 @@ void ecdh_generator_basepoint(void) {
secp256k1_sha256_finalize(&sha, output_ser);
/* compare */
CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0);

memset(output_ecdh, 0, sizeof(output_ecdh));
memset(output_ser, 0, sizeof(output_ser));

/* compute using x-only ECDH function */
secp256k1_eckey_pubkey_serialize(&gen, point, &pointlen, 1);
CHECK(secp256k1_ecdh_xo(output_ecdh, point+1, s_b32) == 1);
/* compute "explicitly" */
secp256k1_sha256_initialize(&sha);
secp256k1_sha256_write(&sha, point2+1, sizeof(point2)-1);
secp256k1_sha256_finalize(&sha, output_ser);
/* compare */
CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0);
}
}

Expand Down Expand Up @@ -2503,6 +2516,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 6e6a1d6

Please sign in to comment.