Skip to content

Commit 6b64825

Browse files
apoelstrabenmajonasnick
committed
1 parent 694ce8f commit 6b64825

File tree

5 files changed

+183
-0
lines changed

5 files changed

+183
-0
lines changed

Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ noinst_HEADERS += src/scalar_8x32_impl.h
2020
noinst_HEADERS += src/scalar_low_impl.h
2121
noinst_HEADERS += src/group.h
2222
noinst_HEADERS += src/group_impl.h
23+
noinst_HEADERS += src/eccommit.h
24+
noinst_HEADERS += src/eccommit_impl.h
2325
noinst_HEADERS += src/ecdsa.h
2426
noinst_HEADERS += src/ecdsa_impl.h
2527
noinst_HEADERS += src/eckey.h

src/eccommit.h

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**********************************************************************
2+
* Copyright (c) 2020 The libsecp256k1-zkp Developers *
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+
#ifndef SECP256K1_ECCOMMIT_H
8+
#define SECP256K1_ECCOMMIT_H
9+
10+
/** Helper function to add a 32-byte value to a scalar */
11+
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak);
12+
/** Helper function to add a 32-byte value, times G, to an EC point */
13+
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak);
14+
15+
/** Serializes elem as a 33 byte array. This is non-constant time with respect to
16+
* whether pubp is the point at infinity. Thus, you may need to declassify
17+
* pubp->infinity before calling this function. */
18+
static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33);
19+
/** Compute an ec commitment tweak as hash(pubkey, data). */
20+
static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size);
21+
/** Compute an ec commitment as pubkey + hash(pubkey, data)*G. */
22+
static int secp256k1_ec_commit(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size);
23+
/** Compute a secret key commitment as seckey + hash(pubkey, data). */
24+
static int secp256k1_ec_commit_seckey(const secp256k1_ecmult_gen_context* ecmult_gen_ctx, secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size);
25+
/** Verify an ec commitment as pubkey + hash(pubkey, data)*G ?= commitment. */
26+
static int secp256k1_ec_commit_verify(const secp256k1_ecmult_context* ecmult_ctx, const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size);
27+
28+
#endif /* SECP256K1_ECCOMMIT_H */

src/eccommit_impl.h

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**********************************************************************
2+
* Copyright (c) 2020 The libsecp256k1 Developers *
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 <stddef.h>
8+
9+
#include "eckey.h"
10+
#include "hash.h"
11+
12+
/* from secp256k1.c */
13+
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak);
14+
static int secp256k1_ec_pubkey_tweak_add_helper(secp256k1_ge *pubp, const unsigned char *tweak);
15+
16+
static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33) {
17+
if (secp256k1_ge_is_infinity(pubp)) {
18+
return 0;
19+
}
20+
secp256k1_fe_normalize(&pubp->x);
21+
secp256k1_fe_normalize(&pubp->y);
22+
secp256k1_fe_get_b32(&buf33[1], &pubp->x);
23+
buf33[0] = secp256k1_fe_is_odd(&pubp->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
24+
return 1;
25+
}
26+
27+
/* Compute an ec commitment tweak as hash(pubp, data). */
28+
static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size)
29+
{
30+
unsigned char rbuf[33];
31+
32+
if (!secp256k1_ec_commit_pubkey_serialize_const(pubp, rbuf)) {
33+
return 0;
34+
}
35+
secp256k1_sha256_write(sha, rbuf, sizeof(rbuf));
36+
secp256k1_sha256_write(sha, data, data_size);
37+
secp256k1_sha256_finalize(sha, tweak32);
38+
return 1;
39+
}
40+
41+
/* Compute an ec commitment as pubp + hash(pubp, data)*G. */
42+
static int secp256k1_ec_commit(secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
43+
unsigned char tweak[32];
44+
45+
*commitp = *pubp;
46+
return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size)
47+
&& secp256k1_ec_pubkey_tweak_add_helper(commitp, tweak);
48+
}
49+
50+
/* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey +
51+
* hash(pubp, data). */
52+
static int secp256k1_ec_commit_seckey(secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
53+
unsigned char tweak[32];
54+
return secp256k1_ec_commit_tweak(tweak, pubp, sha, data, data_size)
55+
&& secp256k1_ec_seckey_tweak_add_helper(seckey, tweak);
56+
}
57+
58+
/* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */
59+
static int secp256k1_ec_commit_verify(const secp256k1_ge* commitp, const secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
60+
secp256k1_gej pj;
61+
secp256k1_ge p;
62+
63+
if (!secp256k1_ec_commit(&p, pubp, sha, data, data_size)) {
64+
return 0;
65+
}
66+
67+
/* Return p == commitp */
68+
secp256k1_ge_neg(&p, &p);
69+
secp256k1_gej_set_ge(&pj, &p);
70+
secp256k1_gej_add_ge_var(&pj, &pj, commitp, NULL);
71+
return secp256k1_gej_is_infinity(&pj);
72+
}
73+

