secp256k1-zkp/include/secp256k1_frost.h

214 lines
8.6 KiB
C
Raw Normal View History

#ifndef SECP256K1_FROST_H
#define SECP256K1_FROST_H
#include "secp256k1_extrakeys.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/** This code is currently a work in progress. It's not secure nor stable. IT
* IS EXTREMELY DANGEROUS AND RECKLESS TO USE THIS MODULE IN PRODUCTION!
* This module implements a variant of Flexible Round-Optimized Schnorr
* Threshold Signatures (FROST) by Chelsea Komlo and Ian Goldberg
* (https://crysp.uwaterloo.ca/software/frost/).
*
* Following the convention used in the MuSig module, the API uses the singular
* term "nonce" to refer to the two "nonces" used by the FROST scheme.
*/
/** Opaque data structures
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. If you
* need to convert to a format suitable for storage, transmission, or
* comparison, use the corresponding serialization and parsing functions.
*/
/** Opaque data structure that holds a signer's _secret_ share.
*
* Guaranteed to be 36 bytes in size. Serialized and parsed with
* `frost_share_serialize` and `frost_share_parse`.
*/
typedef struct {
unsigned char data[36];
} secp256k1_frost_share;
/** Opaque data structure that holds a signer's _secret_ nonce.
*
* Guaranteed to be 68 bytes in size.
*
* WARNING: This structure MUST NOT be copied or read or written to directly.
* A signer who is online throughout the whole process and can keep this
* structure in memory can use the provided API functions for a safe standard
* workflow. See
* https://blockstream.com/2019/02/18/musig-a-new-multisignature-standard/ for
* more details about the risks associated with serializing or deserializing
* this structure.
*
* We repeat, copying this data structure can result in nonce reuse which will
* leak the secret signing key.
*/
typedef struct {
unsigned char data[68];
} secp256k1_frost_secnonce;
/** Opaque data structure that holds a signer's public nonce.
*
* Guaranteed to be 132 bytes in size. It can be safely copied/moved.
* Serialized and parsed with `frost_pubnonce_serialize` and
* `frost_pubnonce_parse`.
*/
typedef struct {
unsigned char data[132];
} secp256k1_frost_pubnonce;
/** Parse a signer's public nonce.
*
* Returns: 1 when the nonce could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: nonce: pointer to a nonce object
* In: in66: pointer to the 66-byte nonce to be parsed
*/
SECP256K1_API int secp256k1_frost_pubnonce_parse(
const secp256k1_context *ctx,
secp256k1_frost_pubnonce *nonce,
const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a signer's public nonce
*
* Returns: 1 when the nonce could be serialized, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: out66: pointer to a 66-byte array to store the serialized nonce
* In: nonce: pointer to the nonce
*/
SECP256K1_API int secp256k1_frost_pubnonce_serialize(
const secp256k1_context *ctx,
unsigned char *out66,
const secp256k1_frost_pubnonce *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a FROST share
*
* Returns: 1 when the share could be serialized, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: out32: pointer to a 32-byte array to store the serialized share
* In: share: pointer to the share
*/
SECP256K1_API int secp256k1_frost_share_serialize(
const secp256k1_context *ctx,
unsigned char *out32,
const secp256k1_frost_share *share
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse a FROST share.
*
* Returns: 1 when the share could be parsed, 0 otherwise.
* Args: ctx: a secp256k1 context object
* Out: share: pointer to a share object
* In: in32: pointer to the 32-byte share to be parsed
*/
SECP256K1_API int secp256k1_frost_share_parse(
const secp256k1_context *ctx,
secp256k1_frost_share *share,
const unsigned char *in32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Creates key generation shares
*
* To generate a key, a trusted dealer generates a share for each other
* participant.
*
* Each participant _must_ have a secure channel with the trusted dealer with
* which they can transmit shares to each other.
*
* A new seed32 _must_ be used for each key generation session. The trusted
* dealer must NOT REUSE their respective seed32 again for subsequent key
* generation sessions. If a trusted dealer fails to complete this session or
* start a new session to generate a new key, they must NOT REUSE their
* respective seed32 again, but instead generate a new one. It is recommended
* to always choose seed32 uniformly at random to avoid their reuse.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: shares: pointer to the key generation shares
* pubshares: pointer to the public verification shares
* pk: pointer to the x-only public key
* In: seed32: a 32-byte seed as explained above
* threshold: the minimum number of signers required to produce a
* signature
* n_participants: the total number of participants
*/
SECP256K1_API int secp256k1_frost_shares_trusted_gen(
const secp256k1_context *ctx,
secp256k1_frost_share *shares,
secp256k1_pubkey *pubshares,
secp256k1_xonly_pubkey *pk,
const unsigned char *seed32,
size_t threshold,
size_t n_participants
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Starts a signing session by generating a nonce
*
* This function outputs a secret nonce that will be required for signing and a
* corresponding public nonce that is intended to be sent to other signers.
*
* FROST, like MuSig, differs from regular Schnorr signing in that
* implementers _must_ take special care to not reuse a nonce. This can be
* ensured by following these rules:
*
* 1. Each call to this function must have a UNIQUE session_id32 that must NOT BE
* REUSED in subsequent calls to this function.
* If you do not provide a seckey, session_id32 _must_ be UNIFORMLY RANDOM
* AND KEPT SECRET (even from other signers). If you do provide a seckey,
* session_id32 can instead be a counter (that must never repeat!). However,
* it is recommended to always choose session_id32 uniformly at random.
* 2. If you already know the seckey, message or aggregate public key, they
* can be optionally provided to derive the nonce and increase
* misuse-resistance. The extra_input32 argument can be used to provide
* additional data that does not repeat in normal scenarios, such as the
* current time.
* 3. Avoid copying (or serializing) the secnonce. This reduces the possibility
* that it is used more than once for signing.
*
* Remember that nonce reuse will leak the secret key!
* Note that using the same agg_share for multiple FROST sessions is fine.
*
* Returns: 0 if the arguments are invalid and 1 otherwise
* Args: ctx: pointer to a context object (not secp256k1_context_static)
* Out: secnonce: pointer to a structure to store the secret nonce
* pubnonce: pointer to a structure to store the public nonce
* In: session_id32: a 32-byte session_id32 as explained above. Must be
* unique to this call to secp256k1_frost_nonce_gen and
* must be uniformly random unless you really know what you
* are doing.
* agg_share: the aggregated share that will later be used for
* signing, if already known (can be NULL)
* msg32: the 32-byte message that will later be signed, if
* already known (can be NULL)
* agg_pk: the FROST-aggregated public key (can be NULL)
* extra_input32: an optional 32-byte array that is input to the nonce
* derivation function (can be NULL)
*/
SECP256K1_API int secp256k1_frost_nonce_gen(
const secp256k1_context *ctx,
secp256k1_frost_secnonce *secnonce,
secp256k1_frost_pubnonce *pubnonce,
const unsigned char *session_id32,
const secp256k1_frost_share *agg_share,
const unsigned char *msg32,
const secp256k1_xonly_pubkey *agg_pk,
const unsigned char *extra_input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
#ifdef __cplusplus
}
#endif
#endif