add eccommit functionality
Co-authored-by: Marko Bencun <mbencun+pgp@gmail.com> Co-authored-by: Jonas Nick <jonasd.nick@gmail.com>
This commit is contained in:
parent
ff4714e641
commit
826bd04b43
@ -16,6 +16,8 @@ noinst_HEADERS += src/group.h
|
|||||||
noinst_HEADERS += src/group_impl.h
|
noinst_HEADERS += src/group_impl.h
|
||||||
noinst_HEADERS += src/num_gmp.h
|
noinst_HEADERS += src/num_gmp.h
|
||||||
noinst_HEADERS += src/num_gmp_impl.h
|
noinst_HEADERS += src/num_gmp_impl.h
|
||||||
|
noinst_HEADERS += src/eccommit.h
|
||||||
|
noinst_HEADERS += src/eccommit_impl.h
|
||||||
noinst_HEADERS += src/ecdsa.h
|
noinst_HEADERS += src/ecdsa.h
|
||||||
noinst_HEADERS += src/ecdsa_impl.h
|
noinst_HEADERS += src/ecdsa_impl.h
|
||||||
noinst_HEADERS += src/eckey.h
|
noinst_HEADERS += src/eckey.h
|
||||||
|
28
src/eccommit.h
Normal file
28
src/eccommit.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
* Copyright (c) 2020 The libsecp256k1-zkp Developers *
|
||||||
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SECP256K1_ECCOMMIT_H
|
||||||
|
#define SECP256K1_ECCOMMIT_H
|
||||||
|
|
||||||
|
/** Helper function to add a 32-byte value to a scalar */
|
||||||
|
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak);
|
||||||
|
/** Helper function to add a 32-byte value, times G, to an EC point */
|
||||||
|
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *p, const unsigned char *tweak);
|
||||||
|
|
||||||
|
/** Serializes elem as a 33 byte array. This is non-constant time with respect to
|
||||||
|
* whether pubp is the point at infinity. Thus, you may need to declassify
|
||||||
|
* pubp->infinity before calling this function. */
|
||||||
|
static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33);
|
||||||
|
/** Compute an ec commitment tweak as hash(pubkey, data). */
|
||||||
|
static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size);
|
||||||
|
/** Compute an ec commitment as pubkey + hash(pubkey, data)*G. */
|
||||||
|
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);
|
||||||
|
/** Compute a secret key commitment as seckey + hash(pubkey, data). */
|
||||||
|
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);
|
||||||
|
/** Verify an ec commitment as pubkey + hash(pubkey, data)*G ?= commitment. */
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif /* SECP256K1_ECCOMMIT_H */
|
73
src/eccommit_impl.h
Normal file
73
src/eccommit_impl.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
* Copyright (c) 2020 The libsecp256k1 Developers *
|
||||||
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
|
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "eckey.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
|
/* from secp256k1.c */
|
||||||
|
static int secp256k1_ec_seckey_tweak_add_helper(secp256k1_scalar *sec, const unsigned char *tweak);
|
||||||
|
static int secp256k1_ec_pubkey_tweak_add_helper(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_ge *pubp, const unsigned char *tweak);
|
||||||
|
|
||||||
|
static int secp256k1_ec_commit_pubkey_serialize_const(secp256k1_ge *pubp, unsigned char *buf33) {
|
||||||
|
if (secp256k1_ge_is_infinity(pubp)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
secp256k1_fe_normalize(&pubp->x);
|
||||||
|
secp256k1_fe_normalize(&pubp->y);
|
||||||
|
secp256k1_fe_get_b32(&buf33[1], &pubp->x);
|
||||||
|
buf33[0] = secp256k1_fe_is_odd(&pubp->y) ? SECP256K1_TAG_PUBKEY_ODD : SECP256K1_TAG_PUBKEY_EVEN;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute an ec commitment tweak as hash(pubp, data). */
|
||||||
|
static int secp256k1_ec_commit_tweak(unsigned char *tweak32, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size)
|
||||||
|
{
|
||||||
|
unsigned char rbuf[33];
|
||||||
|
|
||||||
|
if (!secp256k1_ec_commit_pubkey_serialize_const(pubp, rbuf)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
secp256k1_sha256_write(sha, rbuf, sizeof(rbuf));
|
||||||
|
secp256k1_sha256_write(sha, data, data_size);
|
||||||
|
secp256k1_sha256_finalize(sha, tweak32);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute an ec commitment as pubp + hash(pubp, data)*G. */
|
||||||
|
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) {
|
||||||
|
unsigned char tweak[32];
|
||||||
|
|
||||||
|
*commitp = *pubp;
|
||||||
|
return secp256k1_ec_commit_tweak(tweak, commitp, sha, data, data_size)
|
||||||
|
&& secp256k1_ec_pubkey_tweak_add_helper(ecmult_ctx, commitp, tweak);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the seckey of an ec commitment from the original secret key of the pubkey as seckey +
|
||||||
|
* hash(pubp, data). */
|
||||||
|
static int secp256k1_ec_commit_seckey(secp256k1_scalar* seckey, secp256k1_ge* pubp, secp256k1_sha256* sha, const unsigned char *data, size_t data_size) {
|
||||||
|
unsigned char tweak[32];
|
||||||
|
return secp256k1_ec_commit_tweak(tweak, pubp, sha, data, data_size)
|
||||||
|
&& secp256k1_ec_seckey_tweak_add_helper(seckey, tweak);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify an ec commitment as pubp + hash(pubp, data)*G ?= commitment. */
|
||||||
|
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) {
|
||||||
|
secp256k1_gej pj;
|
||||||
|
secp256k1_ge p;
|
||||||
|
|
||||||
|
if (!secp256k1_ec_commit(ecmult_ctx, &p, pubp, sha, data, data_size)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return p == commitp */
|
||||||
|
secp256k1_ge_neg(&p, &p);
|
||||||
|
secp256k1_gej_set_ge(&pj, &p);
|
||||||
|
secp256k1_gej_add_ge_var(&pj, &pj, commitp, NULL);
|
||||||
|
return secp256k1_gej_is_infinity(&pj);
|
||||||
|
}
|
||||||
|
|
@ -107,7 +107,7 @@ int sign(const secp256k1_context* ctx, unsigned char seckeys[][32], const secp25
|
|||||||
for (i = 0; i < N_SIGNERS; i++) {
|
for (i = 0; i < N_SIGNERS; i++) {
|
||||||
for (j = 0; j < N_SIGNERS; j++) {
|
for (j = 0; j < N_SIGNERS; j++) {
|
||||||
/* To check whether signing was successful, it suffices to either verify
|
/* To check whether signing was successful, it suffices to either verify
|
||||||
* the the combined signature with the combined public key using
|
* the combined signature with the combined public key using
|
||||||
* secp256k1_schnorrsig_verify, or verify all partial signatures of all
|
* secp256k1_schnorrsig_verify, or verify all partial signatures of all
|
||||||
* signers individually. Verifying the combined signature is cheaper but
|
* signers individually. Verifying the combined signature is cheaper but
|
||||||
* verifying the individual partial signatures has the advantage that it
|
* verifying the individual partial signatures has the advantage that it
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "field_impl.h"
|
#include "field_impl.h"
|
||||||
#include "scalar_impl.h"
|
#include "scalar_impl.h"
|
||||||
#include "group_impl.h"
|
#include "group_impl.h"
|
||||||
|
#include "eccommit_impl.h"
|
||||||
#include "ecmult_impl.h"
|
#include "ecmult_impl.h"
|
||||||
#include "ecmult_const_impl.h"
|
#include "ecmult_const_impl.h"
|
||||||
#include "ecmult_gen_impl.h"
|
#include "ecmult_gen_impl.h"
|
||||||
|
78
src/tests.c
78
src/tests.c
@ -2609,6 +2609,83 @@ void run_ec_combine(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_ec_commit(void) {
|
||||||
|
secp256k1_scalar seckey_s;
|
||||||
|
secp256k1_ge pubkey;
|
||||||
|
secp256k1_gej pubkeyj;
|
||||||
|
secp256k1_ge commitment;
|
||||||
|
unsigned char data[32];
|
||||||
|
secp256k1_sha256 sha;
|
||||||
|
|
||||||
|
/* Create random keypair and data */
|
||||||
|
random_scalar_order_test(&seckey_s);
|
||||||
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
|
||||||
|
secp256k1_ge_set_gej(&pubkey, &pubkeyj);
|
||||||
|
secp256k1_testrand256_test(data);
|
||||||
|
|
||||||
|
/* Commit to data and verify */
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 1);
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 1);
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 1);
|
||||||
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
|
||||||
|
ge_equals_gej(&commitment, &pubkeyj);
|
||||||
|
|
||||||
|
/* Check that verification fails with different data */
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 31) == 0);
|
||||||
|
|
||||||
|
/* Check that commmitting fails when the inner pubkey is the point at
|
||||||
|
* infinity */
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
secp256k1_ge_set_infinity(&pubkey);
|
||||||
|
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 0);
|
||||||
|
secp256k1_scalar_set_int(&seckey_s, 0);
|
||||||
|
CHECK(secp256k1_ec_commit_seckey(&seckey_s, &pubkey, &sha, data, 32) == 0);
|
||||||
|
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 32) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_ec_commit_api(void) {
|
||||||
|
unsigned char seckey[32];
|
||||||
|
secp256k1_scalar seckey_s;
|
||||||
|
secp256k1_ge pubkey;
|
||||||
|
secp256k1_gej pubkeyj;
|
||||||
|
secp256k1_ge commitment;
|
||||||
|
unsigned char data[32];
|
||||||
|
secp256k1_sha256 sha;
|
||||||
|
|
||||||
|
memset(data, 23, sizeof(data));
|
||||||
|
|
||||||
|
/* Create random keypair */
|
||||||
|
random_scalar_order_test(&seckey_s);
|
||||||
|
secp256k1_scalar_get_b32(seckey, &seckey_s);
|
||||||
|
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey_s);
|
||||||
|
secp256k1_ge_set_gej(&pubkey, &pubkeyj);
|
||||||
|
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 1) == 1);
|
||||||
|
/* The same pubkey can be both input and output of the function */
|
||||||
|
{
|
||||||
|
secp256k1_ge pubkey_tmp = pubkey;
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit(&ctx->ecmult_ctx, &pubkey_tmp, &pubkey_tmp, &sha, data, 1) == 1);
|
||||||
|
ge_equals_ge(&commitment, &pubkey_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_sha256_initialize(&sha);
|
||||||
|
CHECK(secp256k1_ec_commit_verify(&ctx->ecmult_ctx, &commitment, &pubkey, &sha, data, 1) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_ec_commit(void) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < count * 8; i++) {
|
||||||
|
test_ec_commit();
|
||||||
|
}
|
||||||
|
test_ec_commit_api();
|
||||||
|
}
|
||||||
|
|
||||||
void test_group_decompress(const secp256k1_fe* x) {
|
void test_group_decompress(const secp256k1_fe* x) {
|
||||||
/* The input itself, normalized. */
|
/* The input itself, normalized. */
|
||||||
secp256k1_fe fex = *x;
|
secp256k1_fe fex = *x;
|
||||||
@ -5858,6 +5935,7 @@ int main(int argc, char **argv) {
|
|||||||
run_ecmult_const_tests();
|
run_ecmult_const_tests();
|
||||||
run_ecmult_multi_tests();
|
run_ecmult_multi_tests();
|
||||||
run_ec_combine();
|
run_ec_combine();
|
||||||
|
run_ec_commit();
|
||||||
|
|
||||||
/* endomorphism tests */
|
/* endomorphism tests */
|
||||||
run_endomorphism_tests();
|
run_endomorphism_tests();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user