-
Notifications
You must be signed in to change notification settings - Fork 210
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
FROST Trusted Dealer #278
base: master
Are you sure you want to change the base?
FROST Trusted Dealer #278
Changes from 1 commit
6216645
833d4d8
a64a904
3787674
9fa15f5
af4dfaf
ab1bb83
aea613b
fafc1f1
f41560c
c139f91
f045caf
298accf
640d61c
4b387ef
6aa7df2
eb543cb
b8c671c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,9 @@ extern "C" { | |
* | ||
* The module also supports BIP-341 ("Taproot") and BIP-32 ("ordinary") public | ||
* key tweaking. | ||
* | ||
* 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 | ||
|
@@ -46,6 +49,61 @@ 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Considering that this blog post link has been removed in the MuSig2 PR in the secp256k1 main repo (see bitcoin-core/secp256k1#1479 (comment)), I guess the same should be done here. |
||
* | ||
* 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: pointer to a 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: pointer to a 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 | ||
|
@@ -271,6 +329,61 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_frost_pubkey_xonly_twea | |
const unsigned char *tweak32 | ||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); | ||
|
||
/** 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 group 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 share! | ||
* 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) | ||
* keygen_cache: pointer to the keygen_cache that was used to create the group | ||
* (and potentially tweaked) public key if already known | ||
* (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_frost_keygen_cache *keygen_cache, | ||
const unsigned char *extra_input32 | ||
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can also add How do we decide the args supplied to the hash function for generating a nonce? Should we throw in all available signer information into the hash function? For instance, can we include the participant identifier too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related issue: siv2r/bip-frost-signing#15, which suggests using |
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,6 @@ | |
#define SECP256K1_MODULE_FROST_MAIN | ||
|
||
#include "keygen_impl.h" | ||
#include "session_impl.h" | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/********************************************************************** | ||
* Copyright (c) 2021-2024 Jesse Posner * | ||
* Distributed under the MIT software license, see the accompanying * | ||
* file COPYING or http://www.opensource.org/licenses/mit-license.php.* | ||
**********************************************************************/ | ||
|
||
#ifndef SECP256K1_MODULE_FROST_SESSION_H | ||
#define SECP256K1_MODULE_FROST_SESSION_H | ||
|
||
#include "../../../include/secp256k1.h" | ||
#include "../../../include/secp256k1_frost.h" | ||
|
||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming nit: maybe call it
secshare
(both for the type and its instances and (de)ser function names in the API), in order to underline that this should be kept in secret? also since the public counterpart is calledpubshare
.