Skip to content

Commit e917717

Browse files
committed
Demo code for x-only ECDH
1 parent 2896833 commit e917717

File tree

8 files changed

+116
-1
lines changed

8 files changed

+116
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
bench_inv
22
bench_ecdh
3+
bench_ecdh_xo
34
bench_sign
45
bench_verify
56
bench_recover

Makefile.am

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ libsecp256k1_la_LIBADD = $(SECP_LIBS)
5151

5252
noinst_PROGRAMS =
5353
if USE_BENCHMARK
54-
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal bench_ecdh
54+
noinst_PROGRAMS += bench_verify bench_recover bench_sign bench_internal bench_ecdh bench_ecdh_xo
5555
bench_verify_SOURCES = src/bench_verify.c
5656
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
5757
bench_verify_LDFLAGS = -static
@@ -69,6 +69,10 @@ bench_ecdh_SOURCES = src/bench_ecdh.c
6969
bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS)
7070
bench_ecdh_LDFLAGS = -static
7171
bench_ecdh_CPPFLAGS = $(SECP_INCLUDES)
72+
bench_ecdh_xo_SOURCES = src/bench_ecdh_xo.c
73+
bench_ecdh_xo_LDADD = libsecp256k1.la $(SECP_LIBS)
74+
bench_ecdh_xo_LDFLAGS = -static
75+
bench_ecdh_xo_CPPFLAGS = $(SECP_INCLUDES)
7276
endif
7377

7478
if USE_TESTS

include/secp256k1.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ SECP256K1_WARN_UNUSED_RESULT int secp256k1_point_multiply(
235235
const unsigned char *scalar
236236
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
237237

238+
SECP256K1_WARN_UNUSED_RESULT int secp256k1_xo_multiply(
239+
unsigned char *xo,
240+
const unsigned char *scalar
241+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
242+
238243
/** Verify an ECDSA secret key.
239244
* Returns: 1: secret key is valid
240245
* 0: secret key is invalid

src/bench_ecdh_xo.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**********************************************************************
2+
* Copyright (c) 2015 Pieter Wuille, Andrew Poelstra *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5+
**********************************************************************/
6+
7+
#include <string.h>
8+
9+
#include "include/secp256k1.h"
10+
#include "util.h"
11+
#include "bench.h"
12+
13+
typedef struct {
14+
unsigned char point[33];
15+
int pointlen;
16+
unsigned char scalar[32];
17+
} bench_multiply_t;
18+
19+
static void bench_multiply_setup(void* arg) {
20+
int i;
21+
bench_multiply_t *data = (bench_multiply_t*)arg;
22+
const unsigned char point[] = {
23+
0x03,
24+
0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06,
25+
0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd,
26+
0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb,
27+
0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f
28+
};
29+
30+
for (i = 0; i < 32; i++) data->scalar[i] = i + 1;
31+
data->pointlen = sizeof(point);
32+
memcpy(data->point, point, data->pointlen);
33+
}
34+
35+
static void bench_multiply(void* arg) {
36+
int i;
37+
bench_multiply_t *data = (bench_multiply_t*)arg;
38+
39+
for (i = 0; i < 20000; i++) {
40+
CHECK(secp256k1_xo_multiply(data->point+1, data->scalar) == 1);
41+
}
42+
}
43+
44+
int main(void) {
45+
bench_multiply_t data;
46+
47+
run_benchmark("ecdh_xo_mult", bench_multiply, bench_multiply_setup, NULL, &data, 10, 20000);
48+
return 0;
49+
}

src/group.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ static void secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, cons
4848
* for Y. Return value indicates whether the result is valid. */
4949
static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd);
5050

51+
static int secp256k1_ge_set_xo_iso_var(secp256k1_ge_t *r, secp256k1_fe_t *rk, const secp256k1_fe_t *x);
52+
5153
/** Check whether a group element is the point at infinity. */
5254
static int secp256k1_ge_is_infinity(const secp256k1_ge_t *a);
5355

src/group_impl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,21 @@ static int secp256k1_ge_set_xo_var(secp256k1_ge_t *r, const secp256k1_fe_t *x, i
196196
return 1;
197197
}
198198

199+
static int secp256k1_ge_set_xo_iso_var(secp256k1_ge_t *r, secp256k1_fe_t *rk, const secp256k1_fe_t *x) {
200+
secp256k1_fe_t t;
201+
secp256k1_fe_sqr(&t, x);
202+
secp256k1_fe_mul(&t, &t, x);
203+
secp256k1_fe_set_int(rk, 7);
204+
secp256k1_fe_add(rk, &t); /* K = X^3 + 7 (2) */
205+
206+
/* TODO Jacobi symbol test to make sure K is a square */
207+
208+
r->infinity = 0;
209+
secp256k1_fe_mul(&r->x, rk, x); /* r->x = K*X (1) */
210+
secp256k1_fe_sqr(&r->y, rk); /* r->y = K^2 (1) */
211+
return 1;
212+
}
213+
199214
static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
200215
r->infinity = a->infinity;
201216
r->x = a->x;

src/secp256k1.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,39 @@ int secp256k1_point_multiply(unsigned char *point, int *pointlen, const unsigned
251251
return ret;
252252
}
253253

254+
int secp256k1_xo_multiply(unsigned char *xo, const unsigned char *scalar) {
255+
int ret = 0;
256+
int overflow = 0;
257+
secp256k1_fe_t k, t;
258+
secp256k1_gej_t res;
259+
secp256k1_ge_t pt;
260+
secp256k1_scalar_t s;
261+
DEBUG_CHECK(xo != NULL);
262+
DEBUG_CHECK(scalar != NULL);
263+
264+
secp256k1_scalar_set_b32(&s, scalar, &overflow);
265+
if (overflow) {
266+
ret = -2;
267+
} else {
268+
if (secp256k1_fe_set_b32(&t, xo) && secp256k1_ge_set_xo_iso_var(&pt, &k, &t)) {
269+
secp256k1_ecdh_point_multiply(&res, &pt, &s);
270+
if (!res.infinity) {
271+
secp256k1_fe_sqr(&t, &res.z);
272+
secp256k1_fe_mul(&t, &t, &k);
273+
secp256k1_fe_inv(&k, &t);
274+
secp256k1_fe_mul(&t, &res.x, &k);
275+
secp256k1_fe_normalize(&t);
276+
secp256k1_fe_get_b32(xo, &t);
277+
ret = 1;
278+
}
279+
} else {
280+
ret = -3;
281+
}
282+
}
283+
secp256k1_scalar_clear(&s);
284+
return ret;
285+
}
286+
254287
int secp256k1_ec_seckey_verify(const secp256k1_context_t* ctx, const unsigned char *seckey) {
255288
secp256k1_scalar_t sec;
256289
int ret;

src/tests.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,12 @@ void run_ecdh_api_tests(void) {
13761376
CHECK(secp256k1_point_multiply(point, &pointlen, scalar) == 1);
13771377
}
13781378
CHECK(memcmp(point, expected_comp, 33) == 0);
1379+
/* x-only */
1380+
secp256k1_eckey_pubkey_serialize(&gen, point, &pointlen, 1);
1381+
for (i = 0; i < 100; ++i) {
1382+
CHECK(secp256k1_xo_multiply(point+1, scalar) == 1);
1383+
}
1384+
CHECK(memcmp(point+1, expected_comp+1, 32) == 0);
13791385
}
13801386

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

0 commit comments

Comments
 (0)