src/secp256k1.c

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "field_impl.h"
2626
#include "scalar_impl.h"
2727
#include "group_impl.h"
28+
#include "eccommit_impl.h"
2829
#include "ecmult_impl.h"
2930
#include "ecmult_const_impl.h"
3031
#include "ecmult_gen_impl.h"

src/tests.c

+79
Original file line numberDiff line numberDiff line change
@@ -3596,6 +3596,84 @@ void run_ec_combine(void) {
35963596
}
35973597
}
35983598

3599+
void test_ec_commit(void) {
3600+
secp256k1_scalar seckey_s;
3601+
secp256k1_ge pubkey;
3602+
secp256k1_gej pubkeyj;
3603+
secp256k1_ge commitment;
3604+
unsigned char data[32];
3605+
secp256k1_sha256 sha;
3606+
3607+
/* Create random keypair and data */
3608+
random_scalar_order_test(&seckey_s);
3609+
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
3610+
secp256k1_ge_set_gej(&pubkey, &pubkeyj);
3611+
secp256k1_testrand256_test(data);
3612+
3613+
/* Commit to data and verify */
3614+
secp256k1_sha256_initialize(&sha);
3615+
CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 1);
3616+
secp256k1_sha256_initialize(&sha);
3617+
CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 1);
3618+
secp256k1_sha256_initialize(&sha);
3619+
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 1);
3620+
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
3621+
ge_equals_gej(&commitment, &pubkeyj);
3622+
3623+
/* Check that verification fails with different data */
3624+
secp256k1_sha256_initialize(&sha);
3625+
CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 31) == 0);
3626+
3627+
/* Check that commmitting fails when the inner pubkey is the point at
3628+
* infinity */
3629+
secp256k1_sha256_initialize(&sha);
3630+
secp256k1_ge_set_infinity(&pubkey);
3631+
CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 32) == 0);
3632+
secp256k1_scalar_set_int(&seckey_s, 0);
3633+
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 0);
3634+
CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 32) == 0);
3635+
}
3636+
3637+
3638+
void test_ec_commit_api(void) {
3639+
unsigned char seckey[32];
3640+
secp256k1_scalar seckey_s;
3641+
secp256k1_ge pubkey;
3642+
secp256k1_gej pubkeyj;
3643+
secp256k1_ge commitment;
3644+
unsigned char data[32];
3645+
secp256k1_sha256 sha;
3646+
3647+
memset(data, 23, sizeof(data));
3648+
3649+
/* Create random keypair */
3650+
random_scalar_order_test(&seckey_s);
3651+
secp256k1_scalar_get_b32(seckey, &seckey_s);
3652+
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
3653+
secp256k1_ge_set_gej(&pubkey, &pubkeyj);
3654+
3655+
secp256k1_sha256_initialize(&sha);
3656+
CHECK(secp256k1_ec_commit(&commitment, &pubkey, &sha, data, 1) == 1);
3657+
/* The same pubkey can be both input and output of the function */
3658+
{
3659+
secp256k1_ge pubkey_tmp = pubkey;
3660+
secp256k1_sha256_initialize(&sha);
3661+
CHECK(secp256k1_ec_commit(&pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1);
3662+
ge_equals_ge(&commitment, &pubkey_tmp);
3663+
}
3664+
3665+
secp256k1_sha256_initialize(&sha);
3666+
CHECK(secp256k1_ec_commit_verify(&commitment, &pubkey, &sha, data, 1) == 1);
3667+
}
3668+
3669+
void run_ec_commit(void) {
3670+
int i;
3671+
for (i = 0; i < count * 8; i++) {
3672+
test_ec_commit();
3673+
}
3674+
test_ec_commit_api();
3675+
}
3676+
35993677
void test_group_decompress(const secp256k1_fe* x) {
36003678
/* The input itself, normalized. */
36013679
secp256k1_fe fex = *x;
@@ -7137,6 +7215,7 @@ int main(int argc, char **argv) {
71377215
run_ecmult_const_tests();
71387216
run_ecmult_multi_tests();
71397217
run_ec_combine();
7218+
run_ec_commit();
71407219

71417220
/* endomorphism tests */
71427221
run_endomorphism_tests();

0 commit comments

Comments
 (0)