Skip to content

Commit

Permalink
Squashed 'src/secp256k1/' changes from 2ed54da..2c8e321a1b
Browse files Browse the repository at this point in the history
2c8e321a1b valgrind_ctime_test: Add schnorrsig_sign
47e3b68533 schnorrsig: Add taproot test case
c024c80af3 schnorrsig: Add benchmark for sign and verify
47dd51f6a1 schnorrsig: Add BIP-340 compatible signing and verification
e8a3d6ce06 schnorrsig: Add BIP-340 nonce function
fd70f1f460 schnorrsig: Init empty experimental module
4dcb59e082 Allow initializing tagged sha256
96006e5c46 extrakeys: Add keypair_xonly_tweak_add
311578eaf1 extrakeys: Add keypair struct with create, pub and pub_xonly
f00eebe110 Separate helper functions for pubkey_create and seckey_tweak_add
8409443226 extrakeys: Add xonly_pubkey_tweak_add & xonly_pubkey_tweak_add_test
14acf6db3e Separate helper function for ec_pubkey_tweak_add
95dd2c73c5 extrakeys: Add xonly_pubkey with serialize, parse and from_pubkey
2c767ad9a7 extrakeys: Init empty experimental module
f027df7b04 Make the secp256k1_declassify argument constant
2309c7d Merge bitcoin#769: Undef HAVE___INT128 in basic-config.h to fix gen_context compilation
22e578b Undef HAVE___INT128 in basic-config.h to fix gen_context compilation
3f4a5a1 Merge bitcoin#765: remove dead store in ecdsa_signature_parse_der_lax
f00d657 remove dead store in ecdsa_signature_parse_der_lax
dbd41db Merge bitcoin#759: Fix uninitialized variables in ecmult_multi test
2e7fc5b Fix uninitialized variables in ecmult_multi test

git-subtree-dir: src/secp256k1
git-subtree-split: 2c8e321a1b543e1f008a32c0a9091b752ccf8e72
  • Loading branch information
sipa committed Aug 7, 2020
1 parent 67f232b commit 94dc6bc
Show file tree
Hide file tree
Showing 24 changed files with 2,398 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
bench_inv
bench_ecdh
bench_ecmult
bench_schnorrsig
bench_sign
bench_verify
bench_schnorr_verify
bench_recover
bench_internal
tests
Expand Down
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ compiler:
- gcc
env:
global:
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ECMULTGENPRECISION=auto ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no SCHNORRSIG=no EXPERIMENTAL=no CTIMETEST=yes BENCH=yes ITERS=2
matrix:
- SCALAR=32bit RECOVERY=yes
- SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes
- SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- SCALAR=64bit
- FIELD=64bit RECOVERY=yes
- FIELD=64bit RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- FIELD=64bit ENDOMORPHISM=yes
- FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes
- FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- FIELD=64bit ASM=x86_64
- FIELD=64bit ENDOMORPHISM=yes ASM=x86_64
- FIELD=32bit ENDOMORPHISM=yes
- BIGNUM=no
- BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes
- BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes SCHNORRSIG=yes
- BIGNUM=no STATICPRECOMPUTATION=no
- BUILD=distcheck CTIMETEST= BENCH=
- CPPFLAGS=-DDETERMINISTIC
Expand Down
8 changes: 8 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,11 @@ endif
if ENABLE_MODULE_RECOVERY
include src/modules/recovery/Makefile.am.include
endif

if ENABLE_MODULE_EXTRAKEYS
include src/modules/extrakeys/Makefile.am.include
endif

if ENABLE_MODULE_SCHNORRSIG
include src/modules/schnorrsig/Makefile.am.include
endif
33 changes: 33 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ AC_ARG_ENABLE(module_recovery,
[enable_module_recovery=$enableval],
[enable_module_recovery=no])

AC_ARG_ENABLE(module_extrakeys,
AS_HELP_STRING([--enable-module-extrakeys],[enable extrakeys module (experimental)]),
[enable_module_extrakeys=$enableval],
[enable_module_extrakeys=no])

AC_ARG_ENABLE(module_schnorrsig,
AS_HELP_STRING([--enable-module-schnorrsig],[enable schnorrsig module (experimental)]),
[enable_module_schnorrsig=$enableval],
[enable_module_schnorrsig=no])

AC_ARG_ENABLE(external_default_callbacks,
AS_HELP_STRING([--enable-external-default-callbacks],[enable external default callback functions [default=no]]),
[use_external_default_callbacks=$enableval],
Expand Down Expand Up @@ -493,6 +503,17 @@ if test x"$enable_module_recovery" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module])
fi

