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 Jun 27, 2015
1 parent 2896833 commit e917717
Show file tree
Hide file tree
Showing 8 changed files with 116 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
5 changes: 5 additions & 0 deletions include/secp256k1.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_point_multiply(
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

SECP256K1_WARN_UNUSED_RESULT int secp256k1_xo_multiply(
unsigned char *xo,
const unsigned char *scalar
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
* 0: secret key is invalid
Expand Down
49 changes: 49 additions & 0 deletions src/bench_ecdh_xo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**********************************************************************
* 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;
bench_multiply_t *data = (bench_multiply_t*)arg;

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

int main(void) {
bench_multiply_t data;

run_benchmark("ecdh_xo_mult", 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
33 changes: 33 additions & 0 deletions src/secp256k1.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,39 @@ int secp256k1_point_multiply(unsigned char *point, int *pointlen, const unsigned
return ret;
}

int secp256k1_xo_multiply(unsigned char *xo, 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;
DEBUG_CHECK(xo != NULL);
DEBUG_CHECK(scalar != NULL);

secp256k1_scalar_set_b32(&s, scalar, &overflow);
if (overflow) {
ret = -2;
} else {
if (secp256k1_fe_set_b32(&t, xo) && secp256k1_ge_set_xo_iso_var(&pt, &k, &t)) {
secp256k1_ecdh_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(xo, &t);
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
6 changes: 6 additions & 0 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,12 @@ void run_ecdh_api_tests(void) {
CHECK(secp256k1_point_multiply(point, &pointlen, scalar) == 1);
}
CHECK(memcmp(point, expected_comp, 33) == 0);
/* x-only */
secp256k1_eckey_pubkey_serialize(&gen, point, &pointlen, 1);
for (i = 0; i < 100; ++i) {
CHECK(secp256k1_xo_multiply(point+1, scalar) == 1);
}
CHECK(memcmp(point+1, expected_comp+1, 32) == 0);
}

/***** ECMULT TESTS *****/
Expand Down

0 comments on commit e917717

Please sign in to comment.