chilldkg: Phase 3 - public participant API and CertEq
Add the public participant-facing ChillDKG API to
include/secp256k1_chilldkg.h and the CertEq sub-protocol, completing
the participant side of the protocol (bip-frost-dkg v0.3.0-dev,
reference pinned at a91896883f85b159415ecf298d5e844879af112d).
New module files:
- certeq.h / certeq_impl.h: CertEq sub-protocol. Participants sign
pad33("BIP DKG/certeq message") || u32be(i) || eq_input with plain
BIP0340-tagged Schnorr signatures under their host key
(certeq_participant_step); verification is per-index against the
x-only hostpubkeys[i][1:33] exactly as the reference
(certeq_verify). The coordinator side reuses certeq_verify in
Phase 4.
Public API (all no-malloc, caller-allocated buffers, outputs zeroed on
failure, secret paths cleared):
- secp256k1_chilldkg_hostpubkey_gen: plain compressed host pubkey
generation; rejects zero / >= group order seckeys.
- secp256k1_chilldkg_params_hash: validates session params (participant
and threshold ranges, strictly compressed non-infinity pubkeys, no
duplicates) and computes TH("BIP DKG/params_hash", u32be(t) ||
hostpubkeys).
- Message-length helpers so callers can size buffers:
participant_msg1_len (33t+32n+97), coordinator_msg1_len
(162n+33(t-1)), participant_msg2_len (64), coordinator_msg2_len
(64n), recovery_data_len (4+33t+162n).
- secp256k1_chilldkg_participant_step1: full EncPedPop step1 with
seed=deckey=hostseckey; rejects zero randomness and hostseckeys not
matching the claimed hostpubkey (input errors, not protocol faults).
- secp256k1_chilldkg_participant_step2: parses and verifies cmsg1 via
the Phase 2 encpedpop/simplpedpop participant path, computes the
tweaked secshare/pubshares/threshold pubkey, appends enc_secshares
to eq_input (matching the reference for recovery consistency), and
emits the 64-byte CertEq signature.
- secp256k1_chilldkg_participant_finalize: re-verifies all n CertEq
signatures in the certificate, then outputs the 32-byte secshare,
33-byte threshold pubkey, n pubshares and the self-delimiting
recovery data (eq_input || cert).
Blame reporting without exceptions: public enum
secp256k1_chilldkg_fault (OK / FAULTY_COORDINATOR /
FAULTY_PARTICIPANT / FAULTY_PARTICIPANT_OR_COORDINATOR /
UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR / INVALID_INPUT) plus an out
fault_index, mapping the reference's exception taxonomy:
- hostseckey invalid/mismatch -> INVALID_INPUT (HostSeckeyError),
- cmsg1 scalar overflow/parse -> FAULTY_COORDINATOR (MsgParseError),
- pubnonce/commitment/PoP faults -> FAULTY_PARTICIPANT_OR_COORDINATOR(i),
- share-vs-pubshare mismatch -> UNKNOWN with fault_index = UINT32_MAX,
- certificate signature failure -> FAULTY_COORDINATOR (documented
deviation: fault_index carries the failing signature index as
diagnostic info; the reference discards it).
Enum-returning functions use a local CHILLDKG_ARG_CHECK that fires the
illegal-argument callback and returns INVALID_INPUT (ARG_CHECK would
return 0 = OK).
Opaque state objects with magic-validated save/load (frost idiom):
participant_state1 (4306 bytes, no secrets) and participant_state2
(21073 bytes, contains the secshare; documented keep-secret/no-copy).
Fixed-size at SECP256K1_CHILLDKG_MAX_PARTICIPANTS = 128.
Also fixes a noverify-build bug: state1_load ran point_load inside
VERIFY_CHECK, which compiles out in noverify builds and left the
commitment uninitialized; now called unconditionally.
tests_impl.h: participant_api_test with full-session reference vectors
(n=3, t=2; coordinator aggregation simulated through the internal
Phase 2 coordinator step and verified byte-identical to the
reference's coordinator_step1): msglen helpers, hostpubkey_gen and
params_hash vectors incl. duplicate/invalid/infinity rejection,
byte-exact pmsg1/cmsg1/CertEq sigs/secshare/thresh_pk/pubshares/
recovery, blame cases (tampered enc_secshare -> UNKNOWN, invalid
pubnonce -> FAULTY_PARTICIPANT_OR_COORDINATOR(1), overflowing
enc_secshare -> FAULTY_COORDINATOR, corrupted cert sig ->
FAULTY_COORDINATOR with fault_index and zeroed outputs), NULL-arg
misuse and bad-magic state rejection.
Verified: make check 3/3 (incl. noverify); CMake ctest 363/363;
make distdir includes all new files.
This commit is contained in:
@@ -27,10 +27,286 @@ extern "C" {
|
|||||||
* key, and the public shares of all participants) is designed to be used
|
* key, and the public shares of all participants) is designed to be used
|
||||||
* directly with the FROST signing module (see include/secp256k1_frost.h).
|
* directly with the FROST signing module (see include/secp256k1_frost.h).
|
||||||
*
|
*
|
||||||
|
* A DKG session involves n participants (identified by uint32 identifiers
|
||||||
|
* 0..n-1) and an untrusted coordinator. The number of participants n must
|
||||||
|
* not exceed SECP256K1_CHILLDKG_MAX_PARTICIPANTS. The message flow is:
|
||||||
|
* 1. Every participant runs secp256k1_chilldkg_participant_step1 and sends
|
||||||
|
* the resulting pmsg1 to the coordinator.
|
||||||
|
* 2. The coordinator aggregates the pmsg1s into a single cmsg1 broadcast
|
||||||
|
* to all participants (coordinator API is not available yet).
|
||||||
|
* 3. Every participant runs secp256k1_chilldkg_participant_step2 and sends
|
||||||
|
* the resulting signature (pmsg2) to the coordinator.
|
||||||
|
* 4. The coordinator collects the n signatures into a certificate (cmsg2)
|
||||||
|
* broadcast to all participants.
|
||||||
|
* 5. Every participant runs secp256k1_chilldkg_participant_finalize to
|
||||||
|
* obtain the DKG output and the recovery data.
|
||||||
|
*
|
||||||
* It is recommended to read the documentation in this include file carefully.
|
* It is recommended to read the documentation in this include file carefully.
|
||||||
* Further notes on API usage can be found in src/modules/chilldkg/chilldkg.md.
|
* Further notes on API usage can be found in src/modules/chilldkg/chilldkg.md.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** The maximum number of participants n in a ChillDKG session. The state
|
||||||
|
* objects of this module are fixed-size and do not use dynamic allocation,
|
||||||
|
* so a compile-time cap is required. This matches the FROST module's
|
||||||
|
* SECP256K1_FROST_MAX_PARTICIPANTS. */
|
||||||
|
#define SECP256K1_CHILLDKG_MAX_PARTICIPANTS 128
|
||||||
|
|
||||||
|
/** Fault report of the ChillDKG protocol functions, mapping the exception
|
||||||
|
* taxonomy of the reference implementation.
|
||||||
|
*
|
||||||
|
* For SECP256K1_CHILLDKG_FAULTY_PARTICIPANT and
|
||||||
|
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, the fault_index
|
||||||
|
* output of the failing function is set to the identifier of the (suspected)
|
||||||
|
* faulty participant. For the other fault codes, fault_index is set to
|
||||||
|
* UINT32_MAX, except where documented otherwise. */
|
||||||
|
typedef enum {
|
||||||
|
/** No fault; the step succeeded. */
|
||||||
|
SECP256K1_CHILLDKG_OK = 0,
|
||||||
|
/** The coordinator is faulty. */
|
||||||
|
SECP256K1_CHILLDKG_FAULTY_COORDINATOR = 1,
|
||||||
|
/** The participant with the given fault_index is faulty. */
|
||||||
|
SECP256K1_CHILLDKG_FAULTY_PARTICIPANT = 2,
|
||||||
|
/** The participant with the given fault_index or the coordinator is
|
||||||
|
* faulty. */
|
||||||
|
SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR = 3,
|
||||||
|
/** Some unknown participant or the coordinator is faulty; the
|
||||||
|
* investigation procedure of the protocol is necessary to determine a
|
||||||
|
* suspected participant. */
|
||||||
|
SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR = 4,
|
||||||
|
/** The caller provided invalid input (e.g., an invalid host secret key or
|
||||||
|
* invalid session parameters). */
|
||||||
|
SECP256K1_CHILLDKG_INVALID_INPUT = 5
|
||||||
|
} secp256k1_chilldkg_fault;
|
||||||
|
|
||||||
|
/** Opaque data structures
|
||||||
|
*
|
||||||
|
* The exact representation of data inside the opaque data structures is
|
||||||
|
* implementation defined and not guaranteed to be portable between different
|
||||||
|
* platforms or versions. The data structures can be safely copied/moved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Opaque data structure that holds a participant's session state after
|
||||||
|
* secp256k1_chilldkg_participant_step1.
|
||||||
|
*
|
||||||
|
* The state does not contain secret key material (the secret shares it
|
||||||
|
* relates to are encrypted in pmsg1), but it must not be reused: it must be
|
||||||
|
* passed only to a single secp256k1_chilldkg_participant_step2 call.
|
||||||
|
*
|
||||||
|
* Guaranteed to be 4306 bytes in size.
|
||||||
|
*/
|
||||||
|
typedef struct secp256k1_chilldkg_participant_state1 {
|
||||||
|
unsigned char data[4 + 12 + 33 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||||
|
} secp256k1_chilldkg_participant_state1;
|
||||||
|
|
||||||
|
/** Opaque data structure that holds a participant's session state after
|
||||||
|
* secp256k1_chilldkg_participant_step2.
|
||||||
|
*
|
||||||
|
* This structure contains the participant's secret share; it MUST be kept
|
||||||
|
* secret and MUST NOT be copied. It must not be reused: it must be passed
|
||||||
|
* only to a single secp256k1_chilldkg_participant_finalize call.
|
||||||
|
*
|
||||||
|
* Guaranteed to be 21073 bytes in size.
|
||||||
|
*/
|
||||||
|
typedef struct secp256k1_chilldkg_participant_state2 {
|
||||||
|
unsigned char data[12 + 4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 32 + 33 + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||||
|
} secp256k1_chilldkg_participant_state2;
|
||||||
|
|
||||||
|
/** Compute the participant's host public key from the host secret key.
|
||||||
|
*
|
||||||
|
* The host public key is the long-term cryptographic identity of the
|
||||||
|
* participant. This function interprets hostseckey32 as a big-endian integer
|
||||||
|
* and computes the corresponding "plain" public key in compressed
|
||||||
|
* serialization (33 bytes, starting with 0x02 or 0x03), equivalent to
|
||||||
|
* IndividualPubkey as defined in BIP 327.
|
||||||
|
*
|
||||||
|
* Returns: 1 on success, 0 if the host secret key is invalid (zero or not
|
||||||
|
* less than the group order). On failure, hostpubkey33 is set to
|
||||||
|
* zero.
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* Out: hostpubkey33: pointer to a 33-byte array to store the host public key
|
||||||
|
* In: hostseckey32: pointer to the 32-byte host secret key
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_hostpubkey_gen(
|
||||||
|
const secp256k1_context *ctx,
|
||||||
|
unsigned char *hostpubkey33,
|
||||||
|
const unsigned char *hostseckey32
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||||
|
|
||||||
|
/** Return a hash of the session parameters for out-of-band comparison.
|
||||||
|
*
|
||||||
|
* If all participants have obtained an identical parameters hash (as can be
|
||||||
|
* verified out of band), then they all agree on all host public keys and the
|
||||||
|
* threshold t.
|
||||||
|
*
|
||||||
|
* Returns: 1 on success, 0 if the session parameters are invalid (not
|
||||||
|
* 1 <= t <= n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS, an invalid
|
||||||
|
* host public key, or a duplicate host public key). On failure,
|
||||||
|
* hash32 is set to zero.
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* Out: hash32: pointer to a 32-byte array to store the parameters
|
||||||
|
* hash
|
||||||
|
* In: hostpubkeys33: pointer to an array of n_participants host public
|
||||||
|
* keys (33 bytes each, compressed serialization)
|
||||||
|
* n_participants: total number of participants n
|
||||||
|
* threshold: threshold t
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_params_hash(
|
||||||
|
const secp256k1_context *ctx,
|
||||||
|
unsigned char *hash32,
|
||||||
|
const unsigned char *hostpubkeys33,
|
||||||
|
size_t n_participants,
|
||||||
|
uint32_t threshold
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
|
||||||
|
|
||||||
|
/** Length of a participant's first message (pmsg1): 33*t + 32*n + 97 bytes.
|
||||||
|
* Returns 0 if the parameters are out of range. */
|
||||||
|
SECP256K1_API size_t secp256k1_chilldkg_participant_msg1_len(
|
||||||
|
size_t n_participants,
|
||||||
|
uint32_t threshold
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Length of the coordinator's first message (cmsg1): 162*n + 33*(t-1) bytes.
|
||||||
|
* Returns 0 if the parameters are out of range. */
|
||||||
|
SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg1_len(
|
||||||
|
size_t n_participants,
|
||||||
|
uint32_t threshold
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Length of a participant's second message (pmsg2): 64 bytes. */
|
||||||
|
SECP256K1_API size_t secp256k1_chilldkg_participant_msg2_len(void);
|
||||||
|
|
||||||
|
/** Length of the coordinator's second message (cmsg2, the certificate):
|
||||||
|
* 64*n bytes. Returns 0 if the parameters are out of range. */
|
||||||
|
SECP256K1_API size_t secp256k1_chilldkg_coordinator_msg2_len(
|
||||||
|
size_t n_participants
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Length of the recovery data output by
|
||||||
|
* secp256k1_chilldkg_participant_finalize: 4 + 33*t + 162*n bytes.
|
||||||
|
* Returns 0 if the parameters are out of range. */
|
||||||
|
SECP256K1_API size_t secp256k1_chilldkg_recovery_data_len(
|
||||||
|
size_t n_participants,
|
||||||
|
uint32_t threshold
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Perform a participant's first step of a ChillDKG session.
|
||||||
|
*
|
||||||
|
* Returns: 1 on success, 0 on invalid input (invalid host secret key, host
|
||||||
|
* secret key not matching any host public key, invalid session
|
||||||
|
* parameters, or all-zero randomness). On failure, pmsg1 and the
|
||||||
|
* state are set to zero.
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* Out: state1: pointer to a state1 object to be passed to
|
||||||
|
* secp256k1_chilldkg_participant_step2 (must not be
|
||||||
|
* reused)
|
||||||
|
* pmsg1: pointer to a 33*t + 32*n + 97 byte array (see
|
||||||
|
* secp256k1_chilldkg_participant_msg1_len) to store
|
||||||
|
* the message to be sent to the coordinator
|
||||||
|
* In: hostseckey32: pointer to the 32-byte host secret key
|
||||||
|
* hostpubkeys33: pointer to an array of n host public keys (33 bytes
|
||||||
|
* each); all participants must agree on the order
|
||||||
|
* n_participants: total number of participants n
|
||||||
|
* threshold: threshold t
|
||||||
|
* random32: pointer to 32 bytes of FRESH randomness
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_chilldkg_participant_step1(
|
||||||
|
const secp256k1_context *ctx,
|
||||||
|
secp256k1_chilldkg_participant_state1 *state1,
|
||||||
|
unsigned char *pmsg1,
|
||||||
|
const unsigned char *hostseckey32,
|
||||||
|
const unsigned char *hostpubkeys33,
|
||||||
|
size_t n_participants,
|
||||||
|
uint32_t threshold,
|
||||||
|
const unsigned char *random32
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(8);
|
||||||
|
|
||||||
|
/** Perform a participant's second step of a ChillDKG session.
|
||||||
|
*
|
||||||
|
* Verifies the coordinator's first message, computes the DKG output, and
|
||||||
|
* produces the CertEq signature over the session transcript.
|
||||||
|
*
|
||||||
|
* **Warning:** After sending the produced signature to the coordinator, the
|
||||||
|
* caller **must not** erase the hostseckey, even if the coordinator reply
|
||||||
|
* needed for secp256k1_chilldkg_participant_finalize is not received (some
|
||||||
|
* other participant may deem the session successful and use the resulting
|
||||||
|
* threshold public key).
|
||||||
|
*
|
||||||
|
* Returns: SECP256K1_CHILLDKG_OK on success, otherwise a fault code:
|
||||||
|
* SECP256K1_CHILLDKG_INVALID_INPUT if the host secret key is
|
||||||
|
* invalid or does not match the one used in step 1;
|
||||||
|
* SECP256K1_CHILLDKG_FAULTY_COORDINATOR,
|
||||||
|
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, or
|
||||||
|
* SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR on
|
||||||
|
* protocol faults. On failure, sig64 and the state are set to zero.
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* Out: state2: pointer to a state2 object to be passed to
|
||||||
|
* secp256k1_chilldkg_participant_finalize (must not be
|
||||||
|
* reused)
|
||||||
|
* sig64: pointer to a 64-byte array to store the CertEq
|
||||||
|
* signature (pmsg2) to be sent to the coordinator
|
||||||
|
* fault_index: pointer to a uint32 that receives the identifier of
|
||||||
|
* the (suspected) faulty participant where applicable,
|
||||||
|
* and UINT32_MAX otherwise
|
||||||
|
* In: state1: pointer to the state1 object output by
|
||||||
|
* secp256k1_chilldkg_participant_step1
|
||||||
|
* hostseckey32: pointer to the 32-byte host secret key (must be the
|
||||||
|
* same as in step 1)
|
||||||
|
* cmsg1: pointer to the coordinator's first message
|
||||||
|
* (162*n + 33*(t-1) bytes, see
|
||||||
|
* secp256k1_chilldkg_coordinator_msg1_len)
|
||||||
|
* aux_rand32: pointer to 32 bytes of auxiliary randomness for the
|
||||||
|
* CertEq signature (see BIP 340)
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(
|
||||||
|
const secp256k1_context *ctx,
|
||||||
|
secp256k1_chilldkg_participant_state2 *state2,
|
||||||
|
unsigned char *sig64,
|
||||||
|
uint32_t *fault_index,
|
||||||
|
const secp256k1_chilldkg_participant_state1 *state1,
|
||||||
|
const unsigned char *hostseckey32,
|
||||||
|
const unsigned char *cmsg1,
|
||||||
|
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) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8);
|
||||||
|
|
||||||
|
/** Perform a participant's final step of a ChillDKG session.
|
||||||
|
*
|
||||||
|
* Re-verifies all n CertEq signatures of the certificate and outputs the
|
||||||
|
* DKG output and the recovery data. If this function returns
|
||||||
|
* SECP256K1_CHILLDKG_OK, this participant deems the DKG session successful.
|
||||||
|
*
|
||||||
|
* Returns: SECP256K1_CHILLDKG_OK on success,
|
||||||
|
* SECP256K1_CHILLDKG_FAULTY_COORDINATOR if the certificate contains
|
||||||
|
* an invalid signature. As diagnostic information (deviating from
|
||||||
|
* the reference implementation, which does not report it),
|
||||||
|
* fault_index receives the index of the first invalid signature in
|
||||||
|
* the latter case. On failure, all outputs are set to zero.
|
||||||
|
* Args: ctx: pointer to a context object
|
||||||
|
* Out: secshare32: pointer to a 32-byte array to store the (tweaked)
|
||||||
|
* secret share
|
||||||
|
* thresh_pk33: pointer to a 33-byte array to store the threshold
|
||||||
|
* public key (compressed serialization)
|
||||||
|
* pubshares33: pointer to an array of n 33-byte elements to store
|
||||||
|
* the public shares of all participants
|
||||||
|
* recovery: pointer to a 4 + 33*t + 162*n byte array (see
|
||||||
|
* secp256k1_chilldkg_recovery_data_len) to store the
|
||||||
|
* recovery data
|
||||||
|
* fault_index: pointer to a uint32 (see above)
|
||||||
|
* In: state2: pointer to the state2 object output by
|
||||||
|
* secp256k1_chilldkg_participant_step2
|
||||||
|
* cmsg2: pointer to the coordinator's second message (the
|
||||||
|
* certificate, 64*n bytes)
|
||||||
|
*/
|
||||||
|
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT secp256k1_chilldkg_fault secp256k1_chilldkg_participant_finalize(
|
||||||
|
const secp256k1_context *ctx,
|
||||||
|
unsigned char *secshare32,
|
||||||
|
unsigned char *thresh_pk33,
|
||||||
|
unsigned char *pubshares33,
|
||||||
|
unsigned char *recovery,
|
||||||
|
uint32_t *fault_index,
|
||||||
|
const secp256k1_chilldkg_participant_state2 *state2,
|
||||||
|
const unsigned char *cmsg2
|
||||||
|
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6) SECP256K1_ARG_NONNULL(7) SECP256K1_ARG_NONNULL(8);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,4 +8,6 @@ noinst_HEADERS += src/modules/chilldkg/simplpedpop.h
|
|||||||
noinst_HEADERS += src/modules/chilldkg/simplpedpop_impl.h
|
noinst_HEADERS += src/modules/chilldkg/simplpedpop_impl.h
|
||||||
noinst_HEADERS += src/modules/chilldkg/encpedpop.h
|
noinst_HEADERS += src/modules/chilldkg/encpedpop.h
|
||||||
noinst_HEADERS += src/modules/chilldkg/encpedpop_impl.h
|
noinst_HEADERS += src/modules/chilldkg/encpedpop_impl.h
|
||||||
|
noinst_HEADERS += src/modules/chilldkg/certeq.h
|
||||||
|
noinst_HEADERS += src/modules/chilldkg/certeq_impl.h
|
||||||
noinst_HEADERS += src/modules/chilldkg/tests_impl.h
|
noinst_HEADERS += src/modules/chilldkg/tests_impl.h
|
||||||
|
|||||||
36
src/modules/chilldkg/certeq.h
Normal file
36
src/modules/chilldkg/certeq.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
|
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SECP256K1_MODULE_CHILLDKG_CERTEQ_H
|
||||||
|
#define SECP256K1_MODULE_CHILLDKG_CERTEQ_H
|
||||||
|
|
||||||
|
#include "../../../include/secp256k1.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* This file contains the internal CertEq equality-check sub-protocol of the
|
||||||
|
* ChillDKG module, mirroring the certeq_* functions of
|
||||||
|
* chilldkg_ref/chilldkg.py of the bip-frost-dkg reference implementation.
|
||||||
|
*
|
||||||
|
* The CertEq message of participant i is
|
||||||
|
* pad33("BIP DKG/certeq message") || u32be(i) || eq_input
|
||||||
|
* signed with plain BIP 340 (tag prefix "BIP0340") under the participant's
|
||||||
|
* host key. */
|
||||||
|
|
||||||
|
/* Produce the CertEq signature of the given participant over eq_input
|
||||||
|
* (certeq_participant_step). Returns 1 on success and 0 if hostseckey32 is
|
||||||
|
* invalid. On failure, sig64 is set to zero. */
|
||||||
|
static int secp256k1_chilldkg_certeq_participant_step(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, uint32_t participant_id, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *aux_rand32);
|
||||||
|
|
||||||
|
/* Verify all n CertEq signatures of a certificate (64 bytes per participant)
|
||||||
|
* against the host public keys (certeq_verify). The signature of participant
|
||||||
|
* i is verified against the x-only encoding of hostpubkeys33[i]; the message
|
||||||
|
* commits to the full 33-byte key via eq_input, so dropping the sign byte is
|
||||||
|
* okay (see the reference). Returns 1 if all signatures are valid and 0
|
||||||
|
* otherwise; in the latter case *fault_index receives the index of the first
|
||||||
|
* invalid signature. */
|
||||||
|
static int secp256k1_chilldkg_certeq_verify(const secp256k1_context *ctx, const unsigned char *hostpubkeys33, size_t n, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *cert, uint32_t *fault_index);
|
||||||
|
|
||||||
|
#endif
|
||||||
58
src/modules/chilldkg/certeq_impl.h
Normal file
58
src/modules/chilldkg/certeq_impl.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/***********************************************************************
|
||||||
|
* Distributed under the MIT software license, see the accompanying *
|
||||||
|
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H
|
||||||
|
#define SECP256K1_MODULE_CHILLDKG_CERTEQ_IMPL_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "../../../include/secp256k1.h"
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "certeq.h"
|
||||||
|
#include "../../util.h"
|
||||||
|
|
||||||
|
/* The maximum length of an eq_input (and thus of the variable-length part of
|
||||||
|
* a CertEq message): 4 + 33*t + 33*n + 33*n + 32*n with t, n <=
|
||||||
|
* SECP256K1_CHILLDKG_MAX_PARTICIPANTS. */
|
||||||
|
#define SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN (4 + 131 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS)
|
||||||
|
|
||||||
|
/* certeq_message: pad33("BIP DKG/certeq message") || u32be(participant_id) ||
|
||||||
|
* x. msg must hold 37 + x_len bytes. */
|
||||||
|
static void secp256k1_chilldkg_certeq_message(unsigned char *msg, const unsigned char *x, size_t x_len, uint32_t participant_id) {
|
||||||
|
secp256k1_chilldkg_pad33(msg, "BIP DKG/certeq message");
|
||||||
|
secp256k1_write_be32(msg + 33, participant_id);
|
||||||
|
memcpy(msg + 37, x, x_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_chilldkg_certeq_participant_step(const secp256k1_context *ctx, unsigned char *sig64, const unsigned char *hostseckey32, uint32_t participant_id, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *aux_rand32) {
|
||||||
|
unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN);
|
||||||
|
secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, participant_id);
|
||||||
|
ret = secp256k1_chilldkg_schnorrsig_sign(ctx, sig64, msg, 37 + eq_input_len, hostseckey32, aux_rand32, "BIP0340");
|
||||||
|
secp256k1_memclear_explicit(msg, sizeof(msg));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_chilldkg_certeq_verify(const secp256k1_context *ctx, const unsigned char *hostpubkeys33, size_t n, const unsigned char *eq_input, size_t eq_input_len, const unsigned char *cert, uint32_t *fault_index) {
|
||||||
|
unsigned char msg[37 + SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
VERIFY_CHECK(eq_input_len <= SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_chilldkg_certeq_message(msg, eq_input, eq_input_len, (uint32_t)i);
|
||||||
|
/* Dropping the sign byte from hostpubkeys33[i] is okay because the
|
||||||
|
* message commits to the full host public key. */
|
||||||
|
if (!secp256k1_chilldkg_schnorrsig_verify(ctx, cert + 64 * i, msg, 37 + eq_input_len, hostpubkeys33 + 33 * i + 1, "BIP0340")) {
|
||||||
|
*fault_index = (uint32_t)i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -61,7 +61,7 @@ static int secp256k1_chilldkg_encpedpop_encrypt_multi(const secp256k1_context *c
|
|||||||
* pubnonce (receiver-side ordering in the pad hash). deckey32 is our host
|
* pubnonce (receiver-side ordering in the pad hash). deckey32 is our host
|
||||||
* secret key and enckey33 our host public key.
|
* secret key and enckey33 our host public key.
|
||||||
*
|
*
|
||||||
* Returns SECP256K1_CHILLDKG_SUCCESS on success,
|
* Returns SECP256K1_CHILLDKG_OK on success,
|
||||||
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR (with *fault_index) if
|
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR (with *fault_index) if
|
||||||
* some sender's pubnonce is invalid, and SECP256K1_CHILLDKG_INVALID_INPUT if
|
* some sender's pubnonce is invalid, and SECP256K1_CHILLDKG_INVALID_INPUT if
|
||||||
* deckey32 is invalid. On failure, all pads are cleared. */
|
* deckey32 is invalid. On failure, all pads are cleared. */
|
||||||
@@ -101,7 +101,7 @@ static int secp256k1_chilldkg_encpedpop_participant_step1(const secp256k1_contex
|
|||||||
* output and the EncPedPop eq_input (4 + 33*t + 33*n + 33*n bytes).
|
* output and the EncPedPop eq_input (4 + 33*t + 33*n + 33*n bytes).
|
||||||
*
|
*
|
||||||
* cmsg must be exactly 97*n + 33*(t-1) + 33*n bytes. Returns
|
* cmsg must be exactly 97*n + 33*(t-1) + 33*n bytes. Returns
|
||||||
* SECP256K1_CHILLDKG_SUCCESS on success; otherwise a fault code (with
|
* SECP256K1_CHILLDKG_OK on success; otherwise a fault code (with
|
||||||
* *fault_index set when applicable): FAULTY_COORDINATOR if cmsg is malformed
|
* *fault_index set when applicable): FAULTY_COORDINATOR if cmsg is malformed
|
||||||
* or the pubnonce echo is wrong, FAULTY_PARTICIPANT_OR_COORDINATOR(i) if
|
* or the pubnonce echo is wrong, FAULTY_PARTICIPANT_OR_COORDINATOR(i) if
|
||||||
* sender i's pubnonce is invalid or their pop/commitment is bad, and
|
* sender i's pubnonce is invalid or their pop/commitment is bad, and
|
||||||
@@ -117,7 +117,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c
|
|||||||
* the n summed encrypted secshares. (In pure EncPedPop the coordinator would
|
* the n summed encrypted secshares. (In pure EncPedPop the coordinator would
|
||||||
* send enc_secshares[i] to participant i only; ChillDKG broadcasts them.)
|
* send enc_secshares[i] to participant i only; ChillDKG broadcasts them.)
|
||||||
*
|
*
|
||||||
* Returns SECP256K1_CHILLDKG_SUCCESS on success and
|
* Returns SECP256K1_CHILLDKG_OK on success and
|
||||||
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a participant
|
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a participant
|
||||||
* message is malformed (invalid commitment, or an encrypted share that
|
* message is malformed (invalid commitment, or an encrypted share that
|
||||||
* overflows the group order). */
|
* overflows the group order). */
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decaps_multi(const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
secp256k1_scalar_clear(&deckey);
|
secp256k1_scalar_clear(&deckey);
|
||||||
return SECP256K1_CHILLDKG_SUCCESS;
|
return SECP256K1_CHILLDKG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decrypt_sum(const secp256k1_context *ctx, secp256k1_scalar *out, uint32_t *fault_index, const unsigned char *deckey32, const unsigned char *enckey33, const unsigned char *pubnonces33, const unsigned char *enc_context, size_t enc_context_len, uint32_t participant_id, const secp256k1_scalar *sum_ciphertexts, size_t n) {
|
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decrypt_sum(const secp256k1_context *ctx, secp256k1_scalar *out, uint32_t *fault_index, const unsigned char *deckey32, const unsigned char *enckey33, const unsigned char *pubnonces33, const unsigned char *enc_context, size_t enc_context_len, uint32_t participant_id, const secp256k1_scalar *sum_ciphertexts, size_t n) {
|
||||||
@@ -135,7 +135,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_decrypt_sum(const s
|
|||||||
|
|
||||||
VERIFY_CHECK(n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
VERIFY_CHECK(n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, enckey33, pubnonces33, enc_context, enc_context_len, participant_id, n);
|
fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, enckey33, pubnonces33, enc_context, enc_context_len, participant_id, n);
|
||||||
if (fault == SECP256K1_CHILLDKG_SUCCESS) {
|
if (fault == SECP256K1_CHILLDKG_OK) {
|
||||||
secp256k1_scalar_set_int(out, 0);
|
secp256k1_scalar_set_int(out, 0);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
secp256k1_scalar_add(out, out, &pads[i]);
|
secp256k1_scalar_add(out, out, &pads[i]);
|
||||||
@@ -277,7 +277,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c
|
|||||||
/* secshare = enc_secshare - sum of the pads (decrypt_sum). */
|
/* secshare = enc_secshare - sum of the pads (decrypt_sum). */
|
||||||
secp256k1_chilldkg_encpedpop_serialize_enc_context(enc_context, t, &state->enckeys33[0][0], n);
|
secp256k1_chilldkg_encpedpop_serialize_enc_context(enc_context, t, &state->enckeys33[0][0], n);
|
||||||
fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, state->enckeys33[participant_id], pubnonces, enc_context, 4 + 33 * (size_t)n, participant_id, n);
|
fault = secp256k1_chilldkg_encpedpop_decaps_multi(ctx, pads, fault_index, deckey32, state->enckeys33[participant_id], pubnonces, enc_context, 4 + 33 * (size_t)n, participant_id, n);
|
||||||
if (fault != SECP256K1_CHILLDKG_SUCCESS) {
|
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
secp256k1_scalar_clear(&pads[i]);
|
secp256k1_scalar_clear(&pads[i]);
|
||||||
}
|
}
|
||||||
@@ -297,14 +297,14 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_participant_step2(c
|
|||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
secp256k1_scalar_clear(&pads[i]);
|
secp256k1_scalar_clear(&pads[i]);
|
||||||
}
|
}
|
||||||
if (fault != SECP256K1_CHILLDKG_SUCCESS) {
|
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eq_input += enckeys || pubnonces */
|
/* eq_input += enckeys || pubnonces */
|
||||||
memcpy(eq_input + 4 + 33 * t, &state->enckeys33[0][0], 33 * (size_t)n);
|
memcpy(eq_input + 4 + 33 * t, &state->enckeys33[0][0], 33 * (size_t)n);
|
||||||
memcpy(eq_input + 4 + 33 * t + 33 * (size_t)n, pubnonces, 33 * (size_t)n);
|
memcpy(eq_input + 4 + 33 * t + 33 * (size_t)n, pubnonces, 33 * (size_t)n);
|
||||||
return SECP256K1_CHILLDKG_SUCCESS;
|
return SECP256K1_CHILLDKG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, secp256k1_scalar *enc_secshares, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, const unsigned char *enckeys33, size_t n) {
|
static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, secp256k1_scalar *enc_secshares, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, const unsigned char *enckeys33, size_t n) {
|
||||||
@@ -365,14 +365,14 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_encpedpop_coordinator_step(co
|
|||||||
secp256k1_scalar_clear(&share);
|
secp256k1_scalar_clear(&share);
|
||||||
|
|
||||||
fault = secp256k1_chilldkg_simplpedpop_coordinator_step(ctx, cmsg, dkg_output, eq_input, fault_index, pmsgs, t, (uint32_t)n);
|
fault = secp256k1_chilldkg_simplpedpop_coordinator_step(ctx, cmsg, dkg_output, eq_input, fault_index, pmsgs, t, (uint32_t)n);
|
||||||
if (fault != SECP256K1_CHILLDKG_SUCCESS) {
|
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eq_input += enckeys || pubnonces */
|
/* eq_input += enckeys || pubnonces */
|
||||||
memcpy(eq_input + 4 + 33 * t, enckeys33, 33 * n);
|
memcpy(eq_input + 4 + 33 * t, enckeys33, 33 * n);
|
||||||
memcpy(eq_input + 4 + 33 * t + 33 * n, cmsg + simpl_cmsg_len, 33 * n);
|
memcpy(eq_input + 4 + 33 * t + 33 * n, cmsg + simpl_cmsg_len, 33 * n);
|
||||||
return SECP256K1_CHILLDKG_SUCCESS;
|
return SECP256K1_CHILLDKG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,11 +6,440 @@
|
|||||||
#ifndef SECP256K1_MODULE_CHILLDKG_MAIN_H
|
#ifndef SECP256K1_MODULE_CHILLDKG_MAIN_H
|
||||||
#define SECP256K1_MODULE_CHILLDKG_MAIN_H
|
#define SECP256K1_MODULE_CHILLDKG_MAIN_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "../../../include/secp256k1_chilldkg.h"
|
#include "../../../include/secp256k1_chilldkg.h"
|
||||||
|
|
||||||
#include "util_impl.h"
|
#include "util_impl.h"
|
||||||
#include "vss_impl.h"
|
#include "vss_impl.h"
|
||||||
#include "simplpedpop_impl.h"
|
#include "simplpedpop_impl.h"
|
||||||
#include "encpedpop_impl.h"
|
#include "encpedpop_impl.h"
|
||||||
|
#include "certeq_impl.h"
|
||||||
|
|
||||||
|
/* ARG_CHECK returns 0, which would read as SECP256K1_CHILLDKG_OK in the
|
||||||
|
* enum-returning public functions of this module. Use this variant there. */
|
||||||
|
#define SECP256K1_CHILLDKG_ARG_CHECK(cond) do { \
|
||||||
|
if (EXPECT(!(cond), 0)) { \
|
||||||
|
secp256k1_callback_call(&ctx->illegal_callback, #cond); \
|
||||||
|
return SECP256K1_CHILLDKG_INVALID_INPUT; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Validate the session parameters (params_validate in chilldkg_ref): it must
|
||||||
|
* hold that 1 <= t <= n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS (the reference
|
||||||
|
* allows n up to 2^32 - 1), all host public keys must be valid compressed
|
||||||
|
* public keys (the infinity encoding is not a valid public key), and there
|
||||||
|
* must be no duplicates. */
|
||||||
|
static int secp256k1_chilldkg_params_validate(const unsigned char *hostpubkeys33, size_t n, uint32_t t) {
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
if (t < 1 || n < 1 || t > n || n > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_ge hostpubkey;
|
||||||
|
if (!secp256k1_chilldkg_point_load(&hostpubkey, hostpubkeys33 + 33 * i)
|
||||||
|
|| secp256k1_ge_is_infinity(&hostpubkey)) {
|
||||||
|
/* InvalidHostPubkeyError(i) in the reference. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
for (j = i + 1; j < n; j++) {
|
||||||
|
if (secp256k1_memcmp_var(hostpubkeys33 + 33 * i, hostpubkeys33 + 33 * j, 33) == 0) {
|
||||||
|
/* DuplicateHostPubkeyError in the reference. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char secp256k1_chilldkg_participant_state1_magic[4] = { 0x3f, 0x2c, 0x9e, 0x51 };
|
||||||
|
static const unsigned char secp256k1_chilldkg_participant_state2_magic[4] = { 0x7a, 0xd1, 0x44, 0x0b };
|
||||||
|
|
||||||
|
/* A state1 object consists of
|
||||||
|
* - 4 byte magic set during initialization to allow detecting an
|
||||||
|
* uninitialized object
|
||||||
|
* - 4 byte threshold t, 4 byte participant count n, 4 byte participant_id
|
||||||
|
* (big-endian)
|
||||||
|
* - 33 byte commitment to the secret (compressed encoding with infinity)
|
||||||
|
* - 33 byte pubnonce
|
||||||
|
* - 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS byte host public keys (only the
|
||||||
|
* first n entries are meaningful)
|
||||||
|
* The state contains no secret key material. */
|
||||||
|
static void secp256k1_chilldkg_participant_state1_save(secp256k1_chilldkg_participant_state1 *state, const secp256k1_chilldkg_encpedpop_participant_state *state_i) {
|
||||||
|
unsigned char *ptr = state->data;
|
||||||
|
|
||||||
|
memcpy(ptr, secp256k1_chilldkg_participant_state1_magic, 4);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_write_be32(ptr, state_i->simpl_state.t);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_write_be32(ptr, state_i->simpl_state.n);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_write_be32(ptr, state_i->simpl_state.participant_id);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_chilldkg_point_save(ptr, &state_i->simpl_state.com_to_secret);
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(ptr, state_i->pubnonce33, 33);
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(ptr, &state_i->enckeys33[0][0], 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
|
VERIFY_CHECK(ptr + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS == state->data + sizeof(state->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_chilldkg_participant_state1_load(const secp256k1_context *ctx, secp256k1_chilldkg_encpedpop_participant_state *state_i, const secp256k1_chilldkg_participant_state1 *state) {
|
||||||
|
const unsigned char *ptr = state->data;
|
||||||
|
|
||||||
|
ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_chilldkg_participant_state1_magic, 4) == 0);
|
||||||
|
ptr += 4;
|
||||||
|
state_i->simpl_state.t = secp256k1_read_be32(ptr);
|
||||||
|
ptr += 4;
|
||||||
|
state_i->simpl_state.n = secp256k1_read_be32(ptr);
|
||||||
|
ptr += 4;
|
||||||
|
state_i->simpl_state.participant_id = secp256k1_read_be32(ptr);
|
||||||
|
ptr += 4;
|
||||||
|
/* The remaining contents were written by state1_save. */
|
||||||
|
VERIFY_CHECK(state_i->simpl_state.t >= 1
|
||||||
|
&& state_i->simpl_state.t <= state_i->simpl_state.n
|
||||||
|
&& state_i->simpl_state.n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS
|
||||||
|
&& state_i->simpl_state.participant_id < state_i->simpl_state.n);
|
||||||
|
/* This load always succeeds; call it unconditionally (it must not sit
|
||||||
|
* inside VERIFY_CHECK, which is compiled out in noverify builds). */
|
||||||
|
if (!secp256k1_chilldkg_point_load(&state_i->simpl_state.com_to_secret, ptr)) {
|
||||||
|
VERIFY_CHECK(0);
|
||||||
|
secp256k1_ge_set_infinity(&state_i->simpl_state.com_to_secret);
|
||||||
|
}
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(state_i->pubnonce33, ptr, 33);
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(&state_i->enckeys33[0][0], ptr, 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t t;
|
||||||
|
uint32_t n;
|
||||||
|
/* Only the first 4 + 33*t + 98*n bytes are meaningful. */
|
||||||
|
unsigned char eq_input[SECP256K1_CHILLDKG_MAX_EQ_INPUT_LEN];
|
||||||
|
secp256k1_chilldkg_simplpedpop_dkg_output dkg_output;
|
||||||
|
} secp256k1_chilldkg_participant_state2_internal;
|
||||||
|
|
||||||
|
/* A state2 object consists of
|
||||||
|
* - 4 byte magic
|
||||||
|
* - 4 byte threshold t, 4 byte participant count n (big-endian)
|
||||||
|
* - eq_input (fixed-capacity buffer)
|
||||||
|
* - 32 byte (tweaked) secret share
|
||||||
|
* - 33 byte threshold public key
|
||||||
|
* - 33*SECP256K1_CHILLDKG_MAX_PARTICIPANTS byte public shares (only the first
|
||||||
|
* n entries are meaningful)
|
||||||
|
* The state contains the secret share and must be kept secret. */
|
||||||
|
static void secp256k1_chilldkg_participant_state2_save(secp256k1_chilldkg_participant_state2 *state, const secp256k1_chilldkg_participant_state2_internal *state_i) {
|
||||||
|
unsigned char *ptr = state->data;
|
||||||
|
|
||||||
|
memcpy(ptr, secp256k1_chilldkg_participant_state2_magic, 4);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_write_be32(ptr, state_i->t);
|
||||||
|
ptr += 4;
|
||||||
|
secp256k1_write_be32(ptr, state_i->n);
|
||||||
|
ptr += 4;
|
||||||
|
memcpy(ptr, state_i->eq_input, sizeof(state_i->eq_input));
|
||||||
|
ptr += sizeof(state_i->eq_input);
|
||||||
|
memcpy(ptr, state_i->dkg_output.secshare32, 32);
|
||||||
|
ptr += 32;
|
||||||
|
memcpy(ptr, state_i->dkg_output.thresh_pk33, 33);
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(ptr, &state_i->dkg_output.pubshares33[0][0], 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
|
VERIFY_CHECK(ptr + 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS == state->data + sizeof(state->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int secp256k1_chilldkg_participant_state2_load(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state2_internal *state_i, const secp256k1_chilldkg_participant_state2 *state) {
|
||||||
|
const unsigned char *ptr = state->data;
|
||||||
|
|
||||||
|
ARG_CHECK(secp256k1_memcmp_var(ptr, secp256k1_chilldkg_participant_state2_magic, 4) == 0);
|
||||||
|
ptr += 4;
|
||||||
|
state_i->t = secp256k1_read_be32(ptr);
|
||||||
|
ptr += 4;
|
||||||
|
state_i->n = secp256k1_read_be32(ptr);
|
||||||
|
ptr += 4;
|
||||||
|
/* The remaining contents were written by state2_save. */
|
||||||
|
VERIFY_CHECK(state_i->t >= 1
|
||||||
|
&& state_i->t <= state_i->n
|
||||||
|
&& state_i->n <= SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
|
memcpy(state_i->eq_input, ptr, sizeof(state_i->eq_input));
|
||||||
|
ptr += sizeof(state_i->eq_input);
|
||||||
|
memcpy(state_i->dkg_output.secshare32, ptr, 32);
|
||||||
|
ptr += 32;
|
||||||
|
memcpy(state_i->dkg_output.thresh_pk33, ptr, 33);
|
||||||
|
ptr += 33;
|
||||||
|
memcpy(&state_i->dkg_output.pubshares33[0][0], ptr, 33 * SECP256K1_CHILLDKG_MAX_PARTICIPANTS);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secp256k1_chilldkg_hostpubkey_gen(const secp256k1_context *ctx, unsigned char *hostpubkey33, const unsigned char *hostseckey32) {
|
||||||
|
secp256k1_scalar seckey;
|
||||||
|
secp256k1_gej pubkeyj;
|
||||||
|
secp256k1_ge pubkey;
|
||||||
|
int overflow;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
|
ARG_CHECK(hostpubkey33 != NULL);
|
||||||
|
ARG_CHECK(hostseckey32 != NULL);
|
||||||
|
|
||||||
|
memset(hostpubkey33, 0, 33);
|
||||||
|
secp256k1_scalar_set_b32(&seckey, hostseckey32, &overflow);
|
||||||
|
ret = !overflow & !secp256k1_scalar_is_zero(&seckey);
|
||||||
|
/* Branching on the validity of the host secret key is fine: whether the
|
||||||
|
* caller's key is in range 1..n-1 is not secret. */
|
||||||
|
secp256k1_declassify(ctx, &ret, sizeof(ret));
|
||||||
|
if (ret) {
|
||||||
|
/* pubkey_gen_plain in the reference (IndividualPubkey of BIP 327). */
|
||||||
|
secp256k1_ecmult_gen_gej(&ctx->ecmult_gen_ctx, &pubkeyj, &seckey);
|
||||||
|
secp256k1_ge_set_gej(&pubkey, &pubkeyj);
|
||||||
|
secp256k1_chilldkg_point_save(hostpubkey33, &pubkey);
|
||||||
|
secp256k1_gej_clear(&pubkeyj);
|
||||||
|
}
|
||||||
|
secp256k1_scalar_clear(&seckey);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secp256k1_chilldkg_params_hash(const secp256k1_context *ctx, unsigned char *hash32, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold) {
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(hash32 != NULL);
|
||||||
|
ARG_CHECK(hostpubkeys33 != NULL);
|
||||||
|
|
||||||
|
memset(hash32, 0, 32);
|
||||||
|
if (!secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
secp256k1_chilldkg_params_hash_internal(secp256k1_get_hash_context(ctx), hash32, hostpubkeys33, n_participants, threshold);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_chilldkg_participant_msg1_len(size_t n_participants, uint32_t threshold) {
|
||||||
|
if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 33 * (size_t)threshold + 32 * n_participants + 97;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_chilldkg_coordinator_msg1_len(size_t n_participants, uint32_t threshold) {
|
||||||
|
if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 162 * n_participants + 33 * (size_t)(threshold - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_chilldkg_participant_msg2_len(void) {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_chilldkg_coordinator_msg2_len(size_t n_participants) {
|
||||||
|
if (n_participants < 1 || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 64 * n_participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t secp256k1_chilldkg_recovery_data_len(size_t n_participants, uint32_t threshold) {
|
||||||
|
if (threshold < 1 || n_participants < 1 || threshold > n_participants || n_participants > SECP256K1_CHILLDKG_MAX_PARTICIPANTS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 4 + 33 * (size_t)threshold + 162 * n_participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
int secp256k1_chilldkg_participant_step1(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state1 *state1, unsigned char *pmsg1, const unsigned char *hostseckey32, const unsigned char *hostpubkeys33, size_t n_participants, uint32_t threshold, const unsigned char *random32) {
|
||||||
|
secp256k1_chilldkg_encpedpop_participant_state enc_state;
|
||||||
|
unsigned char hostpubkey33[33];
|
||||||
|
uint32_t participant_id = 0;
|
||||||
|
size_t pmsg1_len;
|
||||||
|
size_t i;
|
||||||
|
int found = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
|
ARG_CHECK(state1 != NULL);
|
||||||
|
ARG_CHECK(pmsg1 != NULL);
|
||||||
|
ARG_CHECK(hostseckey32 != NULL);
|
||||||
|
ARG_CHECK(hostpubkeys33 != NULL);
|
||||||
|
ARG_CHECK(random32 != NULL);
|
||||||
|
|
||||||
|
memset(state1->data, 0, sizeof(state1->data));
|
||||||
|
pmsg1_len = secp256k1_chilldkg_participant_msg1_len(n_participants, threshold);
|
||||||
|
|
||||||
|
/* params_validate, then hostpubkey_gen (HostSeckeyError if invalid). */
|
||||||
|
if (secp256k1_chilldkg_params_validate(hostpubkeys33, n_participants, threshold)
|
||||||
|
&& secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32)) {
|
||||||
|
/* hostpubkeys.index(hostpubkey); the params validation rules out
|
||||||
|
* duplicates, so there is at most one match. */
|
||||||
|
for (i = 0; i < n_participants; i++) {
|
||||||
|
if (secp256k1_memcmp_var(hostpubkeys33 + 33 * i, hostpubkey33, 33) == 0) {
|
||||||
|
participant_id = (uint32_t)i;
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* HostSeckeyError if there is no match; RandomnessError if the
|
||||||
|
* randomness is all zeroes (guards against a malfunctioning random
|
||||||
|
* number generator). */
|
||||||
|
if (found && !secp256k1_is_zero_array(random32, 32)) {
|
||||||
|
/* In EncPedPop, both the seed and the deckey are the host secret
|
||||||
|
* key, and the enckeys are the host public keys (see
|
||||||
|
* chilldkg_ref/chilldkg.py participant_step1). */
|
||||||
|
ret = secp256k1_chilldkg_encpedpop_participant_step1(ctx, &enc_state, pmsg1, hostseckey32, hostseckey32, hostpubkeys33, threshold, participant_id, random32, n_participants);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
secp256k1_chilldkg_participant_state1_save(state1, &enc_state);
|
||||||
|
} else {
|
||||||
|
memset(state1->data, 0, sizeof(state1->data));
|
||||||
|
if (pmsg1_len > 0) {
|
||||||
|
memset(pmsg1, 0, pmsg1_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_chilldkg_fault secp256k1_chilldkg_participant_step2(const secp256k1_context *ctx, secp256k1_chilldkg_participant_state2 *state2, unsigned char *sig64, uint32_t *fault_index, const secp256k1_chilldkg_participant_state1 *state1, const unsigned char *hostseckey32, const unsigned char *cmsg1, const unsigned char *aux_rand32) {
|
||||||
|
secp256k1_chilldkg_encpedpop_participant_state enc_state;
|
||||||
|
secp256k1_chilldkg_participant_state2_internal state2i;
|
||||||
|
unsigned char hostpubkey33[33];
|
||||||
|
secp256k1_scalar enc_secshares[SECP256K1_CHILLDKG_MAX_PARTICIPANTS];
|
||||||
|
secp256k1_chilldkg_fault fault = SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||||
|
size_t n, t, enc_cmsg_len, eq_input_len;
|
||||||
|
uint32_t participant_id;
|
||||||
|
size_t i;
|
||||||
|
int overflow;
|
||||||
|
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(state2 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(sig64 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(state1 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(hostseckey32 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(cmsg1 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(aux_rand32 != NULL);
|
||||||
|
|
||||||
|
memset(&state2i, 0, sizeof(state2i));
|
||||||
|
memset(state2->data, 0, sizeof(state2->data));
|
||||||
|
memset(sig64, 0, 64);
|
||||||
|
*fault_index = UINT32_MAX;
|
||||||
|
|
||||||
|
if (!secp256k1_chilldkg_participant_state1_load(ctx, &enc_state, state1)) {
|
||||||
|
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
t = enc_state.simpl_state.t;
|
||||||
|
n = enc_state.simpl_state.n;
|
||||||
|
participant_id = enc_state.simpl_state.participant_id;
|
||||||
|
|
||||||
|
/* HostSeckeyError if the host secret key is invalid or does not match the
|
||||||
|
* one used in participant_step1. */
|
||||||
|
if (!secp256k1_chilldkg_hostpubkey_gen(ctx, hostpubkey33, hostseckey32)
|
||||||
|
|| secp256k1_memcmp_var(hostpubkey33, enc_state.enckeys33[participant_id], 33) != 0) {
|
||||||
|
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CoordinatorMsg1.from_bytes: cmsg1 = enc_cmsg || enc_secshares, where
|
||||||
|
* enc_cmsg has 97*n + 33*(t-1) + 33*n bytes. The encrypted shares are
|
||||||
|
* parsed checked; an overflow blames the coordinator (MsgParseError ->
|
||||||
|
* FaultyCoordinatorError in the reference). */
|
||||||
|
enc_cmsg_len = 97 * n + 33 * (t - 1) + 33 * n;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_scalar_set_b32(&enc_secshares[i], cmsg1 + enc_cmsg_len + 32 * i, &overflow);
|
||||||
|
if (overflow) {
|
||||||
|
fault = SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eq_input_len = 4 + 33 * t + 66 * n;
|
||||||
|
fault = secp256k1_chilldkg_encpedpop_participant_step2(ctx, &state2i.dkg_output, state2i.eq_input, fault_index, &enc_state, hostseckey32, cmsg1, enc_cmsg_len, &enc_secshares[participant_id]);
|
||||||
|
if (fault != SECP256K1_CHILLDKG_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Include the enc_secshares in eq_input to ensure that participants agree
|
||||||
|
* on all shares, which in turn ensures that they have the right recovery
|
||||||
|
* data. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_scalar_get_b32(state2i.eq_input + eq_input_len + 32 * i, &enc_secshares[i]);
|
||||||
|
}
|
||||||
|
eq_input_len += 32 * n;
|
||||||
|
state2i.t = (uint32_t)t;
|
||||||
|
state2i.n = (uint32_t)n;
|
||||||
|
|
||||||
|
/* pmsg2 = certeq_participant_step(hostseckey, participant_id, eq_input, aux_rand) */
|
||||||
|
if (!secp256k1_chilldkg_certeq_participant_step(ctx, sig64, hostseckey32, participant_id, state2i.eq_input, eq_input_len, aux_rand32)) {
|
||||||
|
/* Unreachable: the host secret key was validated above. */
|
||||||
|
fault = SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||||
|
memset(sig64, 0, 64);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
secp256k1_chilldkg_participant_state2_save(state2, &state2i);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_scalar_clear(&enc_secshares[i]);
|
||||||
|
}
|
||||||
|
/* state2i contains the secret share. */
|
||||||
|
secp256k1_memclear_explicit(&state2i, sizeof(state2i));
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
|
||||||
|
secp256k1_chilldkg_fault secp256k1_chilldkg_participant_finalize(const secp256k1_context *ctx, unsigned char *secshare32, unsigned char *thresh_pk33, unsigned char *pubshares33, unsigned char *recovery, uint32_t *fault_index, const secp256k1_chilldkg_participant_state2 *state2, const unsigned char *cmsg2) {
|
||||||
|
secp256k1_chilldkg_participant_state2_internal state2i;
|
||||||
|
size_t n, t, eq_input_len;
|
||||||
|
|
||||||
|
VERIFY_CHECK(ctx != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(secshare32 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(thresh_pk33 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(pubshares33 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(recovery != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(fault_index != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(state2 != NULL);
|
||||||
|
SECP256K1_CHILLDKG_ARG_CHECK(cmsg2 != NULL);
|
||||||
|
|
||||||
|
memset(secshare32, 0, 32);
|
||||||
|
memset(thresh_pk33, 0, 33);
|
||||||
|
*fault_index = UINT32_MAX;
|
||||||
|
|
||||||
|
/* On a state load failure (uninitialized state), only secshare32 and
|
||||||
|
* thresh_pk33 are zeroed: the sizes of pubshares33 and recovery depend on
|
||||||
|
* the state contents. */
|
||||||
|
if (!secp256k1_chilldkg_participant_state2_load(ctx, &state2i, state2)) {
|
||||||
|
return SECP256K1_CHILLDKG_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
t = state2i.t;
|
||||||
|
n = state2i.n;
|
||||||
|
eq_input_len = 4 + 33 * t + 98 * n;
|
||||||
|
|
||||||
|
memset(pubshares33, 0, 33 * n);
|
||||||
|
memset(recovery, 0, 4 + 33 * t + 162 * n);
|
||||||
|
|
||||||
|
/* certeq_verify: the host public keys are part of eq_input (at offset
|
||||||
|
* 4 + 33*t). An invalid signature in the certificate blames the
|
||||||
|
* coordinator; fault_index receives the index of the first invalid
|
||||||
|
* signature as diagnostic information. */
|
||||||
|
if (!secp256k1_chilldkg_certeq_verify(ctx, state2i.eq_input + 4 + 33 * t, n, state2i.eq_input, eq_input_len, cmsg2, fault_index)) {
|
||||||
|
secp256k1_memclear_explicit(&state2i, sizeof(state2i));
|
||||||
|
return SECP256K1_CHILLDKG_FAULTY_COORDINATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(secshare32, state2i.dkg_output.secshare32, 32);
|
||||||
|
memcpy(thresh_pk33, state2i.dkg_output.thresh_pk33, 33);
|
||||||
|
memcpy(pubshares33, &state2i.dkg_output.pubshares33[0][0], 33 * n);
|
||||||
|
/* recovery data = eq_input || cert */
|
||||||
|
memcpy(recovery, state2i.eq_input, eq_input_len);
|
||||||
|
memcpy(recovery + eq_input_len, cmsg2, 64 * n);
|
||||||
|
|
||||||
|
/* state2i contains the secret share. */
|
||||||
|
secp256k1_memclear_explicit(&state2i, sizeof(state2i));
|
||||||
|
return SECP256K1_CHILLDKG_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ static void secp256k1_chilldkg_simplpedpop_participant_step2_prepare_secshare(se
|
|||||||
* verification). Outputs the DKG output and the SimplPedPop contribution to
|
* verification). Outputs the DKG output and the SimplPedPop contribution to
|
||||||
* eq_input (4 + 33*t bytes).
|
* eq_input (4 + 33*t bytes).
|
||||||
*
|
*
|
||||||
* cmsg must be exactly 97*n + 33*(t-1) bytes. Returns SECP256K1_CHILLDKG_SUCCESS
|
* cmsg must be exactly 97*n + 33*(t-1) bytes. Returns SECP256K1_CHILLDKG_OK
|
||||||
* on success; otherwise a fault code (with *fault_index set when applicable):
|
* on success; otherwise a fault code (with *fault_index set when applicable):
|
||||||
* - FAULTY_COORDINATOR if cmsg is malformed or the echo of our own
|
* - FAULTY_COORDINATOR if cmsg is malformed or the echo of our own
|
||||||
* commitment to the secret is wrong;
|
* commitment to the secret is wrong;
|
||||||
@@ -109,7 +109,7 @@ static void secp256k1_chilldkg_simplpedpop_assemble_sum_coms(secp256k1_ge *sum_c
|
|||||||
* eq_input (4 + 33*t bytes). The pops are NOT verified here (participants
|
* eq_input (4 + 33*t bytes). The pops are NOT verified here (participants
|
||||||
* verify them in step 2).
|
* verify them in step 2).
|
||||||
*
|
*
|
||||||
* Outputs cmsg (97*n + 33*(t-1) bytes). Returns SECP256K1_CHILLDKG_SUCCESS on
|
* Outputs cmsg (97*n + 33*(t-1) bytes). Returns SECP256K1_CHILLDKG_OK on
|
||||||
* success and SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a
|
* success and SECP256K1_CHILLDKG_FAULTY_PARTICIPANT (with *fault_index) if a
|
||||||
* participant message is malformed. */
|
* participant message is malformed. */
|
||||||
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, uint32_t n);
|
static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step(const secp256k1_context *ctx, unsigned char *cmsg, secp256k1_chilldkg_simplpedpop_dkg_output *dkg_output, unsigned char *eq_input, uint32_t *fault_index, const unsigned char *const *pmsgs, uint32_t t, uint32_t n);
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_participant_step2
|
|||||||
|
|
||||||
secp256k1_scalar_clear(&tweak);
|
secp256k1_scalar_clear(&tweak);
|
||||||
secp256k1_scalar_clear(&secshare_tweaked);
|
secp256k1_scalar_clear(&secshare_tweaked);
|
||||||
return SECP256K1_CHILLDKG_SUCCESS;
|
return SECP256K1_CHILLDKG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_chilldkg_simplpedpop_assemble_sum_coms(secp256k1_ge *sum_coms, const secp256k1_ge *coms_to_secrets, const secp256k1_ge *sum_coms_to_nonconst_terms, size_t n, size_t t) {
|
static void secp256k1_chilldkg_simplpedpop_assemble_sum_coms(secp256k1_ge *sum_coms, const secp256k1_ge *coms_to_secrets, const secp256k1_ge *sum_coms_to_nonconst_terms, size_t n, size_t t) {
|
||||||
@@ -350,7 +350,7 @@ static secp256k1_chilldkg_fault secp256k1_chilldkg_simplpedpop_coordinator_step(
|
|||||||
}
|
}
|
||||||
|
|
||||||
secp256k1_scalar_clear(&tweak);
|
secp256k1_scalar_clear(&tweak);
|
||||||
return SECP256K1_CHILLDKG_SUCCESS;
|
return SECP256K1_CHILLDKG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -201,6 +201,54 @@ static const unsigned char vec_enc_pubshares[3][33] = {
|
|||||||
/* encpedpop n = 3, t = 2 */
|
/* encpedpop n = 3, t = 2 */
|
||||||
/* all python-side sanity checks passed */
|
/* all python-side sanity checks passed */
|
||||||
|
|
||||||
|
static const unsigned char vec3_hostseckeys[3][32] = {
|
||||||
|
{ 0x63, 0xf1, 0xca, 0xd7, 0x7b, 0xa9, 0x64, 0x63, 0x48, 0x03, 0xa3, 0x11, 0x03, 0x0f, 0x5c, 0x74, 0x30, 0x5b, 0x9c, 0x06, 0x24, 0x13, 0xc3, 0xbe, 0xc0, 0xe1, 0xbc, 0xf4, 0x39, 0xb3, 0x35, 0xcf },
|
||||||
|
{ 0xba, 0x8b, 0x85, 0xb8, 0xd3, 0x0d, 0xcf, 0x07, 0x87, 0xc6, 0x5b, 0x7c, 0x6a, 0x46, 0x08, 0xef, 0xc7, 0x25, 0x35, 0x52, 0x8d, 0xc5, 0x4f, 0xf1, 0xa7, 0x13, 0x52, 0x32, 0x6b, 0x51, 0x71, 0xb1 },
|
||||||
|
{ 0x73, 0xed, 0x74, 0x96, 0x68, 0x50, 0xa1, 0x21, 0x61, 0x59, 0xd6, 0xe1, 0xf8, 0x07, 0xcc, 0xfb, 0xfa, 0x89, 0x3d, 0xc8, 0xa9, 0x07, 0xfe, 0xfd, 0xe2, 0x34, 0x01, 0xd0, 0xd2, 0xe9, 0xa3, 0xa8 },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_hostpubkeys[3][33] = {
|
||||||
|
{ 0x02, 0x2d, 0x9b, 0xc8, 0xa8, 0x44, 0x57, 0xc7, 0x51, 0x00, 0x1f, 0x71, 0x4a, 0xd9, 0xac, 0x72, 0x82, 0x8a, 0x01, 0xe5, 0x31, 0xbe, 0x63, 0xe7, 0xfc, 0x3c, 0x4d, 0x37, 0x0c, 0x2f, 0xec, 0xd8, 0x43 },
|
||||||
|
{ 0x03, 0x34, 0xbe, 0xe4, 0x54, 0x9f, 0x86, 0x95, 0xd8, 0x96, 0xa3, 0xf0, 0x60, 0x40, 0xe0, 0x26, 0x3c, 0x41, 0x90, 0x54, 0xf3, 0xb8, 0xc7, 0x83, 0xa7, 0x7a, 0x77, 0x02, 0x82, 0x86, 0x14, 0x97, 0x3a },
|
||||||
|
{ 0x02, 0x85, 0xe6, 0xb7, 0xa7, 0xfb, 0x26, 0x5f, 0x38, 0xb9, 0xad, 0xc3, 0x9e, 0x51, 0xd4, 0xac, 0x2d, 0xfb, 0x0f, 0x31, 0xa6, 0xf1, 0x8e, 0x7f, 0xf8, 0xae, 0x2f, 0x3c, 0xa7, 0xbc, 0xaa, 0x7d, 0xcf },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_params_hash[32] = { 0x40, 0x6a, 0x61, 0xe7, 0xd3, 0x91, 0x7e, 0xc0, 0x8d, 0x10, 0x51, 0x38, 0x62, 0xab, 0xbb, 0x40, 0x42, 0x14, 0x39, 0x7c, 0x81, 0x5b, 0x32, 0x60, 0x87, 0xb8, 0x0b, 0x90, 0x31, 0xee, 0xf6, 0xbb };
|
||||||
|
static const unsigned char vec3_randoms[3][32] = {
|
||||||
|
{ 0x47, 0x1f, 0x0e, 0xfc, 0x32, 0x6d, 0xaa, 0x68, 0xbb, 0x76, 0x70, 0x31, 0x88, 0x3a, 0xff, 0x5a, 0xcd, 0xc8, 0xca, 0xad, 0x58, 0x5b, 0x0f, 0x5d, 0x13, 0x52, 0xf7, 0x54, 0x70, 0x6c, 0x23, 0xcc },
|
||||||
|
{ 0xb6, 0x2d, 0x69, 0xb3, 0x7f, 0x3b, 0x20, 0xbd, 0x57, 0x7a, 0xf0, 0x05, 0x7d, 0xd5, 0x11, 0x52, 0xe2, 0xea, 0x90, 0x1c, 0xe1, 0x0f, 0xe9, 0x6c, 0x25, 0x68, 0x55, 0x1d, 0xda, 0xfc, 0xa1, 0x9d },
|
||||||
|
{ 0xda, 0x99, 0x81, 0x45, 0xd2, 0x74, 0x0f, 0x62, 0xbe, 0x66, 0x57, 0x5b, 0x5f, 0xc1, 0xfd, 0x8d, 0xf4, 0x42, 0x53, 0x72, 0xbb, 0x59, 0x5a, 0x5b, 0xe5, 0x55, 0x17, 0xb9, 0xfe, 0xac, 0x3e, 0x21 },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_aux_rands[3][32] = {
|
||||||
|
{ 0x43, 0xbb, 0x36, 0xca, 0xf9, 0x05, 0x46, 0x37, 0xdf, 0x41, 0x06, 0x33, 0x10, 0x0c, 0x83, 0x4c, 0x96, 0x5f, 0x6b, 0x88, 0xe9, 0x4c, 0x54, 0x7a, 0x88, 0x0d, 0xce, 0x85, 0x7a, 0xd9, 0x58, 0x66 },
|
||||||
|
{ 0x01, 0x96, 0xeb, 0x2f, 0x75, 0x84, 0x78, 0x28, 0x2d, 0x0a, 0x8f, 0x73, 0x55, 0x90, 0x22, 0x8c, 0x2d, 0x26, 0xef, 0xfe, 0x9e, 0xad, 0xf8, 0x4b, 0xf2, 0xfe, 0x5d, 0xa0, 0x94, 0x3e, 0x64, 0x03 },
|
||||||
|
{ 0x4a, 0xee, 0x4b, 0xc4, 0x92, 0x1b, 0xf2, 0x6e, 0xf1, 0xe2, 0x25, 0x75, 0x1b, 0x4f, 0x5f, 0x3d, 0x5f, 0x9a, 0x16, 0x08, 0x04, 0x45, 0x18, 0x5c, 0x98, 0xb5, 0xbf, 0xb1, 0x70, 0xa7, 0x0a, 0x0d },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_pmsgs1[3][259] = {
|
||||||
|
{ 0x03, 0x13, 0xa8, 0x3d, 0xe5, 0x5f, 0xc3, 0xef, 0x04, 0xe3, 0xd5, 0x0b, 0xe3, 0xe5, 0xae, 0x6f, 0x7d, 0xc8, 0x17, 0x5c, 0x03, 0x61, 0xa2, 0x87, 0xe3, 0x05, 0xac, 0x24, 0xb7, 0xdb, 0x90, 0x5b, 0xa0, 0x02, 0x8e, 0x23, 0x9d, 0x76, 0x52, 0xf4, 0xe2, 0x7b, 0x8f, 0xf7, 0x3b, 0xce, 0xe1, 0xd5, 0xb4, 0xea, 0xf3, 0xc4, 0x1b, 0xef, 0x9d, 0xfc, 0xae, 0x10, 0x53, 0x51, 0xc3, 0x5d, 0xce, 0x73, 0x15, 0xaf, 0x5a, 0x61, 0xbc, 0x3f, 0x93, 0x88, 0x46, 0xad, 0x6e, 0x75, 0x60, 0x32, 0xaf, 0x07, 0x13, 0x50, 0xa5, 0x7f, 0x4d, 0xe5, 0xcc, 0x19, 0x2c, 0xb8, 0x94, 0xc9, 0x05, 0x7e, 0xd1, 0x98, 0x92, 0x80, 0xf4, 0xba, 0x10, 0x30, 0xe5, 0x6a, 0x11, 0xe9, 0xfa, 0xf6, 0x6c, 0xe9, 0x15, 0xcc, 0x29, 0x19, 0xb6, 0x5c, 0x91, 0x3c, 0xbf, 0xcf, 0xf1, 0x92, 0x88, 0xf6, 0xd5, 0x6f, 0x0a, 0x19, 0xb9, 0x06, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0xea, 0x7b, 0xb3, 0xd7, 0x0c, 0xfc, 0x81, 0x31, 0xe7, 0x7c, 0x63, 0x93, 0xad, 0x2a, 0x28, 0xd7, 0x8b, 0x5a, 0xda, 0x3b, 0xc4, 0x18, 0x5a, 0xcb, 0x64, 0x49, 0x5a, 0x4d, 0xfe, 0xde, 0xd9, 0x82, 0xd7, 0xcc, 0x01, 0x2a, 0x67, 0x40, 0x5b, 0x09, 0xe8, 0x61, 0xbd, 0xa2, 0x72, 0xb8, 0x23, 0x1f, 0xa6, 0xaa, 0xe5, 0xee, 0xdd, 0x01, 0x35, 0xa4, 0x13, 0x5d, 0x08, 0xa5, 0xc5, 0x5c, 0xd9, 0xd4, 0xe1, 0x0e, 0x48, 0x6f, 0x44, 0x6c, 0x29, 0x72, 0xe2, 0x25, 0x06, 0x25, 0x37, 0x0e, 0x28, 0x3f, 0x69, 0x26, 0xc2, 0xc1, 0x79, 0x50, 0xad, 0x0a, 0x0b, 0x20, 0xc1, 0xce, 0x41, 0xe1, 0xff, 0x66 },
|
||||||
|
{ 0x03, 0x98, 0xf0, 0x88, 0x65, 0x27, 0x59, 0x6b, 0x2c, 0x49, 0xf6, 0xa3, 0xf6, 0x58, 0x46, 0x52, 0x76, 0xdf, 0x6c, 0xd5, 0xc6, 0x68, 0xe2, 0xdf, 0x88, 0x6b, 0xe6, 0x15, 0x81, 0x60, 0x5e, 0x10, 0xa7, 0x02, 0x8c, 0x88, 0x50, 0xb8, 0x9e, 0xe9, 0xb1, 0xe9, 0x89, 0x8a, 0xb2, 0x61, 0x91, 0xb4, 0xf4, 0xc2, 0x9e, 0x9b, 0x7b, 0x0f, 0x71, 0x27, 0x05, 0xe3, 0xd9, 0x54, 0xb0, 0xaf, 0xa1, 0x40, 0x3c, 0x6c, 0xc5, 0xe6, 0x8a, 0xcd, 0xb0, 0xaf, 0x07, 0x62, 0xb1, 0x3f, 0x24, 0xeb, 0x34, 0xd0, 0x39, 0x72, 0xd5, 0x34, 0xcc, 0x72, 0x02, 0x0c, 0x10, 0x19, 0x44, 0x00, 0xd0, 0x21, 0x3f, 0x0d, 0x7f, 0x1e, 0x0d, 0x08, 0xaa, 0xd3, 0xec, 0x21, 0xff, 0x9b, 0xc7, 0xcb, 0x04, 0x97, 0x79, 0x27, 0xd7, 0xc6, 0xe6, 0xbb, 0x4f, 0x0d, 0x88, 0x7a, 0x70, 0x4a, 0x7d, 0xbd, 0x65, 0x8f, 0xa3, 0xc3, 0xc9, 0x2d, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0xaf, 0xa6, 0x65, 0x5c, 0xee, 0xee, 0x61, 0x74, 0x28, 0x40, 0xb7, 0xf1, 0xaf, 0x76, 0x0d, 0xf2, 0xf6, 0xcc, 0x6d, 0x4e, 0xe0, 0x5a, 0x9a, 0xd1, 0xfc, 0x7b, 0x5d, 0x86, 0x5c, 0x42, 0xc0, 0x52, 0xd5, 0xb6, 0x97, 0xb0, 0x91, 0xdb, 0xf8, 0xde, 0x6d, 0x2d, 0x81, 0xab, 0xff, 0xb5, 0xf0, 0xcb, 0x75, 0xbd, 0x86, 0xe3, 0x86, 0x04, 0x15, 0x68, 0x05, 0x5e, 0xe2, 0xb4, 0x8f, 0x7c, 0xfc, 0x3d, 0x91, 0x54, 0x76, 0x91, 0x11, 0x18, 0x25, 0x84, 0xf4, 0xf9, 0xdf, 0xad, 0x29, 0xc6, 0x2b, 0x57, 0xc1, 0xf1, 0xe4, 0xa5, 0x40, 0xc0, 0x7f, 0xcb, 0x18, 0x65, 0x07, 0x5c, 0xb2, 0x14, 0x6c, 0x2b },
|
||||||
|
{ 0x02, 0xc0, 0xa6, 0xde, 0xcb, 0x4a, 0xd7, 0x34, 0xe9, 0xec, 0x43, 0xbd, 0x50, 0xf3, 0xa6, 0xd6, 0xe8, 0xad, 0xa8, 0x38, 0xe8, 0x44, 0x40, 0x0b, 0xfe, 0x14, 0x7e, 0x46, 0xc8, 0xa1, 0x61, 0x5a, 0x2e, 0x03, 0xc8, 0x14, 0xb5, 0xe1, 0x99, 0xff, 0x42, 0x88, 0x52, 0x78, 0x52, 0x96, 0xc4, 0x57, 0x06, 0x65, 0xde, 0x04, 0x58, 0x15, 0x99, 0xc3, 0xb0, 0xcd, 0x24, 0x7e, 0x67, 0x0c, 0x15, 0x51, 0x01, 0xc2, 0x7b, 0x09, 0xdd, 0x3d, 0x86, 0x90, 0xba, 0x4c, 0x1d, 0x65, 0x33, 0x07, 0x50, 0x7a, 0x2c, 0xb3, 0x06, 0x9e, 0xab, 0xbd, 0xe2, 0xb6, 0xe2, 0x4f, 0x0d, 0x79, 0xb4, 0x0a, 0xb4, 0x90, 0xae, 0x89, 0x48, 0xcc, 0x90, 0x5a, 0x4d, 0xc5, 0xc2, 0xe0, 0x59, 0xda, 0x08, 0x33, 0x1b, 0x82, 0x40, 0x51, 0xfa, 0x0b, 0x07, 0x93, 0xe3, 0x6d, 0x96, 0xaf, 0xeb, 0xf6, 0xfc, 0xef, 0x85, 0x1b, 0x21, 0x94, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x6b, 0xc6, 0x34, 0x69, 0xb1, 0x4e, 0x16, 0xc0, 0x90, 0xdf, 0x4a, 0xc9, 0x3b, 0x3d, 0xbc, 0xee, 0xee, 0x29, 0x96, 0x3e, 0xa4, 0x87, 0x2b, 0x9a, 0xb2, 0x59, 0x4f, 0x81, 0x45, 0xaf, 0xfc, 0x3a, 0xfe, 0x8b, 0xfb, 0x90, 0x3d, 0x9b, 0x91, 0xde, 0x14, 0x0f, 0xee, 0xfb, 0x7a, 0x30, 0x67, 0x6d, 0x0d, 0x0f, 0x0e, 0xe7, 0xd9, 0x1b, 0xb8, 0x99, 0xcf, 0xe6, 0xf9, 0x2c, 0x74, 0x1f, 0xb5, 0xb8, 0x20, 0xab, 0x89, 0x01, 0x21, 0x83, 0xf7, 0x65, 0x7e, 0x27, 0x60, 0xf6, 0xa6, 0x73, 0xfa, 0xef, 0x33, 0x72, 0x77, 0xd3, 0xdc, 0x12, 0xc2, 0xe3, 0x87, 0xa9, 0xd4, 0x57, 0x80, 0x89, 0xab, 0xa2 },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_cmsg1[519] = { 0x03, 0x13, 0xa8, 0x3d, 0xe5, 0x5f, 0xc3, 0xef, 0x04, 0xe3, 0xd5, 0x0b, 0xe3, 0xe5, 0xae, 0x6f, 0x7d, 0xc8, 0x17, 0x5c, 0x03, 0x61, 0xa2, 0x87, 0xe3, 0x05, 0xac, 0x24, 0xb7, 0xdb, 0x90, 0x5b, 0xa0, 0x03, 0x98, 0xf0, 0x88, 0x65, 0x27, 0x59, 0x6b, 0x2c, 0x49, 0xf6, 0xa3, 0xf6, 0x58, 0x46, 0x52, 0x76, 0xdf, 0x6c, 0xd5, 0xc6, 0x68, 0xe2, 0xdf, 0x88, 0x6b, 0xe6, 0x15, 0x81, 0x60, 0x5e, 0x10, 0xa7, 0x02, 0xc0, 0xa6, 0xde, 0xcb, 0x4a, 0xd7, 0x34, 0xe9, 0xec, 0x43, 0xbd, 0x50, 0xf3, 0xa6, 0xd6, 0xe8, 0xad, 0xa8, 0x38, 0xe8, 0x44, 0x40, 0x0b, 0xfe, 0x14, 0x7e, 0x46, 0xc8, 0xa1, 0x61, 0x5a, 0x2e, 0x03, 0xe5, 0x85, 0xdb, 0x07, 0xe5, 0x5b, 0xe4, 0x78, 0x39, 0x99, 0xeb, 0xae, 0x7a, 0x14, 0xe0, 0x02, 0x32, 0x42, 0x98, 0x8f, 0x93, 0x8d, 0x44, 0x71, 0x9b, 0x3a, 0x52, 0xae, 0x63, 0xed, 0x0b, 0x6d, 0x5a, 0x61, 0xbc, 0x3f, 0x93, 0x88, 0x46, 0xad, 0x6e, 0x75, 0x60, 0x32, 0xaf, 0x07, 0x13, 0x50, 0xa5, 0x7f, 0x4d, 0xe5, 0xcc, 0x19, 0x2c, 0xb8, 0x94, 0xc9, 0x05, 0x7e, 0xd1, 0x98, 0x92, 0x80, 0xf4, 0xba, 0x10, 0x30, 0xe5, 0x6a, 0x11, 0xe9, 0xfa, 0xf6, 0x6c, 0xe9, 0x15, 0xcc, 0x29, 0x19, 0xb6, 0x5c, 0x91, 0x3c, 0xbf, 0xcf, 0xf1, 0x92, 0x88, 0xf6, 0xd5, 0x6f, 0x0a, 0x19, 0xb9, 0x06, 0xc5, 0xe6, 0x8a, 0xcd, 0xb0, 0xaf, 0x07, 0x62, 0xb1, 0x3f, 0x24, 0xeb, 0x34, 0xd0, 0x39, 0x72, 0xd5, 0x34, 0xcc, 0x72, 0x02, 0x0c, 0x10, 0x19, 0x44, 0x00, 0xd0, 0x21, 0x3f, 0x0d, 0x7f, 0x1e, 0x0d, 0x08, 0xaa, 0xd3, 0xec, 0x21, 0xff, 0x9b, 0xc7, 0xcb, 0x04, 0x97, 0x79, 0x27, 0xd7, 0xc6, 0xe6, 0xbb, 0x4f, 0x0d, 0x88, 0x7a, 0x70, 0x4a, 0x7d, 0xbd, 0x65, 0x8f, 0xa3, 0xc3, 0xc9, 0x2d, 0x7b, 0x09, 0xdd, 0x3d, 0x86, 0x90, 0xba, 0x4c, 0x1d, 0x65, 0x33, 0x07, 0x50, 0x7a, 0x2c, 0xb3, 0x06, 0x9e, 0xab, 0xbd, 0xe2, 0xb6, 0xe2, 0x4f, 0x0d, 0x79, 0xb4, 0x0a, 0xb4, 0x90, 0xae, 0x89, 0x48, 0xcc, 0x90, 0x5a, 0x4d, 0xc5, 0xc2, 0xe0, 0x59, 0xda, 0x08, 0x33, 0x1b, 0x82, 0x40, 0x51, 0xfa, 0x0b, 0x07, 0x93, 0xe3, 0x6d, 0x96, 0xaf, 0xeb, 0xf6, 0xfc, 0xef, 0x85, 0x1b, 0x21, 0x94, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x05, 0xe8, 0x4d, 0x9d, 0xad, 0x38, 0xf9, 0x66, 0xa0, 0x9c, 0x66, 0x4e, 0x97, 0xdd, 0xf3, 0xbb, 0xfa, 0xf3, 0x23, 0xfb, 0xea, 0x68, 0xe0, 0xc0, 0x93, 0x79, 0x4a, 0x3c, 0x00, 0x65, 0x13, 0x8c, 0xac, 0x0e, 0x94, 0x6b, 0x36, 0xb7, 0xe5, 0xc6, 0x69, 0x9f, 0x2e, 0x49, 0xec, 0x9e, 0x7b, 0x5a, 0xb4, 0x19, 0xc1, 0xec, 0xdd, 0x8f, 0xc3, 0x2e, 0x68, 0xfe, 0x27, 0x6d, 0x28, 0x8d, 0x09, 0x47, 0x93, 0x0e, 0x48, 0x01, 0x77, 0x08, 0x46, 0x5d, 0x55, 0x46, 0x46, 0xc9, 0x07, 0x48, 0x4e, 0x87, 0xa3, 0xdc, 0x42, 0x53, 0xe6, 0xdb, 0x4f, 0x7c, 0xeb, 0x5d, 0x3e, 0xf5, 0xa4, 0x49, 0xd5, 0xf2 };
|
||||||
|
static const unsigned char vec3_pmsgs2[3][64] = {
|
||||||
|
{ 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5 },
|
||||||
|
{ 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed },
|
||||||
|
{ 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_cmsg2[192] = { 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5, 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed, 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef };
|
||||||
|
static const unsigned char vec3_secshares[3][32] = {
|
||||||
|
{ 0x38, 0xf8, 0x44, 0xd4, 0x6d, 0xf1, 0xf9, 0x51, 0x56, 0x40, 0x60, 0x09, 0xb7, 0x04, 0x11, 0xcf, 0x88, 0x02, 0x4c, 0xa6, 0xd6, 0x4a, 0x37, 0x06, 0x9f, 0x44, 0x97, 0x10, 0x7d, 0x3d, 0x47, 0x33 },
|
||||||
|
{ 0x01, 0x1d, 0x1f, 0x86, 0x77, 0xaf, 0x70, 0x71, 0xcf, 0x89, 0xf6, 0x3f, 0x94, 0xad, 0xf7, 0x7c, 0xfa, 0xe7, 0xca, 0xb3, 0x28, 0xd4, 0x4d, 0x5e, 0x24, 0x29, 0x5e, 0x06, 0x77, 0xda, 0x3b, 0xfe },
|
||||||
|
{ 0xc9, 0x41, 0xfa, 0x38, 0x81, 0x6c, 0xe7, 0x92, 0x48, 0xd3, 0x8c, 0x75, 0x72, 0x57, 0xdd, 0x29, 0x28, 0x7c, 0x25, 0xa6, 0x2a, 0xa7, 0x03, 0xf1, 0x68, 0xe0, 0x83, 0x89, 0x42, 0xad, 0x72, 0x0a },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_thresh_pk[33] = { 0x03, 0x07, 0xf3, 0xc6, 0x29, 0x69, 0xf9, 0xee, 0xaf, 0xb9, 0xf3, 0xd6, 0x25, 0xcb, 0xa6, 0xe8, 0x09, 0x00, 0x17, 0x04, 0xc0, 0x92, 0xd7, 0xca, 0xac, 0x49, 0x6f, 0xd3, 0xed, 0x07, 0x35, 0x23, 0x2c };
|
||||||
|
static const unsigned char vec3_pubshares[3][33] = {
|
||||||
|
{ 0x02, 0x2a, 0x8d, 0x1c, 0x2a, 0x1c, 0x95, 0x97, 0x89, 0xdf, 0xa2, 0xb5, 0xc4, 0xc2, 0x97, 0xdb, 0xc9, 0x09, 0x6b, 0xb7, 0xd7, 0x20, 0x1f, 0xe6, 0x67, 0x38, 0x13, 0xae, 0xff, 0x9f, 0xbc, 0x58, 0xba },
|
||||||
|
{ 0x03, 0x1a, 0x40, 0x20, 0x79, 0x6b, 0x0c, 0x5f, 0x0e, 0x4a, 0x67, 0xd2, 0x74, 0x8f, 0xd2, 0xea, 0x93, 0x65, 0x2c, 0xae, 0x41, 0x0f, 0xf0, 0x2d, 0x45, 0x79, 0x8a, 0x44, 0xb4, 0x50, 0x8f, 0xd5, 0x4d },
|
||||||
|
{ 0x02, 0xea, 0xad, 0x03, 0x65, 0xfe, 0x7e, 0xa9, 0xea, 0xd9, 0x30, 0x44, 0xb9, 0x68, 0xf6, 0xe7, 0x18, 0x51, 0xe5, 0xac, 0xd3, 0x80, 0x92, 0x11, 0xd8, 0x4d, 0xe2, 0xd7, 0x3a, 0xf6, 0xf9, 0x4a, 0xee },
|
||||||
|
};
|
||||||
|
static const unsigned char vec3_recovery[556] = { 0x00, 0x00, 0x00, 0x02, 0x03, 0xdd, 0xe3, 0x46, 0x0b, 0x06, 0x56, 0x58, 0xf6, 0x85, 0x78, 0x85, 0xee, 0x42, 0xa8, 0xfa, 0x9c, 0x53, 0xd6, 0x3d, 0x75, 0x02, 0x16, 0x65, 0x03, 0xf1, 0xb6, 0x6a, 0x56, 0xb9, 0x76, 0xa2, 0x70, 0x03, 0xe5, 0x85, 0xdb, 0x07, 0xe5, 0x5b, 0xe4, 0x78, 0x39, 0x99, 0xeb, 0xae, 0x7a, 0x14, 0xe0, 0x02, 0x32, 0x42, 0x98, 0x8f, 0x93, 0x8d, 0x44, 0x71, 0x9b, 0x3a, 0x52, 0xae, 0x63, 0xed, 0x0b, 0x6d, 0x02, 0x2d, 0x9b, 0xc8, 0xa8, 0x44, 0x57, 0xc7, 0x51, 0x00, 0x1f, 0x71, 0x4a, 0xd9, 0xac, 0x72, 0x82, 0x8a, 0x01, 0xe5, 0x31, 0xbe, 0x63, 0xe7, 0xfc, 0x3c, 0x4d, 0x37, 0x0c, 0x2f, 0xec, 0xd8, 0x43, 0x03, 0x34, 0xbe, 0xe4, 0x54, 0x9f, 0x86, 0x95, 0xd8, 0x96, 0xa3, 0xf0, 0x60, 0x40, 0xe0, 0x26, 0x3c, 0x41, 0x90, 0x54, 0xf3, 0xb8, 0xc7, 0x83, 0xa7, 0x7a, 0x77, 0x02, 0x82, 0x86, 0x14, 0x97, 0x3a, 0x02, 0x85, 0xe6, 0xb7, 0xa7, 0xfb, 0x26, 0x5f, 0x38, 0xb9, 0xad, 0xc3, 0x9e, 0x51, 0xd4, 0xac, 0x2d, 0xfb, 0x0f, 0x31, 0xa6, 0xf1, 0x8e, 0x7f, 0xf8, 0xae, 0x2f, 0x3c, 0xa7, 0xbc, 0xaa, 0x7d, 0xcf, 0x03, 0x14, 0x18, 0x10, 0xaf, 0x9a, 0x1b, 0x7c, 0x34, 0x27, 0x0a, 0x83, 0xaa, 0x52, 0x62, 0xc2, 0xbe, 0x22, 0x4a, 0x4c, 0x6b, 0xde, 0x0d, 0xc4, 0xdf, 0xda, 0xd1, 0xc2, 0x7f, 0x09, 0x3b, 0x9b, 0x38, 0x03, 0x77, 0xb8, 0xeb, 0x7f, 0x3c, 0xf3, 0x08, 0x9a, 0xeb, 0x55, 0x77, 0xeb, 0xb3, 0x7a, 0xf4, 0x84, 0x25, 0x91, 0xcf, 0x6c, 0x97, 0x42, 0xa4, 0x8e, 0xc6, 0x56, 0xdb, 0xb8, 0xf2, 0x50, 0xf7, 0x09, 0x03, 0xfc, 0x22, 0xdc, 0xf0, 0xed, 0xd5, 0x9e, 0xdf, 0x52, 0xab, 0x06, 0xeb, 0xce, 0xba, 0x18, 0x33, 0x7d, 0x00, 0xec, 0x2e, 0xf5, 0x57, 0xcd, 0x23, 0x70, 0xe4, 0x82, 0x07, 0x2b, 0x51, 0x6d, 0x37, 0x05, 0xe8, 0x4d, 0x9d, 0xad, 0x38, 0xf9, 0x66, 0xa0, 0x9c, 0x66, 0x4e, 0x97, 0xdd, 0xf3, 0xbb, 0xfa, 0xf3, 0x23, 0xfb, 0xea, 0x68, 0xe0, 0xc0, 0x93, 0x79, 0x4a, 0x3c, 0x00, 0x65, 0x13, 0x8c, 0xac, 0x0e, 0x94, 0x6b, 0x36, 0xb7, 0xe5, 0xc6, 0x69, 0x9f, 0x2e, 0x49, 0xec, 0x9e, 0x7b, 0x5a, 0xb4, 0x19, 0xc1, 0xec, 0xdd, 0x8f, 0xc3, 0x2e, 0x68, 0xfe, 0x27, 0x6d, 0x28, 0x8d, 0x09, 0x47, 0x93, 0x0e, 0x48, 0x01, 0x77, 0x08, 0x46, 0x5d, 0x55, 0x46, 0x46, 0xc9, 0x07, 0x48, 0x4e, 0x87, 0xa3, 0xdc, 0x42, 0x53, 0xe6, 0xdb, 0x4f, 0x7c, 0xeb, 0x5d, 0x3e, 0xf5, 0xa4, 0x49, 0xd5, 0xf2, 0x09, 0x1e, 0xab, 0x60, 0x71, 0x94, 0x54, 0x81, 0xfb, 0x97, 0xd0, 0x1c, 0x93, 0xdc, 0x2d, 0xd2, 0xcb, 0xea, 0xbc, 0xa1, 0xb0, 0x9a, 0xd6, 0x65, 0x85, 0xa4, 0x25, 0x84, 0xf2, 0x8d, 0xeb, 0xb3, 0x2c, 0x20, 0x4e, 0xc5, 0xe0, 0x5d, 0xaf, 0xd5, 0xc9, 0xf2, 0x65, 0xce, 0x1a, 0x2b, 0xa4, 0x50, 0x1b, 0x4a, 0x1b, 0x9a, 0x0e, 0x97, 0xc7, 0xf4, 0xb3, 0x4f, 0x86, 0x23, 0x31, 0x85, 0x54, 0xe5, 0x4f, 0x38, 0xc9, 0x07, 0xc0, 0x20, 0x29, 0xb9, 0x8d, 0x8b, 0x65, 0xa1, 0xc1, 0xbb, 0x24, 0x89, 0x64, 0x38, 0xc0, 0x71, 0xef, 0xd6, 0xa4, 0x90, 0x96, 0x4e, 0x9d, 0x83, 0x23, 0x8a, 0x98, 0xf0, 0xd3, 0x06, 0xf3, 0xc9, 0x4c, 0xa1, 0x50, 0x07, 0x57, 0x89, 0xc6, 0xfc, 0xe8, 0xb8, 0x02, 0xf2, 0x36, 0xfd, 0xcd, 0xf5, 0x8e, 0x5a, 0x1c, 0x65, 0x21, 0x4d, 0xa2, 0x7f, 0xed, 0x3e, 0xa6, 0xed, 0x8b, 0x92, 0x3f, 0xae, 0x45, 0x7c, 0xb0, 0x5c, 0x36, 0x9f, 0x7d, 0x9d, 0x84, 0x28, 0xa2, 0x2c, 0x63, 0x0a, 0x62, 0xeb, 0x6b, 0x51, 0x89, 0x11, 0x54, 0x6a, 0x96, 0xf7, 0x45, 0x88, 0xc1, 0x4a, 0xbd, 0x63, 0xa7, 0xfa, 0x16, 0x9e, 0x17, 0xd9, 0xc5, 0x97, 0x4b, 0x0b, 0xe6, 0xc5, 0x92, 0xfe, 0x48, 0x6b, 0xec, 0xfc, 0xfd, 0xea, 0x76, 0xa3, 0xfa, 0x92, 0xa7, 0x2f, 0xba, 0x1e, 0x7b, 0xef };
|
||||||
|
/* chilldkg session n = 3, t = 2 */
|
||||||
|
/* all python-side sanity checks passed */
|
||||||
|
|
||||||
/* The group order n and (2^256 - 1) mod n, for scalar parsing edge cases. */
|
/* The group order n and (2^256 - 1) mod n, for scalar parsing edge cases. */
|
||||||
static const unsigned char vec_scalar_order_n[32] = {
|
static const unsigned char vec_scalar_order_n[32] = {
|
||||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
@@ -265,11 +313,11 @@ static void chilldkg_params_hash_test(void) {
|
|||||||
unsigned char out[32];
|
unsigned char out[32];
|
||||||
|
|
||||||
/* TH("BIP DKG/params_hash", u32be(2) || hostpubkeys) */
|
/* TH("BIP DKG/params_hash", u32be(2) || hostpubkeys) */
|
||||||
secp256k1_chilldkg_params_hash(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 2);
|
secp256k1_chilldkg_params_hash_internal(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 2);
|
||||||
CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) == 0);
|
CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) == 0);
|
||||||
|
|
||||||
/* t is part of the hash input. */
|
/* t is part of the hash input. */
|
||||||
secp256k1_chilldkg_params_hash(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 3);
|
secp256k1_chilldkg_params_hash_internal(hash_ctx, out, &vec_params_hash_hostpubkeys[0][0], 3, 3);
|
||||||
CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) != 0);
|
CHECK(secp256k1_memcmp_var(out, vec_params_hash, 32) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +686,7 @@ static void chilldkg_simplpedpop_test(void) {
|
|||||||
|
|
||||||
/* coordinator_step: cmsg, eq_input and the DKG output are byte-exact. */
|
/* coordinator_step: cmsg, eq_input and the DKG output are byte-exact. */
|
||||||
fault = secp256k1_chilldkg_simplpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, &fault_index, pmsg_ptrs, t, n);
|
fault = secp256k1_chilldkg_simplpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, &fault_index, pmsg_ptrs, t, n);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
CHECK(secp256k1_memcmp_var(cmsg, vec_simpl_cmsg, cmsg_len) == 0);
|
CHECK(secp256k1_memcmp_var(cmsg, vec_simpl_cmsg, cmsg_len) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(eq_input, vec_simpl_eq_input, eq_len) == 0);
|
CHECK(secp256k1_memcmp_var(eq_input, vec_simpl_eq_input, eq_len) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(coord_dkg.thresh_pk33, vec_simpl_thresh_pk, 33) == 0);
|
CHECK(secp256k1_memcmp_var(coord_dkg.thresh_pk33, vec_simpl_thresh_pk, 33) == 0);
|
||||||
@@ -659,7 +707,7 @@ static void chilldkg_simplpedpop_test(void) {
|
|||||||
secp256k1_scalar_get_b32(buf32, &secshare);
|
secp256k1_scalar_get_b32(buf32, &secshare);
|
||||||
CHECK(secp256k1_memcmp_var(buf32, vec_simpl_untweaked_secshares[i], 32) == 0);
|
CHECK(secp256k1_memcmp_var(buf32, vec_simpl_untweaked_secshares[i], 32) == 0);
|
||||||
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[i], eq_input_p, &fault_index, &states[i], cmsg, cmsg_len, &secshare);
|
fault = secp256k1_chilldkg_simplpedpop_participant_step2(CTX, &dkg_outputs[i], eq_input_p, &fault_index, &states[i], cmsg, cmsg_len, &secshare);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
CHECK(secp256k1_memcmp_var(eq_input_p, vec_simpl_eq_input, eq_len) == 0);
|
CHECK(secp256k1_memcmp_var(eq_input_p, vec_simpl_eq_input, eq_len) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(dkg_outputs[i].secshare32, vec_simpl_secshares[i], 32) == 0);
|
CHECK(secp256k1_memcmp_var(dkg_outputs[i].secshare32, vec_simpl_secshares[i], 32) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(dkg_outputs[i].thresh_pk33, vec_simpl_thresh_pk, 33) == 0);
|
CHECK(secp256k1_memcmp_var(dkg_outputs[i].thresh_pk33, vec_simpl_thresh_pk, 33) == 0);
|
||||||
@@ -819,7 +867,7 @@ static void chilldkg_encpedpop_test(void) {
|
|||||||
CHECK(secp256k1_chilldkg_encpedpop_encaps_multi(CTX, pads_send, &scalar_tmp, vec_enc_pubnonces[0], vec_enc_hostseckeys[0], &vec_enc_hostpubkeys[0][0], enc_context, sizeof(enc_context), 0, n) == 1);
|
CHECK(secp256k1_chilldkg_encpedpop_encaps_multi(CTX, pads_send, &scalar_tmp, vec_enc_pubnonces[0], vec_enc_hostseckeys[0], &vec_enc_hostpubkeys[0][0], enc_context, sizeof(enc_context), 0, n) == 1);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
fault = secp256k1_chilldkg_encpedpop_decaps_multi(CTX, pads_recv, &fault_index, vec_enc_hostseckeys[i], vec_enc_hostpubkeys[i], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), i, n);
|
fault = secp256k1_chilldkg_encpedpop_decaps_multi(CTX, pads_recv, &fault_index, vec_enc_hostseckeys[i], vec_enc_hostpubkeys[i], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), i, n);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
CHECK(secp256k1_scalar_eq(&pads_send[i], &pads_recv[0]));
|
CHECK(secp256k1_scalar_eq(&pads_send[i], &pads_recv[0]));
|
||||||
}
|
}
|
||||||
/* decaps_multi rejects an invalid own host secret key. */
|
/* decaps_multi rejects an invalid own host secret key. */
|
||||||
@@ -849,7 +897,7 @@ static void chilldkg_encpedpop_test(void) {
|
|||||||
}
|
}
|
||||||
for (j = 0; j < n; j++) {
|
for (j = 0; j < n; j++) {
|
||||||
fault = secp256k1_chilldkg_encpedpop_decrypt_sum(CTX, &scalar_tmp, &fault_index, vec_enc_hostseckeys[j], vec_enc_hostpubkeys[j], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), j, &enc_secshares[j], n);
|
fault = secp256k1_chilldkg_encpedpop_decrypt_sum(CTX, &scalar_tmp, &fault_index, vec_enc_hostseckeys[j], vec_enc_hostpubkeys[j], &vec_enc_pubnonces[0][0], enc_context, sizeof(enc_context), j, &enc_secshares[j], n);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
secp256k1_scalar_set_int(&scalar_tmp2, 0);
|
secp256k1_scalar_set_int(&scalar_tmp2, 0);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
secp256k1_scalar p;
|
secp256k1_scalar p;
|
||||||
@@ -862,7 +910,7 @@ static void chilldkg_encpedpop_test(void) {
|
|||||||
/* coordinator_step: cmsg, eq_input, summed encrypted shares and the DKG
|
/* coordinator_step: cmsg, eq_input, summed encrypted shares and the DKG
|
||||||
* output are byte-exact. */
|
* output are byte-exact. */
|
||||||
fault = secp256k1_chilldkg_encpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, enc_secshares, &fault_index, pmsg_ptrs, t, &vec_enc_hostpubkeys[0][0], n);
|
fault = secp256k1_chilldkg_encpedpop_coordinator_step(CTX, cmsg, &coord_dkg, eq_input, enc_secshares, &fault_index, pmsg_ptrs, t, &vec_enc_hostpubkeys[0][0], n);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
CHECK(secp256k1_memcmp_var(cmsg, vec_enc_cmsg, cmsg_len) == 0);
|
CHECK(secp256k1_memcmp_var(cmsg, vec_enc_cmsg, cmsg_len) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(eq_input, vec_enc_eq_input, eq_len) == 0);
|
CHECK(secp256k1_memcmp_var(eq_input, vec_enc_eq_input, eq_len) == 0);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
@@ -878,7 +926,7 @@ static void chilldkg_encpedpop_test(void) {
|
|||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
unsigned char eq_input_p[268];
|
unsigned char eq_input_p[268];
|
||||||
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input_p, &fault_index, &states[i], vec_enc_hostseckeys[i], cmsg, cmsg_len, &enc_secshares[i]);
|
fault = secp256k1_chilldkg_encpedpop_participant_step2(CTX, &dkg_output, eq_input_p, &fault_index, &states[i], vec_enc_hostseckeys[i], cmsg, cmsg_len, &enc_secshares[i]);
|
||||||
CHECK(fault == SECP256K1_CHILLDKG_SUCCESS);
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
CHECK(secp256k1_memcmp_var(eq_input_p, vec_enc_eq_input, eq_len) == 0);
|
CHECK(secp256k1_memcmp_var(eq_input_p, vec_enc_eq_input, eq_len) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(dkg_output.secshare32, vec_enc_out_secshares[i], 32) == 0);
|
CHECK(secp256k1_memcmp_var(dkg_output.secshare32, vec_enc_out_secshares[i], 32) == 0);
|
||||||
CHECK(secp256k1_memcmp_var(dkg_output.thresh_pk33, vec_enc_thresh_pk, 33) == 0);
|
CHECK(secp256k1_memcmp_var(dkg_output.thresh_pk33, vec_enc_thresh_pk, 33) == 0);
|
||||||
@@ -958,6 +1006,262 @@ static void chilldkg_encpedpop_test(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chilldkg_participant_api_test(void) {
|
||||||
|
const size_t n = 3;
|
||||||
|
const uint32_t t = 2;
|
||||||
|
const size_t pmsg1_len = 33 * 2 + 32 * 3 + 97; /* 259 */
|
||||||
|
const size_t cmsg1_len = 162 * 3 + 33 * 1; /* 519 */
|
||||||
|
const size_t enc_cmsg_len = 97 * 3 + 33 * 1 + 33 * 3; /* 423 */
|
||||||
|
const size_t recovery_len = 4 + 33 * 2 + 162 * 3; /* 556 */
|
||||||
|
secp256k1_chilldkg_participant_state1 state1[3];
|
||||||
|
secp256k1_chilldkg_participant_state2 state2[3];
|
||||||
|
secp256k1_chilldkg_simplpedpop_dkg_output coord_dkg;
|
||||||
|
secp256k1_scalar enc_secshares[3];
|
||||||
|
unsigned char pmsg1[3][259];
|
||||||
|
unsigned char sig64[3][64];
|
||||||
|
unsigned char cmsg1[519];
|
||||||
|
unsigned char cmsg1_bad[519];
|
||||||
|
unsigned char cmsg2[192];
|
||||||
|
unsigned char cmsg2_bad[192];
|
||||||
|
unsigned char hostpubkeys33[3 * 33];
|
||||||
|
unsigned char pubshares33[3 * 33];
|
||||||
|
unsigned char recovery[556];
|
||||||
|
unsigned char eq_input[268];
|
||||||
|
unsigned char buf33[33];
|
||||||
|
unsigned char buf32[32];
|
||||||
|
unsigned char secshare32[32];
|
||||||
|
unsigned char zero32[32] = { 0 };
|
||||||
|
const unsigned char *pmsg1_ptrs[3];
|
||||||
|
secp256k1_chilldkg_fault fault;
|
||||||
|
uint32_t fault_index = 0;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
pmsg1_ptrs[i] = pmsg1[i];
|
||||||
|
memcpy(hostpubkeys33 + 33 * i, vec3_hostpubkeys[i], 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Message length helpers. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg1_len(n, t) == pmsg1_len);
|
||||||
|
CHECK(secp256k1_chilldkg_coordinator_msg1_len(n, t) == cmsg1_len);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg2_len() == 64);
|
||||||
|
CHECK(secp256k1_chilldkg_coordinator_msg2_len(n) == sizeof(cmsg2));
|
||||||
|
CHECK(secp256k1_chilldkg_recovery_data_len(n, t) == recovery_len);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg1_len(0, 1) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg1_len(n, 0) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg1_len(n, (uint32_t)(n + 1)) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_msg1_len(SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 1, 1) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_coordinator_msg1_len(n, 0) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_coordinator_msg2_len(0) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_recovery_data_len(n, (uint32_t)(n + 1)) == 0);
|
||||||
|
|
||||||
|
/* hostpubkey_gen: byte-exact against the reference; invalid host secret
|
||||||
|
* keys are rejected and zero the output. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, vec3_hostseckeys[i]) == 1);
|
||||||
|
CHECK(secp256k1_memcmp_var(buf33, vec3_hostpubkeys[i], 33) == 0);
|
||||||
|
}
|
||||||
|
CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, zero32) == 0);
|
||||||
|
CHECK(secp256k1_is_zero_array(buf33, 33));
|
||||||
|
CHECK(secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, vec_scalar_order_n) == 0);
|
||||||
|
CHECK(secp256k1_is_zero_array(buf33, 33));
|
||||||
|
|
||||||
|
/* params_hash: byte-exact against the reference; invalid parameters
|
||||||
|
* (duplicate or invalid host public keys, t or n out of range) are
|
||||||
|
* rejected and zero the output. */
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, t) == 1);
|
||||||
|
CHECK(secp256k1_memcmp_var(buf32, vec3_params_hash, 32) == 0);
|
||||||
|
{
|
||||||
|
unsigned char bad_hostpubkeys[3 * 33];
|
||||||
|
memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys));
|
||||||
|
memcpy(bad_hostpubkeys + 33, hostpubkeys33, 33); /* duplicate */
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0);
|
||||||
|
CHECK(secp256k1_is_zero_array(buf32, 32));
|
||||||
|
memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys));
|
||||||
|
memset(bad_hostpubkeys + 33, 0xff, 33); /* invalid public key */
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0);
|
||||||
|
memcpy(bad_hostpubkeys, hostpubkeys33, sizeof(bad_hostpubkeys));
|
||||||
|
memset(bad_hostpubkeys + 33, 0, 33); /* infinity is not a valid public key */
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, bad_hostpubkeys, n, t) == 0);
|
||||||
|
}
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, 0) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, n, (uint32_t)(n + 1)) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_params_hash(CTX, buf32, hostpubkeys33, SECP256K1_CHILLDKG_MAX_PARTICIPANTS + 1, t) == 0);
|
||||||
|
|
||||||
|
/* participant_step1: byte-exact messages against the reference. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &state1[i], pmsg1[i], vec3_hostseckeys[i], hostpubkeys33, n, t, vec3_randoms[i]) == 1);
|
||||||
|
CHECK(secp256k1_memcmp_var(pmsg1[i], vec3_pmsgs1[i], pmsg1_len) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* participant_step1 rejects invalid input and zeroes its outputs. */
|
||||||
|
{
|
||||||
|
secp256k1_chilldkg_participant_state1 tmp_state1;
|
||||||
|
unsigned char tmp_pmsg1[259];
|
||||||
|
unsigned char other_seckey[32];
|
||||||
|
memset(other_seckey, 0, 32);
|
||||||
|
other_seckey[31] = 1; /* valid key, but not in hostpubkeys33 */
|
||||||
|
|
||||||
|
/* All-zero randomness (RandomnessError in the reference). */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, t, zero32) == 0);
|
||||||
|
CHECK(secp256k1_is_zero_array(tmp_state1.data, sizeof(tmp_state1.data)));
|
||||||
|
CHECK(secp256k1_is_zero_array(tmp_pmsg1, sizeof(tmp_pmsg1)));
|
||||||
|
/* Host secret key not in the session (HostSeckeyError). */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, other_seckey, hostpubkeys33, n, t, vec3_randoms[0]) == 0);
|
||||||
|
/* Invalid host secret key. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, zero32, hostpubkeys33, n, t, vec3_randoms[0]) == 0);
|
||||||
|
/* Invalid session parameters. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, 0, vec3_randoms[0]) == 0);
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &tmp_state1, tmp_pmsg1, vec3_hostseckeys[0], hostpubkeys33, n, (uint32_t)(n + 1), vec3_randoms[0]) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simulate the coordinator with the internal EncPedPop coordinator step:
|
||||||
|
* cmsg1 = enc_cmsg || enc_secshares. The result is byte-exact against the
|
||||||
|
* reference coordinator_step1. */
|
||||||
|
fault = secp256k1_chilldkg_encpedpop_coordinator_step(CTX, cmsg1, &coord_dkg, eq_input, enc_secshares, &fault_index, pmsg1_ptrs, t, hostpubkeys33, n);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_scalar_get_b32(cmsg1 + enc_cmsg_len + 32 * i, &enc_secshares[i]);
|
||||||
|
}
|
||||||
|
CHECK(secp256k1_memcmp_var(cmsg1, vec3_cmsg1, cmsg1_len) == 0);
|
||||||
|
|
||||||
|
/* participant_step2: byte-exact CertEq signatures against the reference. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[i], sig64[i], &fault_index, &state1[i], vec3_hostseckeys[i], cmsg1, vec3_aux_rands[i]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
|
CHECK(secp256k1_memcmp_var(sig64[i], vec3_pmsgs2[i], 64) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The certificate is the concatenation of the pmsg2 signatures. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
memcpy(cmsg2 + 64 * i, sig64[i], 64);
|
||||||
|
}
|
||||||
|
CHECK(secp256k1_memcmp_var(cmsg2, vec3_cmsg2, sizeof(cmsg2)) == 0);
|
||||||
|
|
||||||
|
/* participant_finalize: byte-exact outputs against the reference. */
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
fault = secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &state2[i], cmsg2);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
|
CHECK(secp256k1_memcmp_var(secshare32, vec3_secshares[i], 32) == 0);
|
||||||
|
CHECK(secp256k1_memcmp_var(buf33, vec3_thresh_pk, 33) == 0);
|
||||||
|
for (j = 0; j < n; j++) {
|
||||||
|
CHECK(secp256k1_memcmp_var(pubshares33 + 33 * j, vec3_pubshares[j], 33) == 0);
|
||||||
|
}
|
||||||
|
CHECK(secp256k1_memcmp_var(recovery, vec3_recovery, recovery_len) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* participant_step2 with a host secret key that does not match the one
|
||||||
|
* used in step 1 is an input error (HostSeckeyError in the reference). */
|
||||||
|
{
|
||||||
|
unsigned char tmp_sig64[64];
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &state1[0], vec3_hostseckeys[1], cmsg1, vec3_aux_rands[0]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_INVALID_INPUT);
|
||||||
|
CHECK(secp256k1_is_zero_array(tmp_sig64, 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* participant_step2 blames faults correctly. */
|
||||||
|
{
|
||||||
|
secp256k1_chilldkg_participant_state1 fresh_state1;
|
||||||
|
unsigned char tmp_sig64[64];
|
||||||
|
|
||||||
|
/* A tampered encrypted secshare: the decrypted share does not match
|
||||||
|
* the pubshare; the fault cannot be attributed without the
|
||||||
|
* investigation procedure. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1);
|
||||||
|
memcpy(cmsg1_bad, cmsg1, cmsg1_len);
|
||||||
|
cmsg1_bad[enc_cmsg_len + 31] ^= 1;
|
||||||
|
fault_index = 0;
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||||
|
CHECK(fault_index == UINT32_MAX);
|
||||||
|
|
||||||
|
/* An invalid pubnonce of participant 1 blames that participant or the
|
||||||
|
* coordinator. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1);
|
||||||
|
memcpy(cmsg1_bad, cmsg1, cmsg1_len);
|
||||||
|
memset(cmsg1_bad + 324 + 33, 0xff, 33);
|
||||||
|
fault_index = 0;
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR);
|
||||||
|
CHECK(fault_index == 1);
|
||||||
|
|
||||||
|
/* An encrypted secshare that overflows the group order blames the
|
||||||
|
* coordinator. */
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1);
|
||||||
|
memcpy(cmsg1_bad, cmsg1, cmsg1_len);
|
||||||
|
memset(cmsg1_bad + enc_cmsg_len, 0xff, 32);
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1_bad, vec3_aux_rands[0]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* participant_finalize: an invalid signature in the certificate blames
|
||||||
|
* the coordinator and zeroes the outputs. */
|
||||||
|
{
|
||||||
|
secp256k1_chilldkg_participant_state1 fresh_state1;
|
||||||
|
secp256k1_chilldkg_participant_state2 fresh_state2;
|
||||||
|
unsigned char tmp_sig64[64];
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &fresh_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1);
|
||||||
|
fault = secp256k1_chilldkg_participant_step2(CTX, &fresh_state2, tmp_sig64, &fault_index, &fresh_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_OK);
|
||||||
|
|
||||||
|
memcpy(cmsg2_bad, cmsg2, sizeof(cmsg2));
|
||||||
|
cmsg2_bad[64 + 10] ^= 1; /* corrupt the signature of participant 1 */
|
||||||
|
fault_index = 0;
|
||||||
|
fault = secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &fresh_state2, cmsg2_bad);
|
||||||
|
CHECK(fault == SECP256K1_CHILLDKG_FAULTY_COORDINATOR);
|
||||||
|
CHECK(fault_index == 1);
|
||||||
|
CHECK(secp256k1_is_zero_array(secshare32, 32));
|
||||||
|
CHECK(secp256k1_is_zero_array(buf33, 33));
|
||||||
|
CHECK(secp256k1_is_zero_array(pubshares33, 33 * n));
|
||||||
|
CHECK(secp256k1_is_zero_array(recovery, recovery_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* API misuse. */
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_hostpubkey_gen(CTX, NULL, vec3_hostseckeys[0]));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_hostpubkey_gen(CTX, buf33, NULL));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_params_hash(CTX, NULL, hostpubkeys33, n, t));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_params_hash(CTX, buf32, NULL, n, t));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, NULL, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], NULL, vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], NULL, hostpubkeys33, n, t, vec3_randoms[0]));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], vec3_hostseckeys[0], NULL, n, t, vec3_randoms[0]));
|
||||||
|
CHECK_ILLEGAL(CTX, secp256k1_chilldkg_participant_step1(CTX, &state1[0], pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, NULL));
|
||||||
|
/* API misuse of the enum-returning functions: the illegal-argument
|
||||||
|
* callback fires exactly once and the function returns INVALID_INPUT. */
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, NULL, sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], NULL, &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], NULL, &state1[0], vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, NULL, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], NULL, cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], NULL, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], sig64[0], &fault_index, &state1[0], vec3_hostseckeys[0], cmsg1, NULL) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, NULL, buf33, pubshares33, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, NULL, pubshares33, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, NULL, recovery, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, NULL, &fault_index, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, NULL, &state2[0], cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, NULL, cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &state2[0], NULL) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
|
||||||
|
/* States with a bad magic (uninitialized or corrupted) are rejected. */
|
||||||
|
{
|
||||||
|
secp256k1_chilldkg_participant_state1 bad_state1;
|
||||||
|
secp256k1_chilldkg_participant_state2 bad_state2;
|
||||||
|
unsigned char tmp_sig64[64];
|
||||||
|
memset(&bad_state1, 0, sizeof(bad_state1));
|
||||||
|
memset(&bad_state2, 0, sizeof(bad_state2));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &bad_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_finalize(CTX, secshare32, buf33, pubshares33, recovery, &fault_index, &bad_state2, cmsg2) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
CHECK(secp256k1_chilldkg_participant_step1(CTX, &bad_state1, pmsg1[0], vec3_hostseckeys[0], hostpubkeys33, n, t, vec3_randoms[0]) == 1);
|
||||||
|
bad_state1.data[0] ^= 1;
|
||||||
|
CHECK_ILLEGAL_VOID(CTX, CHECK(secp256k1_chilldkg_participant_step2(CTX, &state2[0], tmp_sig64, &fault_index, &bad_state1, vec3_hostseckeys[0], cmsg1, vec3_aux_rands[0]) == SECP256K1_CHILLDKG_INVALID_INPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
secp256k1_scalar_clear(&enc_secshares[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct tf_test_entry tests_chilldkg[] = {
|
static const struct tf_test_entry tests_chilldkg[] = {
|
||||||
CASE1(chilldkg_tagged_hashes_test),
|
CASE1(chilldkg_tagged_hashes_test),
|
||||||
CASE1(chilldkg_params_hash_test),
|
CASE1(chilldkg_params_hash_test),
|
||||||
@@ -968,6 +1272,7 @@ static const struct tf_test_entry tests_chilldkg[] = {
|
|||||||
CASE1(chilldkg_vss_test),
|
CASE1(chilldkg_vss_test),
|
||||||
CASE1(chilldkg_simplpedpop_test),
|
CASE1(chilldkg_simplpedpop_test),
|
||||||
CASE1(chilldkg_encpedpop_test),
|
CASE1(chilldkg_encpedpop_test),
|
||||||
|
CASE1(chilldkg_participant_api_test),
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,36 +7,16 @@
|
|||||||
#define SECP256K1_MODULE_CHILLDKG_UTIL_H
|
#define SECP256K1_MODULE_CHILLDKG_UTIL_H
|
||||||
|
|
||||||
#include "../../../include/secp256k1.h"
|
#include "../../../include/secp256k1.h"
|
||||||
|
#include "../../../include/secp256k1_chilldkg.h"
|
||||||
|
|
||||||
#include "../../group.h"
|
#include "../../group.h"
|
||||||
#include "../../hash.h"
|
#include "../../hash.h"
|
||||||
#include "../../scalar.h"
|
#include "../../scalar.h"
|
||||||
|
|
||||||
/* Maximum number of participants (and thus the maximum threshold) supported by
|
/* The public header defines SECP256K1_CHILLDKG_MAX_PARTICIPANTS and the fault
|
||||||
* this module. The state objects of the module are fixed-size and do not use
|
* enum secp256k1_chilldkg_fault (SECP256K1_CHILLDKG_OK, ...), which the
|
||||||
* dynamic allocation, so a compile-time cap is required. This matches the
|
* internal SimplPedPop/EncPedPop functions use directly as their return
|
||||||
* frost module's convention; the public header will expose the same constant
|
* codes. */
|
||||||
* in a later phase. */
|
|
||||||
#define SECP256K1_CHILLDKG_MAX_PARTICIPANTS 128
|
|
||||||
|
|
||||||
/* Return codes of the internal SimplPedPop/EncPedPop functions, mirroring the
|
|
||||||
* exception taxonomy of chilldkg_ref/util.py. The public API will expose its
|
|
||||||
* own enum in a later phase.
|
|
||||||
*
|
|
||||||
* For SECP256K1_CHILLDKG_FAULTY_PARTICIPANT and
|
|
||||||
* SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR, the fault_index output
|
|
||||||
* of the failing function receives the index of the (suspected) faulty
|
|
||||||
* participant. For SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR
|
|
||||||
* the faulty party cannot be identified without the investigation procedure
|
|
||||||
* (a later phase); fault_index is set to UINT32_MAX. */
|
|
||||||
typedef enum {
|
|
||||||
SECP256K1_CHILLDKG_SUCCESS = 0,
|
|
||||||
SECP256K1_CHILLDKG_FAULTY_COORDINATOR,
|
|
||||||
SECP256K1_CHILLDKG_FAULTY_PARTICIPANT,
|
|
||||||
SECP256K1_CHILLDKG_FAULTY_PARTICIPANT_OR_COORDINATOR,
|
|
||||||
SECP256K1_CHILLDKG_UNKNOWN_FAULTY_PARTICIPANT_OR_COORDINATOR,
|
|
||||||
SECP256K1_CHILLDKG_INVALID_INPUT
|
|
||||||
} secp256k1_chilldkg_fault;
|
|
||||||
|
|
||||||
/* This file contains the internal primitives of the ChillDKG module that
|
/* This file contains the internal primitives of the ChillDKG module that
|
||||||
* mirror chilldkg_ref/util.py, secp256k1lab/bip340.py and secp256k1lab/ecdh.py
|
* mirror chilldkg_ref/util.py, secp256k1lab/bip340.py and secp256k1lab/ecdh.py
|
||||||
@@ -120,6 +100,6 @@ static void secp256k1_chilldkg_encpedpop_self_pad(const secp256k1_hash_ctx *hash
|
|||||||
/* Compute the session parameters hash (chilldkg.py `params_hash`):
|
/* Compute the session parameters hash (chilldkg.py `params_hash`):
|
||||||
* out32 = TH("BIP DKG/params_hash", u32be(t) || hostpubkeys[0] || ... || hostpubkeys[n-1])
|
* out32 = TH("BIP DKG/params_hash", u32be(t) || hostpubkeys[0] || ... || hostpubkeys[n-1])
|
||||||
* where hostpubkeys33 is an array of n 33-byte compressed host public keys. */
|
* where hostpubkeys33 is an array of n 33-byte compressed host public keys. */
|
||||||
static void secp256k1_chilldkg_params_hash(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t);
|
static void secp256k1_chilldkg_params_hash_internal(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ static void secp256k1_chilldkg_encpedpop_self_pad(const secp256k1_hash_ctx *hash
|
|||||||
secp256k1_memclear_explicit(hash32, sizeof(hash32));
|
secp256k1_memclear_explicit(hash32, sizeof(hash32));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void secp256k1_chilldkg_params_hash(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t) {
|
static void secp256k1_chilldkg_params_hash_internal(const secp256k1_hash_ctx *hash_ctx, unsigned char *out32, const unsigned char *hostpubkeys33, size_t n, uint32_t t) {
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
secp256k1_sha256 sha;
|
secp256k1_sha256 sha;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user