if test x"$enable_module_schnorrsig" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_SCHNORRSIG, 1, [Define this symbol to enable the schnorrsig module])
enable_module_extrakeys=yes
fi

# Test if extrakeys is set after the schnorrsig module to allow the schnorrsig
# module to set enable_module_extrakeys=yes
if test x"$enable_module_extrakeys" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_EXTRAKEYS, 1, [Define this symbol to enable the extrakeys module])
fi

AC_C_BIGENDIAN()

if test x"$use_external_asm" = x"yes"; then
Expand All @@ -508,11 +529,19 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([WARNING: experimental build])
AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh])
AC_MSG_NOTICE([Building extrakeys module: $enable_module_extrakeys])
AC_MSG_NOTICE([Building schnorrsig module: $enable_module_schnorrsig])
AC_MSG_NOTICE([******])
else
if test x"$enable_module_ecdh" = x"yes"; then
AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_extrakeys" = x"yes"; then
AC_MSG_ERROR([extrakeys module is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_schnorrsig" = x"yes"; then
AC_MSG_ERROR([schnorrsig module is experimental. Use --enable-experimental to allow.])
fi
if test x"$set_asm" = x"arm"; then
AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.])
fi
Expand All @@ -531,6 +560,8 @@ AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"])
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"])

Expand All @@ -550,6 +581,8 @@ echo " with benchmarks = $use_benchmark"
echo " with coverage = $enable_coverage"
echo " module ecdh = $enable_module_ecdh"
echo " module recovery = $enable_module_recovery"
echo " module extrakeys = $enable_module_extrakeys"
echo " module schnorrsig = $enable_module_schnorrsig"
echo
echo " asm = $set_asm"
echo " bignum = $set_bignum"
Expand Down
1 change: 0 additions & 1 deletion contrib/lax_der_parsing.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_
return 0;
}
spos = pos;
pos += slen;

