Pitfall Category
Insecure Subprotocols
Subprotocols assumed by the protocol design, such as broadcast channels and authenticated or confidential peer-to-peer transport, must be realized by the deployment.
Pitfall Category
Subprotocols assumed by the protocol design, such as broadcast channels and authenticated or confidential peer-to-peer transport, must be realized by the deployment.
Pitfall
What Can Go Wrong. MPC protocols such as GG18, GG20, and FROST may rely on a reliable broadcast channel for some rounds, and are often implemented by instantiating the broadcast with multicast: simply having each party send the same message to all others over P2P links. Per Goldwasser and Lindell, 2002, privacy and correctness can be achieved without full broadcast by using echo-broadcast (receivers re-send what they got and abort on mismatch), at the cost of non-unanimous abort. But echo-broadcast only achieves “broadcast with abort”: same value or $\bot$, never two different non-abort values, still strictly weaker than what these protocols assume in their published proofs. A library that cannot tell whether a given round was supposed to be broadcast or point-to-point cannot enforce reliable broadcast, and therefore cannot ensure privacy and correctness.
Security implication. Honest parties end up with different views of the same round, which can cause them to compute incompatible outputs and break correctness. In threshold signing, equivocation in a DKG commitment round leaves honest parties disagreeing on the public key; in a zero-knowledge proof round, it can let an invalid proof pass for one verifier and fail for another.
How to avoid. Implement a reliable broadcast protocol (not just echo-broadcast) for any round whose security proof requires Byzantine agreement. In settings with fewer than $n/3$ corruptions, Bracha broadcast provides the required guarantees. Enforce the per-round broadcast-vs-P2P classification at the library boundary using the protocol specification as reference, rather than delegating the decision to the caller.
Kudelski’s audit of ING’s threshold-ECDSA library identified a communication-layer failure in the GG18 resharing protocol. The issue was a design-level mismatch: the resharing mitigation relies on all honest parties seeing the same final confirmation, but that assumption is not realized by sending separate point-to-point messages. ING implemented the standard “forget-and-forgive” mitigation, a final ACK confirmation round before parties delete their old shares; Kudelski noted that this mitigation “might actually make things worse” if a robust broadcast channel is not available, because the final ACK can itself be equivocated. If an application realizes broadcast as $N$ separate point-to-point sends, a malicious sender can equivocate.
Kudelski’s example starts with four peers $(A, B, C, D)$ using a threshold of 3, and a resharing ceremony that adds a fifth peer $E$ while keeping the threshold at 3. At the end of the resharing protocol, malicious $E$ sends different final-round messages to different honest parties:
ACK to $A$ and $B$.not ACK to $C$ and $D$.$A$ and $B$ believe resharing succeeded, discard their old shares, and migrate to the new committee. $C$ and $D$ believe resharing failed, keep the old shares, and do not save the new shares. The honest parties are now split between incompatible old and new committee states. Neither honest subset has enough compatible shares to sign without $E$, so the single malicious participant can lock the wallet.
What can go wrong. Many MPC protocols such as GG18 and GG20 assume the presence of confidential and authenticated P2P channels. The deployment must realize that assumption, typically through mutual TLS, signed/encrypted application-level messages, or a noise-protocol handshake. Implementations that hand-roll channel security (raw TCP, ad-hoc JSON over HTTP, or implicit trust in a central coordinator that re-signs messages) routinely fail to provide these guarantees.
Security implication. Without per-message authentication, a network attacker can impersonate parties and inject messages honest parties attribute to the wrong source; the victim of the attribution is then blamed for protocol violations it did not commit. Without confidentiality, intermediate values that the ideal functionality hides leak to the network, and downstream secret-dependent computations become vulnerable to offline analysis. In threshold signing this translates to rogue messages causing spurious aborts, silent share exposure, and key-extraction attacks that exploit observed intermediate values.
How to avoid. Instantiate the point-to-point channels with “standard secure channel implementations”, such as mutual TLS or QUIC between each pair of parties. Ensure that the certificates of each party is pinned or issued by a trusted authority.
axelarnetwork/tofnd accepts spoofed from field on the wire
(Issue #60)Axelar’s
tofnd is a Rust daemon implementing GG20
(Gennaro–Goldfeder, 2020), a threshold-ECDSA protocol widely deployed in MPC wallet
implementations. Each message is wrapped in a TrafficIn envelope that carries both a
transport-level sender identity (from_party_uid) and an inner MsgMeta with a
protocol-level sender index (from: usize). As reported in Issue #60,
the inner from field is unauthenticated: a malicious party can edit it in the
binary payload and send messages on behalf of any other party.
The vulnerable handler discarded the transport identity and passed the raw payload straight to the cryptographic core (source):
1// FILE: src/gg20/protocol.rs — axelarnetwork/tofnd (pre-fix, lines 106–117)
2while protocol.expecting_more_msgs_this_round() {
3 let traffic = chan.receiver.next().await.ok_or(...)?;
4 let traffic = traffic.unwrap();
5 // Only `traffic.payload` is forwarded to tofn; the transport-level
6 // `traffic.from_party_uid` is discarded. tofn then trusts the inner
7 // `MsgMeta { from: usize, ... }` self-attribution.
8 protocol.set_msg_in(&traffic.payload)?;
9}
A malicious party Alice with subshares {0, 1} could craft a message with
MsgMeta::from = 2 (Bob’s subshare index), and no consistency check linked that index
back to the transport-authenticated from_party_uid. The fix is split across two
repos: tofn (the cryptographic library tofnd wraps) had to first expose the from
field in its public API (Issue #42)
so tofnd could then enforce from_party_uid == MsgMeta::from before dispatch.
coinbase/kryptology GG20 DKG ships secret shares unencrypted
(Issue #29)GG20’s joint key-generation procedure (inherited from GG18) assumes the Round 2 P2P delivery of each Shamir share $x_{ij}$ runs over a confidential point-to-point channel. The GG18/GG20 papers assume this private channel abstractly and leave its instantiation to the deployment; Paillier encryption enters only in the signing-phase MtA, never for the keygen shares. The Coinbase library’s GG20 implementation provides no confidentiality of its own and returns the share as a bare struct field (source):
1// FILE: pkg/tecdsa/gg20/participant/dkg_round2.go — coinbase/kryptology
2
3type DkgRound2P2PSend struct {
4 xij *v1.ShamirShare // raw share — no encryption applied
5}
6// ...
7p2PSend[id] = &DkgRound2P2PSend{ xij: dp.state.X[id-1] }