Skip to content

Commit a110572

Browse files
committed
pull in ecdsa sign to contract PR
bitcoin-core/secp256k1#669
1 parent 32e6c1a commit a110572

File tree

11 files changed

+781
-82
lines changed

11 files changed

+781
-82
lines changed

src/secp256k1/.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ env:
1717
- SCALAR=32bit FIELD=32bit EXPERIMENTAL=yes RANGEPROOF=yes WHITELIST=yes GENERATOR=yes SCHNORRSIG=yes MUSIG=yes
1818
- FIELD=64bit EXPERIMENTAL=yes RANGEPROOF=yes WHITELIST=yes GENERATOR=yes SCHNORRSIG=yes MUSIG=yes
1919
- SCALAR=32bit RECOVERY=yes
20-
- SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes
20+
- SCALAR=32bit FIELD=32bit ECDH=yes ECDSA_SIGN_TO_CONTRACT=yes EXPERIMENTAL=yes
21+
- SCALAR=32bit FIELD=32bit EXPERIMENTAL=yes
2122
- SCALAR=64bit
2223
- FIELD=64bit RECOVERY=yes
2324
- FIELD=64bit ENDOMORPHISM=yes

src/secp256k1/Makefile.am

+4
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,7 @@ endif
205205
if ENABLE_MODULE_SURJECTIONPROOF
206206
include src/modules/surjection/Makefile.am.include
207207
endif
208+
209+
if ENABLE_MODULE_ECDSA_SIGN_TO_CONTRACT
210+
include src/modules/ecdsa_sign_to_contract/Makefile.am.include
211+
endif

src/secp256k1/configure.ac

+25-10
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ AC_ARG_ENABLE(module_whitelist,
159159
[enable_module_whitelist=$enableval],
160160
[enable_module_whitelist=no])
161161

162+
AC_ARG_ENABLE(module_ecdsa_sign_to_contract,
163+
AS_HELP_STRING([--enable-module-ecdsa-sign-to-contract],[enable ECDSA sign-to-contract module [default=no]]),
164+
[enable_module_ecdsa_sign_to_contract=$enableval],
165+
[enable_module_ecdsa_sign_to_contract=no])
166+
162167
AC_ARG_ENABLE(external_default_callbacks,
163168
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]),
164169
[use_external_default_callbacks=$enableval],
@@ -587,6 +592,10 @@ if test x"$enable_module_surjectionproof" = x"yes"; then
587592
AC_DEFINE(ENABLE_MODULE_SURJECTIONPROOF, 1, [Define this symbol to enable the surjection proof module])
588593
fi
589594

595+
if test x"$enable_module_ecdsa_sign_to_contract" = x"yes"; then
596+
AC_DEFINE(ENABLE_MODULE_ECDSA_SIGN_TO_CONTRACT, 1, [Define this symbol to enable the ECDSA sign-to-contract module])
597+
fi
598+
590599
AC_C_BIGENDIAN()
591600

592601
if test x"$use_external_asm" = x"yes"; then
@@ -612,6 +621,7 @@ if test x"$enable_experimental" = x"yes"; then
612621
AC_MSG_NOTICE([Building surjection proof module: $enable_module_surjectionproof])
613622
AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig])
614623
AC_MSG_NOTICE([Building MuSig module: $enable_module_musig])
624+
AC_MSG_NOTICE([Building ECDSA sign-to-contract module: $enable_module_ecdsa_sign_to_contract])
615625
AC_MSG_NOTICE([******])
616626

617627

@@ -639,6 +649,9 @@ else
639649
if test x"$enable_module_ecdh" = x"yes"; then
640650
AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
641651
fi
652+
if test x"$enable_module_ecdsa_sign_to_contract" = x"yes"; then
653+
AC_MSG_ERROR([ECDA sign-to-contract module module is experimental. Use --enable-experimental to allow.])
654+
fi
642655
if test x"$enable_module_schnorrsig" = x"yes"; then
643656
AC_MSG_ERROR([schnorrsig module is experimental. Use --enable-experimental to allow.])
644657
fi
@@ -681,6 +694,7 @@ AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"ye
681694
AM_CONDITIONAL([ENABLE_MODULE_GENERATOR], [test x"$enable_module_generator" = x"yes"])
682695
AM_CONDITIONAL([ENABLE_MODULE_RANGEPROOF], [test x"$enable_module_rangeproof" = x"yes"])
683696
AM_CONDITIONAL([ENABLE_MODULE_WHITELIST], [test x"$enable_module_whitelist" = x"yes"])
697+
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_SIGN_TO_CONTRACT], [test x"$enable_module_ecdsa_sign_to_contract" = x"yes"])
684698
AM_CONDITIONAL([USE_JNI], [test x"$use_jni" = x"yes"])
685699
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"])
686700
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"])
@@ -705,16 +719,17 @@ echo " with coverage = $enable_coverage"
705719
echo " module ecdh = $enable_module_ecdh"
706720
echo " module recovery = $enable_module_recovery"
707721
echo " module schnorrsig = $enable_module_schnorrsig"
722+
echo " module ecdsa sign-to-contract = $enable_module_ecdsa_sign_to_contract"
708723
echo
709-
echo " asm = $set_asm"
710-
echo " bignum = $set_bignum"
711-
echo " field = $set_field"
712-
echo " scalar = $set_scalar"
713-
echo " ecmult window size = $set_ecmult_window"
714-
echo " ecmult gen prec. bits = $set_ecmult_gen_precision"
724+
echo " asm = $set_asm"
725+
echo " bignum = $set_bignum"
726+
echo " field = $set_field"
727+
echo " scalar = $set_scalar"
728+
echo " ecmult window size = $set_ecmult_window"
729+
echo " ecmult gen prec. bits = $set_ecmult_gen_precision"
715730
echo
716-
echo " CC = $CC"
717-
echo " CFLAGS = $CFLAGS"
718-
echo " CPPFLAGS = $CPPFLAGS"
719-
echo " LDFLAGS = $LDFLAGS"
731+
echo " CC = $CC"
732+
echo " CFLAGS = $CFLAGS"
733+
echo " CPPFLAGS = $CPPFLAGS"
734+
echo " LDFLAGS = $LDFLAGS"
720735
echo

