#ifndef SECP256K1_ECDSA_ADAPTOR_H #define SECP256K1_ECDSA_ADAPTOR_H #ifdef __cplusplus extern "C" { #endif #include "secp256k1.h" /** This module implements single signer ECDSA adaptor signatures following * "One-Time Verifiably Encrypted Signatures A.K.A. Adaptor Signatures" by * Lloyd Fournier * (https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-November/002316.html * and https://github.com/LLFourn/one-time-VES/blob/master/main.pdf). * * WARNING! DANGER AHEAD! * As mentioned in Lloyd Fournier's paper, the adaptor signature leaks the * Elliptic-curve Diffie–Hellman (ECDH) key between the signing key and the * encryption key. This is not a problem for ECDSA adaptor signatures * themselves, but may result in a complete loss of security when they are * composed with other schemes. More specifically, let us refer to the * signer's public key as X = x*G, and to the encryption key as Y = y*G. * Given X, Y and the adaptor signature, it is trivial to compute Y^x = X^y. * * A defense is to not reuse the signing key of ECDSA adaptor signatures in * protocols that rely on the hardness of the CDH problem, e.g., Diffie-Hellman * key exchange and ElGamal encryption. In general, it is a well-established * cryptographic practice to seperate keys for different purposes whenever * possible. */ /** A pointer to a function to deterministically generate a nonce. * * Same as secp256k1_nonce_function_hardened with the exception of using the * compressed 33-byte encoding for the pubkey argument. * * 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 hash being verified * key32: pointer to a 32-byte secret key * pk33: the 33-byte serialized pubkey corresponding to key32 * algo: pointer to an array describing the signature algorithm * 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 pubkey, the algorithm description, and data. */ typedef int (*secp256k1_nonce_function_hardened_ecdsa_adaptor)( unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *pk33, 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. * The hash will be tagged with algo after removing all terminating null bytes. */ SECP256K1_API const secp256k1_nonce_function_hardened_ecdsa_adaptor secp256k1_nonce_function_ecdsa_adaptor; /** Encrypted Signing * * Creates an adaptor signature, which includes a proof to verify the adaptor * signature. * WARNING: Make sure you have read and understood the WARNING at the top of * this file and applied the suggested countermeasures. * * Returns: 1 on success, 0 on failure * Args: ctx: pointer to a context object (not secp256k1_context_static) * Out: adaptor_sig162: pointer to 162 byte to store the returned signature * In: seckey32: pointer to 32 byte secret key that will be used for * signing * enckey: pointer to the encryption public key * msg32: pointer to the 32-byte message hash to sign * noncefp: pointer to a nonce generation function. If NULL, * secp256k1_nonce_function_ecdsa_adaptor is used * ndata: pointer to arbitrary data used by the nonce generation * function (can be NULL). If it is non-NULL and * secp256k1_nonce_function_ecdsa_adaptor is used, then * ndata must be a pointer to 32-byte auxiliary randomness * as per BIP-340. */ SECP256K1_API int secp256k1_ecdsa_adaptor_encrypt( const secp256k1_context *ctx, unsigned char *adaptor_sig162, unsigned char *seckey32, const secp256k1_pubkey *enckey, const unsigned char *msg32, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); /** Encryption Verification * * Verifies that the adaptor decryption key can be extracted from the adaptor signature * and the completed ECDSA signature. * * Returns: 1 on success, 0 on failure * Args: ctx: pointer to a context object * In: adaptor_sig162: pointer to 162-byte signature to verify * pubkey: pointer to the public key corresponding to the secret key * used for signing * msg32: pointer to the 32-byte message hash being verified * enckey: pointer to the adaptor encryption public key */ SECP256K1_API int secp256k1_ecdsa_adaptor_verify( const secp256k1_context *ctx, const unsigned char *adaptor_sig162, const secp256k1_pubkey *pubkey, const unsigned char *msg32, const secp256k1_pubkey *enckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); /** Signature Decryption * * Derives an ECDSA signature from an adaptor signature and an adaptor decryption key. * * Returns: 1 on success, 0 on failure * Args: ctx: pointer to a context object * Out: sig: pointer to the ECDSA signature to create * In: deckey32: pointer to 32-byte decryption secret key for the adaptor * encryption public key * adaptor_sig162: pointer to 162-byte adaptor sig */ SECP256K1_API int secp256k1_ecdsa_adaptor_decrypt( const secp256k1_context *ctx, secp256k1_ecdsa_signature *sig, const unsigned char *deckey32, const unsigned char *adaptor_sig162 ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); /** Decryption Key Recovery * * Extracts the adaptor decryption key from the complete signature and the adaptor * signature. * * Returns: 1 on success, 0 on failure * Args: ctx: pointer to a context object (not secp256k1_context_static) * Out: deckey32: pointer to 32-byte adaptor decryption key for the adaptor * encryption public key * In: sig: pointer to ECDSA signature to recover the adaptor decryption * key from * adaptor_sig162: pointer to adaptor signature to recover the adaptor * decryption key from * enckey: pointer to the adaptor encryption public key */ SECP256K1_API int secp256k1_ecdsa_adaptor_recover( const secp256k1_context *ctx, unsigned char *deckey32, const secp256k1_ecdsa_signature *sig, const unsigned char *adaptor_sig162, const secp256k1_pubkey *enckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5); #ifdef __cplusplus } #endif #endif /* SECP256K1_ECDSA_ADAPTOR_H */