Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an experimental schnorr signature adaptor module #268

Closed
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,7 @@ endif
if ENABLE_MODULE_ECDSA_ADAPTOR
include src/modules/ecdsa_adaptor/Makefile.am.include
endif

if ENABLE_MODULE_SCHNORR_ADAPTOR
include src/modules/schnorr_adaptor/Makefile.am.include
endif
1 change: 1 addition & 0 deletions ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ esac
--enable-module-rangeproof="$RANGEPROOF" --enable-module-whitelist="$WHITELIST" --enable-module-generator="$GENERATOR" \
--enable-module-schnorrsig="$SCHNORRSIG" --enable-module-musig="$MUSIG" --enable-module-ecdsa-adaptor="$ECDSAADAPTOR" \
--enable-module-schnorrsig="$SCHNORRSIG" \
--enable-module-schnorr-adaptor="$SCHNORRADAPTOR" \
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
--enable-examples="$EXAMPLES" \
--enable-ctime-tests="$CTIMETESTS" \
--with-valgrind="$WITH_VALGRIND" \
Expand Down
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ AC_ARG_ENABLE(module_ellswift,
AS_HELP_STRING([--enable-module-ellswift],[enable ElligatorSwift module [default=yes]]), [],
[SECP_SET_DEFAULT([enable_module_ellswift], [yes], [yes])])

AC_ARG_ENABLE(module_schnorr_adaptor,
AS_HELP_STRING([--enable-module-schnorr-adaptor],[enable schnorr adaptor module [default=no]]), [],
[SECP_SET_DEFAULT([enable_module_schnorr_adaptor], [no], [yes])])