src/secp256k1/include/secp256k1.h

+55
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern "C" {
66
#endif
77

88
#include <stddef.h>
9+
#include <stdint.h>
910

1011
/* These rules specify the order of arguments in API calls:
1112
*
@@ -81,6 +82,29 @@ typedef struct {
8182
unsigned char data[64];
8283
} secp256k1_ecdsa_signature;
8384

85+
/** Data structure that holds a sign-to-contract ("s2c") opening information.
86+
* Sign-to-contract allows a signer to commit to some data as part of a signature. It
87+
* can be used as an Out-argument in certain signing functions.
88+
*
89+
* This structure is not opaque, but it is strongly discouraged to read or write to
90+
* it directly.
91+
*
92+
* The exact representation of data inside is implementation defined and not
93+
* guaranteed to be portable between different platforms or versions. It can
94+
* be safely copied/moved.
95+
*/
96+
typedef struct {
97+
/* magic is set during initialization */
98+
uint64_t magic;
99+
/* Public nonce before applying the sign-to-contract commitment */
100+
secp256k1_pubkey original_pubnonce;
101+
/* Byte indicating if signing algorithm negated the nonce. Alternatively when
102+
* verifying we could compute the EC commitment of original_pubnonce and the
103+
* data and negate if this would not be a valid nonce. But this would prevent
104+
* batch verification of sign-to-contract commitments. */
105+
int nonce_is_negated;
106+
} secp256k1_s2c_opening;
107+
84108
/** A pointer to a function to deterministically generate a nonce.
85109
*
86110
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail.
@@ -444,6 +468,37 @@ SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact(
444468
const secp256k1_ecdsa_signature* sig
445469
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
446470

471+
/** Parse a sign-to-contract opening.
472+
*
473+
* Returns: 1 if the opening was fully valid.
474+
* 0 if the opening could not be parsed or is invalid.
475+
* Args: ctx: a secp256k1 context object.
476+
* Out: opening: pointer to an opening object. If 1 is returned, it is set to a
477+
* parsed version of input. If not, its value is undefined.
478+
* In: input34: pointer to 34-byte array with a serialized opening
479+
*
480+
*/
481+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_s2c_opening_parse(
482+
const secp256k1_context* ctx,
483+
secp256k1_s2c_opening* opening,
484+
const unsigned char *input34
485+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
486+
487+
/** Serialize a sign-to-contract opening into a byte sequence.
488+
*
489+
* Returns: 1 if the opening was successfully serialized.
490+
* 0 if the opening was not initializaed.
491+
* Args: ctx: a secp256k1 context object.
492+
* Out: output34: pointer to a 34-byte array to place the serialized opening
493+
* in.
494+
* In: opening: a pointer to an initialized `secp256k1_s2c_opening`.
495+
*/
496+
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_s2c_opening_serialize(
497+
const secp256k1_context* ctx,
498+
unsigned char *output34,
499+
const secp256k1_s2c_opening* opening
500+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
501+
447502
/** Verify an ECDSA signature.
448503
*
449504
* Returns: 1: correct signature
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#ifndef SECP256K1_ECDSA_SIGN_TO_CONTRACT_H
2+
#define SECP256K1_ECDSA_SIGN_TO_CONTRACT_H
3+
4+
#include "secp256k1.h"
5+
6+
#ifdef __cplusplus
7+
extern "C" {
8+
#endif
9+
10+
/** Same as secp256k1_ecdsa_sign, but s2c_data32 is committed to by adding `hash(R1, s2c_data32)` to
11+
* the nonce generated by noncefp.
12+
* Returns: 1: signature created
13+
* 0: the nonce generation function failed, or the private key was invalid.
14+
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
15+
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
16+
* s2c_opening: pointer to an secp256k1_s2c_opening structure which can be
17+
* NULL but is required to be not NULL if this signature creates
18+
* a sign-to-contract commitment (i.e. the `s2c_data` argument
19+
* is not NULL).
20+
* In:
21+
* msg32: the 32-byte message hash being signed (cannot be NULL)
22+
* seckey: pointer to a 32-byte secret key (cannot be NULL)
23+
* s2c_data32: pointer to a 32-byte data to create an optional
24+
* sign-to-contract commitment to if not NULL (can be NULL).
25+
*/
26+
SECP256K1_API int secp256k1_ecdsa_s2c_sign(
27+
const secp256k1_context* ctx,
28+
secp256k1_ecdsa_signature *sig,
29+
secp256k1_s2c_opening *s2c_opening,
30+
const unsigned char *msg32,
31+
const unsigned char *seckey,
32+
const unsigned char* s2c_data32
33+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
34+
35+
/** Verify a sign-to-contract commitment.
36+
*
37+
* Returns: 1: the signature contains a commitment to data32
38+
* 0: incorrect opening
39+
* Args: ctx: a secp256k1 context object, initialized for verification.
40+
* In: sig: the signature containing the sign-to-contract commitment (cannot be NULL)
41+
* data32: the 32-byte data that was committed to (cannot be NULL)
42+
* opening: pointer to the opening created during signing (cannot be NULL)
43+
*/
44+
SECP256K1_API int secp256k1_ecdsa_s2c_verify_commit(
45+
const secp256k1_context* ctx,
46+
const secp256k1_ecdsa_signature *sig,
47+
const unsigned char *data32,
48+
const secp256k1_s2c_opening *opening
49+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
50+
51+
#ifdef __cplusplus
52+
}
53+
#endif
54+
55+
#endif /* SECP256K1_ECDSA_SIGN_TO_CONTRACT_H */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include_HEADERS += include/secp256k1_ecdsa_sign_to_contract.h
2+
noinst_HEADERS += src/modules/ecdsa_sign_to_contract/main_impl.h
3+
noinst_HEADERS += src/modules/ecdsa_sign_to_contract/tests_impl.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**********************************************************************
2+
* Copyright (c) 2019 Marko Bencun, Jonas Nick *
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_MODULE_ECDSA_SIGN_TO_CONTRACT_MAIN_H
8+
#define SECP256K1_MODULE_ECDSA_SIGN_TO_CONTRACT_MAIN_H
9+
10+
#include "include/secp256k1_ecdsa_sign_to_contract.h"
11+
12+
int secp256k1_ecdsa_s2c_sign(const secp256k1_context *ctx, secp256k1_ecdsa_signature *signature, secp256k1_s2c_opening *s2c_opening, const unsigned char *msg32, const unsigned char *seckey, const unsigned char* s2c_data32) {
13+
secp256k1_scalar r, s;
14+
int ret;
15+
ARG_CHECK(signature != NULL);
16+
ret = secp256k1_ecdsa_sign_helper(ctx, &r, &s, s2c_opening, msg32, seckey, s2c_data32, NULL, NULL, NULL);
17+
if (ret) {
18+
secp256k1_ecdsa_signature_save(signature, &r, &s);
19+
} else {
20+
memset(signature, 0, sizeof(*signature));
21+
}
22+
return ret;
23+
}
24+
25+
int secp256k1_ecdsa_s2c_verify_commit(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *data32, const secp256k1_s2c_opening *opening) {
26+
secp256k1_pubkey commitment;
27+
secp256k1_ge commitment_ge;
28+
unsigned char x_bytes1[32];
29+
unsigned char x_bytes2[32];
30+
secp256k1_scalar sigr, sigs;
31+
32+
VERIFY_CHECK(ctx != NULL);
33+
ARG_CHECK(sig != NULL);
34+
ARG_CHECK(data32 != NULL);
35+
ARG_CHECK(opening != NULL);
36+
ARG_CHECK(secp256k1_s2c_commit_is_init(opening));
37+
38+
if (!secp256k1_ec_commit(ctx, &commitment, &opening->original_pubnonce, data32, 32)) {
39+
return 0;
40+
}
41+
42+
/* Check that sigr (x coordinate of R) matches the x coordinate of the commitment. */
43+
secp256k1_ecdsa_signature_load(ctx, &sigr, &sigs, sig);
44+
45+
if (!secp256k1_pubkey_load(ctx, &commitment_ge, &commitment)) {
46+
return 0;
47+
}
48+
secp256k1_fe_normalize(&commitment_ge.x);
49+
secp256k1_fe_get_b32(x_bytes1, &commitment_ge.x);
50+
secp256k1_scalar_get_b32(x_bytes2, &sigr);
51+
return memcmp(x_bytes1, x_bytes2, 32) == 0;
52+
53+
}
54+
55+
#endif /* SECP256K1_ECDSA_SIGN_TO_CONTRACT_MAIN_H */

0 commit comments

Comments
 (0)