In our recent blog, Threshold Cryptography II, we explored the FROST protocol for threshold EdDSA. Compared to EdDSA, threshold ECDSA is significantly more complex due to the difficulty of securely distributing the signature’s non-linear terms. This issue was addressed in GG18 [3] using the Multiplicative-to-Additive (MtA) secret share conversion protocol and Paillier additively homomorphic encryption scheme, enabling a secure and efficient threshold signature scheme.
This protocol enhances fault tolerance and security guarantees, making it suitable for decentralized use cases such as cross-chain bridges, multiparty computation (MPC) wallets, and other blockchain applications that require resilience against single points of failure when nodes (parties) are performing cryptographic signing operations.
Binance tss-lib [1] is a Go implementation of threshold ECDSA protocol based on GG18 [3]. It performs distributed key generation and a 9-round signing protocol, allowing any subset of out of participants to jointly produce a valid ECDSA signature without reconstructing the secret key.
This third post in the Threshold Cryptography series provides a bird’s-eye view of the 9-round threshold ECDSA protocol implemented in tss-lib [1]. Detailed exposition of the underlying MtA secret share conversion protocol and zero-knowledge proofs will follow in the next two posts.
ECDSA
Elliptic Curve Digital Signature Algorithm (ECDSA) is an elliptic curve variant of the Digital Signature Algorithm (DSA). It operates over a cyclic group of large prime order , generated by a curve base point on the elliptic curve. Additionally, a cryptographic hash function maps arbitrary strings to elements in the prime field . The notation stands for curve point addition and stands for scalar multiplication with a curve point. The secret key is a nonzero scalar (i.e., nonzero elements in \mathbb{Z}_q$), and its public key is the curve point $y = x \bullet g \in G.
Signature Generation
- Given a message , compute the hash .
- Select a random nonce .
- Compute point and let be its $x$-coordinate.
- Then compute mod .
- The ECDSA signature is where both and are scalars in .
Signature Verification
- Given a signature , verify .
- Compute , where and is the public key.
- The signature is valid if the x$-coordinate of $R' equals to .
Challenge in ECDSA Threshold Signing
Unlike EdDSA, the challenge to create threshold ECDSA lies in the nonlinear terms and during the signature generation. Simply distributing the nonce and private key among parties do not directly yield signature shares.
To get around with it, the Bar-Ilan and Beaver inversion trick was utilized in the MtA protocol of GG18 [3] by introducing a random value , then computing , and rewriting .
If is additively shared among the parties, then is publicly revealed, while remains secretly shared.
Defining intermediate values and , then and , so each party holds one share and .
As long as the multiplicative shares (i.e., each term in and in k_i \cdot \sum_{i \ne j} \omega_j$) can be converted to additive share $\alpha and such that , then each party will hold the additive shares and of the product and .
9-Round Threshold ECDSA
Binance tss-lib [1] assumes two types of communication channels: a broadcast channel for disseminating messages to all parties except for itself, and a peer-to-peer (p2p) channel for secure, private communication between two individual parties.
The implementation of the threshold ECDSA over the Secp256k1 curve operates in 9 rounds with two additional offline stages, prepare and finalize. In each round, parties validate and process messages received from peers via broadcast or p2p channels, then generate and transmit new messages accordingly.
It assumes that a secret key is distributed to parties (for example, with methods on secret sharing schemes in the first post) so that each holds a secret share and any parties or more could reconstruct the private key. At the beginning of the protocol, the parties in the group prepared to participate in the signing are predetermined and the group size is . For simplicity, we assume that only parties in the group participate in the ECDSA threshold signing.
Prepare
Given the parties, each party converts its Shamir secret share to additive secret share by multiplying the i$-th Lagrange coefficient $\lambda_i = \sum_{j=1,i\ne j}^{t+1} \frac{p_j}{p_j - p_i}, where is the participant identifier associated to used in the key sharing (Note that the first post on distributed key generation assumes for simplicity). Additionally, computes all the public key shares of the parties by taking scalar multiplication with the Lagrange coefficients.
Refer to GG18 [3], Page 11:

Round 1
Each party checks that the hash of message is within the range of the scalar field of the Secp256k1 curve, then every starts to run the MtA protocol with every other peer to convert the multiplicative shares to additive shares.
- selects nonce share and auxiliary random value .
- Computes point and creates its commitment (i.e., hash of the point and a random value .).
- With every other P_j$’s Paillier public key, $P_i invokes AliceInit() to encrypt the nonce share (Alice’s share a$) and create range proof of $k_i for each .
- sends the encrypted value (ciphertext) of and its range proof to every corresponding via the p2p channel.
- broadcasts the commitment to .

Refer to GG18 [3], Page 11:

Refer to GG18 [3], Page 9:

Round 2
Each party invokes BobMid() to
- verify the range proof from round 1.
- report the party with invalid range proof.
- call ProveBob() to create its share and encrypt the share with (Bob’s share $b$) and $P_i$’s Paillier public key, then generate the Bob proof.
- Aborts if an error occurs.
invokes BobMidWC() (i.e., MtA with check) to
- verify the range proof from round 1.
- report the party with invalid range proof.
- call ProveBob() to create its share and encrypt the share with its private key share (Bob’s share b$) and $P_i$’s Paillier public key, then generate the Bob proof with check with an extra [Schnorr proof](https://datatracker.ietf.org/doc/rfc8235/) to the $\omega_j.
- Aborts if an error occurs.
sends encrypted shares and Bob proofs to the corresponding peer .

Refer to GG18 [3], Page 9:

Round 3
Each party invokes AliceEnd() to
- verify the Bob proof.
- report the party with invalid Bob proof.
- decrypt the encrypted share and compute its share .
- Aborts if an error occurs.
Each party invokes AliceEndWC() to
- verify the Bob proof with check.
- report the party with invalid Bob proof with check.
- decrypt the encrypted share and compute its share .
- Aborts if an error occurs.
Each party computes the and , where and .
broadcasts to other participants.

Refer to GG18 [3], Page 9:

Refer to GG18 [3], Page 11:

Round 4
- Each party sums over all the mod and computes its inverse mod .
- creates a Schnorr proof to .
- broadcasts the Schnorr proof with the decommitment in round 1.

Refer to GG18 [3], Page 11:

Round 5
- Each party verifies P_j$'s commitment and extracts $\Gamma_j from it, then verifies its Schnorr proof.
- computes the curve point (equal to k^{-1} \bullet g$) and gets its $x$-coordinate, $r.
- computes its signature share with the hash of the signing message and the share .
- selects random values , , then computes , and creates hash commitment to , .
- broadcasts the hash commitment.

Refer to GG18 [3], Page 11:

Round 6
- Each party creates Schnorr proof to with and Schnorr proof to with .
- broadcasts the decommitment in round 5 and Schnorr proofs.

Refer to GG18 [3], Page 11 and 12:

Round 7
- Each party verifies the hash commitment to and .
- verifies the Schnorr proofs.
- Reports the party with invalid Bob proof with check. Aborts if it fails.
- computes and .
- continues to compute and .
- creates the hash commitment to and .
- broadcasts the hash commitment.

Refer to GG18 [3], Page 12:

Round 8
- Each party broadcasts the decommitment to and from round 7.

Refer to GG18 [3], Page 12:

Round 9
- Each party computes and .
- verifies if . Aborts if it is not.
- Until this point, it is safe for to broadcast its signature share .

Refer to GG18 [3], Page 12:

Finalize
- Each party computes .
- creates the signature and converts it to a standard format with recovery ID to prevent signature malleability.
- verifies the newly created signature to ensure it is valid.
Conclusion
This post provides a high-level overview of the 9-round threshold ECDSA scheme implemented in Binance tss-lib [1]. The technical details on the MtA secret share conversion protocol and zero-knowledge proofs utilized in the protocol will be covered in the following two posts.
References
- Binance: https://github.com/bnb-chain/tss-lib
- Binance: Binance Open-Sources Threshold Signature Scheme Library
- Rosario Gennaro, Steven Goldfeder, 2018: Fast Multiparty Threshold ECDSA with Fast Trustless Setup (GG18)
- Ran Canetti, Rosario Gennaro, Steven Goldfeder, Nikolaos Makriyannis, Udi Peled, 2021: UC Non-Interactive, Proactive, Threshold ECDSA with Identifiable Aborts (CGGMP21)