AC_ARG_ENABLE(module_ecdsa_s2c,
AS_HELP_STRING([--enable-module-ecdsa-s2c],[enable ECDSA sign-to-contract module [default=no]]),
[],
Expand Down Expand Up @@ -490,6 +494,11 @@ if test x"$enable_module_schnorrsig" = x"yes"; then
enable_module_extrakeys=yes
fi

if test x"$enable_module_schnorr_adaptor" = x"yes"; then
AC_DEFINE(ENABLE_MODULE_SCHNORR_ADAPTOR, 1, [Define thsi symbol to enable the Schnorr adaptor module])
enable_module_extrakeys=yes
fi
ZhePang marked this conversation as resolved.
Show resolved Hide resolved

if test x"$enable_module_ellswift" = x"yes"; then
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DENABLE_MODULE_ELLSWIFT=1"
fi
Expand Down Expand Up @@ -557,6 +566,9 @@ else
if test x"$set_asm" = x"arm32"; then
AC_MSG_ERROR([ARM32 assembly optimization is experimental. Use --enable-experimental to allow.])
fi
if test x"$enable_module_schnorr_adaptor" = x"yes"; then
AC_MSG_ERROR([schnorr adaptor signatures module is experimental. Use --enable-experimental to allow.])
fi
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
fi

###
Expand All @@ -581,6 +593,7 @@ AM_CONDITIONAL([ENABLE_MODULE_RANGEPROOF], [test x"$enable_module_rangeproof" =
AM_CONDITIONAL([ENABLE_MODULE_WHITELIST], [test x"$enable_module_whitelist" = 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([ENABLE_MODULE_SCHNORR_ADAPTOR], [test x"$enable_module_schnorr_adaptor" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ELLSWIFT], [test x"$enable_module_ellswift" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_S2C], [test x"$enable_module_ecdsa_s2c" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_ECDSA_ADAPTOR], [test x"$enable_module_ecdsa_adaptor" = x"yes"])
Expand All @@ -607,6 +620,7 @@ 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 " module schnorr-adaptor = $enable_module_schnorr_adaptor"
echo " module ellswift = $enable_module_ellswift"
echo " module generator = $enable_module_generator"
echo " module rangeproof = $enable_module_rangeproof"
Expand Down
138 changes: 138 additions & 0 deletions include/secp256k1_schnorr_adaptor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#ifndef SECP256K1_SCHNORR_ADAPTOR_H
#define SECP256K1_SCHNORR_ADAPTOR_H

#include "secp256k1.h"
#include "secp256k1_extrakeys.h"

#ifdef __cplusplus
extern "C" {
#endif

/** A pointer to a function to deterministically generate a nonce.
*
* Same as secp256k1_schnorrsig_nonce function with the exception of accepting an
* additional adaptor point t argument. The adaptor point argument can protect
* signature schemes with key-prefixed challenge hash inputs against reusing the
* nonce when signing with different adaptor points.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
*
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to
* return an error.
* Out: nonce32: pointer to a 32-byte array to be filled by the function
* In: msg32: the 32-byte message being verified (will not be NULL)
* key32: pointer to a 32-byte secret key (will not be NULL)
* t33: the 33-byte serialized adaptor point (will not be NULL)
* xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32
* (will not be NULL)
* algo: pointer to an array describing the signature
* algorithm (will not be NULL)
* algolen: the length of the algo array
* data: arbitrary data pointer that is passed through
*
* Except for test cases, this function should compute some cryptographic hash of
* the message, the key, the adaptor point, the pubkey, the algorithm description, and data.
*/
typedef int (*secp256k1_adaptor_nonce_function_hardened)(
unsigned char *nonce32,
const unsigned char *msg32,
const unsigned char *key32,
const unsigned char *t33,
const unsigned char *xonly_pk32,
const unsigned char *algo,
size_t algolen,
void *data
);

/** A modified BIP-340 nonce generation function.
*
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* auxiliary random data as defined in BIP-340. If the data pointer is NULL,
* the nonce derivation procedure follows BIP-340 by setting the auxiliary
* random data to zero. The algo argument must be non-NULL, otherwise the
* function will fail and return 0. The hash will be tagged with algo.
* Therefore, to create BIP-340 compliant signatures, algo must be set to
* "BIP0340/nonce" and algolen to 13.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
*/
SECP256K1_API const secp256k1_adaptor_nonce_function_hardened secp256k1_adaptor_nonce_function_bip340;
ZhePang marked this conversation as resolved.
Show resolved Hide resolved

/** Create a Schnorr adaptor signature.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to replace the term "adaptor signature" with "pre-signature" to be consistent with the literature (see #268 (comment))?

*
* This function only signs 32-byte messages. If you have messages of a
* different size (or the same size but without a context-specific tag
* prefix), it is recommended to create a 32-byte message hash with
* secp256k1_tagged_sha256 and then sign the hash. Tagged hashing allows
* providing an context-specific tag for domain separation. This prevents
* signatures from being valid in multiple contexts by accident.
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig65: pointer to a 65-byte array to store the serialized signature.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
* In: msg32: the 32-byte message being signed.
* keypair: pointer to an initialized keypair.
* t33: pointer to a 33-byte compressed adaptor point.
* aux_rand32: 32 bytes of fresh randomness. While recommended to provide
* this, it is only supplemental to security and can be NULL. A
* NULL argument is treated the same as an all-zero one. See
* BIP-340 "Default Signing" for a full explanation of this
* argument and for guidance if randomness is expensive.
*/
SECP256K1_API int secp256k1_schnorr_adaptor_presign(
const secp256k1_context *ctx,
unsigned char *sig65,
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
const unsigned char *msg32,
const secp256k1_keypair *keypair,
const unsigned char *t33,
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Extract an adaptor point T from the signature.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object.
* Out: t33: pointer to a 33-byte array to store the compressed adaptor point.
* In: sig65: pointer to a 65-byte serialized signature.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
* msg32: the 32-byte message being signed.
* pubkey: pointer to an x-only public key to verify with (cannot be NULL)
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
*/
SECP256K1_API int secp256k1_schnorr_adaptor_extract_t(
jonasnick marked this conversation as resolved.
Show resolved Hide resolved
const secp256k1_context *ctx,
unsigned char *t33,
const unsigned char *sig65,
const unsigned char *msg32,
const secp256k1_xonly_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Adapt an adaptor signature to a schnorr signature.
ZhePang marked this conversation as resolved.
Show resolved Hide resolved
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object.
* Out: sig64: pointer to a 64-byte array to store the adapted schnorr signature.
* In: sig65: pointer to a 65-byte serialized adaptor signature.
* t32: pointer to a 32-byte adaptor.
*/
SECP256K1_API int secp256k1_schnorr_adaptor_adapt(
const secp256k1_context *ctx,
unsigned char *sig64,
const unsigned char *sig65,
const unsigned char *t32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

/** Extract the adaptor from an adaptor signature and a schnorr signature.
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object.
* Out: t32: pointer to a 32-byte array to store the adaptor.
* In: sig65: pointer to a 65-byte serialized adaptor signature.
* sig64: pointer to a 64-byte adapted schnorr signature.
*/
SECP256K1_API int secp256k1_schnorr_adaptor_extract_adaptor(
jonasnick marked this conversation as resolved.
Show resolved Hide resolved
const secp256k1_context *ctx,
unsigned char *t32,
const unsigned char *sig65,
const unsigned char *sig64
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

#ifdef __cplusplus
}
#endif

#endif /* SECP256K1_SCHNORR_ADAPTOR_H */
22 changes: 22 additions & 0 deletions src/ctime_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include "../include/secp256k1_schnorrsig.h"
#endif

#ifdef ENABLE_MODULE_SCHNORR_ADAPTOR
#include "../include/secp256k1_schnorr_adaptor.h"
#endif

#ifdef ENABLE_MODULE_ELLSWIFT
#include "../include/secp256k1_ellswift.h"
#endif
Expand Down Expand Up @@ -193,6 +197,24 @@ static void run_tests(secp256k1_context *ctx, unsigned char *key) {
CHECK(ret == 1);
#endif

#ifdef ENABLE_MODULE_SCHNORR_ADAPTOR
{
unsigned char t[33];

for (i = 0; i < 33; i++) {
t[i] = i + 2;
}

SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_keypair_create(ctx, &keypair, key);
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
ret = secp256k1_schnorr_adaptor_presign(ctx, sig, msg, &keypair, t, NULL);
SECP256K1_CHECKMEM_DEFINE(&ret, sizeof(ret));
CHECK(ret == 1);
}
#endif

#ifdef ENABLE_MODULE_ELLSWIFT
SECP256K1_CHECKMEM_UNDEFINE(key, 32);
ret = secp256k1_ellswift_create(ctx, ellswift, key, NULL);
Expand Down
3 changes: 3 additions & 0 deletions src/modules/schnorr_adaptor/Makefile.am.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_HEADERS += include/secp256k1_schnorr_adaptor.h
noinst_HEADERS += src/modules/schnorr_adaptor/main_impl.h
noinst_HEADERS += src/modules/schnorr_adaptor/tests_impl.h
Loading
Loading