Skip to content

Commit 64e56f8

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

File tree

11 files changed

+1067
-82
lines changed

11 files changed

+1067
-82
lines changed

src/secp256k1/.travis.yml

Lines changed: 2 additions & 1 deletion
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 25 additions & 10 deletions
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

Lines changed: 55 additions & 0 deletions
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
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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+
/** Compute commitment on the client as part of the ECDSA Anti Nonce Covert Channel Protocol.
52+
*
53+
* ECDSA Anti Nonce Covert Channel Protocol:
54+
* 1. The host draws randomness `k2`, commits to it with sha256 and sends the commitment to the client.
55+
* 2. The client commits to its original nonce `k1` using the host commitment by calling
56+
* `secp256k1_ecdsa_anti_covert_channel_client_commit`. The client sends the resulting commitment
57+
* `R1` to the host.
58+
* 3. The host replies with `k2` generated in step 1.
59+
* 4. The client signs with `secp256k1_ecdsa_s2c_sign`, using the `k2` as `s2c_data` and
60+
* sends the signature and opening to the host.
61+
* 5. The host verifies that `R_x = (R1 + H(R1, k2)*G)_x`, where R_x is the `r` part of the signature by using
62+
* `secp256k1_ecdsa_s2c_anti_nonce_covert_channel_host_verify` with the client's
63+
* commitment from step 2 and the signature and opening received in step 4. If verification does
64+
* not succeed, the protocol failed and can be restarted.
65+
*
66+
* Returns 1 on success, 0 on failure.
67+
* Args: ctx: pointer to a context object (cannot be NULL)
68+
* Out: client_commit: pointer to a pubkey where the clients public nonce will be
69+
* placed. (cannot be NULL)
70+
* In: msg32: the 32-byte message hash to be signed (cannot be NULL)
71+
* seckey32: the 32-byte secret key used for signing (cannot be NULL)
72+
* noncefp: pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
73+
* rand_commitment32: the 32-byte randomness commitment from the host (cannot be NULL)
74+
*/
75+
SECP256K1_API int secp256k1_ecdsa_s2c_anti_nonce_covert_channel_client_commit(
76+
const secp256k1_context* ctx,
77+
secp256k1_pubkey *client_commit,
78+
const unsigned char *msg32,
79+
const unsigned char *seckey32,
80+
unsigned char *rand_commitment32
81+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
82+
83+
/** Create a randomness commitment on the host as part of the ECDSA Anti Nonce Covert Channel Protocol.
84+
*
85+
* Returns 1 on success, 0 on failure.
86+
* Args: ctx: pointer to a context object (cannot be NULL)
87+
* Out: rand_commitment32: pointer to 32-byte array to store the returned commitment (cannot be NULL)
88+
* In: rand32: the 32-byte randomness to commit to (cannot be NULL)
89+
*/
90+
SECP256K1_API int secp256k1_ecdsa_s2c_anti_nonce_covert_channel_host_commit(
91+
secp256k1_context *ctx,
92+
unsigned char *rand_commitment32,
93+
const unsigned char *rand32
94+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
95+
96+
/** Verify that a clients signature contains the hosts randomness as part of the Anti
97+
* Nonce Covert Channel Protocol. Does not verify the signature itself.
98+
*
99+
* Returns 1 on success, 0 on failure.
100+
* Args: ctx: pointer to a context object (cannot be NULL)
101+
* In: sig: pointer to the signature whose randomness should be verified
102+
* (cannot be NULL)
103+
* rand32: pointer to the 32-byte randomness from the host which should
104+
* be included by the signature (cannot be NULL)
105+
* opening: pointer to the opening produced by the client when signing
106+
* with `rand32` as `s2c_data` (cannot be NULL)
107+
* client_commit: pointer to the client's commitment created in
108+
* `secp256k1_ecdsa_s2c_anti_nonce_covert_channel_client_commit`
109+
* (cannot be NULL)
110+
*/
111+
SECP256K1_API int secp256k1_ecdsa_s2c_anti_nonce_covert_channel_host_verify(
112+
secp256k1_context *ctx,
113+
const secp256k1_ecdsa_signature *sig,
114+
const unsigned char *rand32,
115+
const secp256k1_s2c_opening *opening,
116+
const secp256k1_pubkey *client_commit
117+
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
118+
119+
#ifdef __cplusplus
120+
}
121+
#endif
122+
123+
#endif /* SECP256K1_ECDSA_SIGN_TO_CONTRACT_H */
Lines changed: 3 additions & 0 deletions
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

0 commit comments

Comments
 (0)