/* Ignore leading zeroes in R */
while (rlen > 0 && input[rpos] == 0) {
Expand Down
3 changes: 2 additions & 1 deletion contrib/travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ fi
--enable-experimental="$EXPERIMENTAL" --enable-endomorphism="$ENDOMORPHISM" \
--with-field="$FIELD" --with-bignum="$BIGNUM" --with-asm="$ASM" --with-scalar="$SCALAR" \
--enable-ecmult-static-precomputation="$STATICPRECOMPUTATION" --with-ecmult-gen-precision="$ECMULTGENPRECISION" \
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" "$EXTRAFLAGS" "$USE_HOST"
--enable-module-ecdh="$ECDH" --enable-module-recovery="$RECOVERY" \
--enable-module-schnorrsig="$SCHNORRSIG" "$EXTRAFLAGS" "$USE_HOST"

if [ -n "$BUILD" ]
then
Expand Down
234 changes: 234 additions & 0 deletions include/secp256k1_extrakeys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
#ifndef SECP256K1_EXTRAKEYS_H
#define SECP256K1_EXTRAKEYS_H

#include "secp256k1.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Opaque data structure that holds a parsed and valid "x-only" public key.
* An x-only pubkey encodes a point whose Y coordinate is even. It is
* serialized using only its X coordinate (32 bytes). See BIP-340 for more
* information about x-only pubkeys.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, or
* comparison, use secp256k1_xonly_pubkey_serialize and
* secp256k1_xonly_pubkey_parse.
*/
typedef struct {
unsigned char data[64];
} secp256k1_xonly_pubkey;

/** Opaque data structure that holds a keypair consisting of a secret and a
* public key.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 96 bytes in size, and can be safely copied/moved.
*/
typedef struct {
unsigned char data[96];
} secp256k1_keypair;

/** Parse a 32-byte public key into a xonly_pubkey object.
*
* Returns: 1 if the public key was fully valid.
* 0 if the public key could not be parsed or is invalid.
*
* Args: ctx: a secp256k1 context object (cannot be NULL).
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
* parsed version of input. If not, its value is undefined (cannot
* be NULL).
* In: input32: pointer to a serialized xonly_pubkey (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey* pubkey,
const unsigned char *input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Serialize an xonly_pubkey object into a 32-byte sequence.
*
* Returns: 1 always.
*
* Args: ctx: a secp256k1 context object (cannot be NULL).
* Out: output32: a pointer to a 32-byte array to place the serialized key in
* (cannot be NULL).
* In: pubkey: a pointer to a secp256k1_xonly_pubkey containing an
* initialized public key (cannot be NULL).
*/
SECP256K1_API int secp256k1_xonly_pubkey_serialize(
const secp256k1_context* ctx,
unsigned char *output32,
const secp256k1_xonly_pubkey* pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey.
*
* Returns: 1 if the public key was successfully converted
* 0 otherwise
*
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: xonly_pubkey: pointer to an x-only public key object for placing the
* converted public key (cannot be NULL)
* pk_parity: pointer to an integer that will be set to 1 if the point
* encoded by xonly_pubkey is the negation of pubkey and set
* to 0 otherwise. (can be NULL)
* In: pubkey: pointer to a public key that is converted (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey *xonly_pubkey,
int *pk_parity,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);

/** Tweak an x-only public key by adding tweak times the generator to it.
*
* Note that the resulting point can not be represented by an x-only pubkey
* because it may have an odd Y coordinate. Instead, the output_pubkey is a
* normal secp256k1_pubkey.
*
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
*
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL)
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0 (cannot
* be NULL)
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
* (cannot be NULL).
* tweak32: pointer to a 32-byte tweak. If the tweak is invalid
* according to secp256k1_ec_seckey_verify, this function
* returns 0. For uniformly random 32-byte arrays the
* chance of being invalid is negligible (around 1 in
* 2^128) (cannot be NULL).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
const secp256k1_context* ctx,
secp256k1_pubkey *output_pubkey,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Checks that an output pubkey is the result of calling
* secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32.
*
* The output pubkey is represented by its 32-byte x-only serialization and its
* pk_parity, which can both be obtained by converting the result of tweak_add
* to a secp256k1_xonly_pubkey.
*
* Note that this alone does _not_ verify that output pubkey is a commitment.
* If the tweak is not chosen in a specific way, the output pubkey can easily
* be the result of a different internal_pubkey and tweak.
*
* Returns: 0 if the arguments are invalid or the output pubkey is not the
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL)
* In: output_pubkey32: pointer to a serialized xonly_pubkey (cannot be NULL)
* output_pk_parity: the parity of the output pubkey (whose serialization is
* passed in as output_pubkey32). This must match the
* pk_parity value that is returned when calling
* secp256k1_xonly_pubkey with the output pubkey, or this
* function will fail.
* internal_pubkey: pointer to an x-only public key object to apply the
* tweak to (cannot be NULL)
* tweak32: pointer to a 32-byte tweak (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check(
const secp256k1_context* ctx,
const unsigned char *output_pubkey32,
int output_pk_parity,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Compute the keypair for a secret key.
*
* Returns: 1: secret was valid, keypair is ready to use
* 0: secret was invalid, try again
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: keypair: pointer to the created keypair (cannot be NULL)
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
const secp256k1_context* ctx,
secp256k1_keypair *keypair,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Get the public key from a keypair.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to
* the keypair public key. If not, its value is undefined. (cannot
* be NULL)
* In: keypair: pointer to a keypair (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
const secp256k1_context* ctx,
secp256k1_pubkey *pubkey,
const secp256k1_keypair *keypair
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Get the x-only public key from a keypair.
*
* This is the same as calling secp256k1_keypair_pub and then
* secp256k1_xonly_pubkey_from_pubkey.
*
* Returns: 0 if the arguments are invalid. 1 otherwise.
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set
* to the keypair public key after converting it to an
* xonly_pubkey. If not, its value is undefined (cannot be NULL).
* pk_parity: pointer to an integer that will be set to the pk_parity
* argument of secp256k1_xonly_pubkey_from_pubkey (can be NULL).
* In: keypair: pointer to a keypair (cannot be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
const secp256k1_context* ctx,
secp256k1_xonly_pubkey *pubkey,
int *pk_parity,
const secp256k1_keypair *keypair
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);

/** Tweak a keypair by adding tweak times the generator to the x-only public key
* and secret key parts of the keypair.
*
* Calling this function and then secp256k1_keypair_pub results in the same
* public key as calling secp256k1_keypair_xonly_pub and then
* secp256k1_xonly_pubkey_tweak_add.
*
* Returns: 0 if the arguments are invalid or the resulting keypair would be
* invalid (only when the tweak is the negation of the keypair's
* secret key). 1 otherwise.
*
* Args: ctx: pointer to a context object initialized for validation
* (cannot be NULL)
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* an invalid value if this function returns 0 (cannot be
* NULL).
* In: tweak32: pointer to a 32-byte tweak. If the tweak is invalid according
* to secp256k1_ec_seckey_verify, this function returns 0. For
* uniformly random 32-byte arrays the chance of being invalid
* is negligible (around 1 in 2^128) (cannot be NULL).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
const secp256k1_context* ctx,
secp256k1_keypair *keypair,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

#ifdef __cplusplus
}
#endif

#endif /* SECP256K1_EXTRAKEYS_H */
Loading

0 comments on commit 94dc6bc

Please sign in to comment.