立刻保护您的项目
借助最大的web3安全提供商来增强您的项目。
CertiK 安全专家将审核您的请求,并尽快与您联系。

Threshold Cryptography III: Binance tss-lib’s 9-Round Threshold ECDSA

技术博客 ·技术洞察 ·
Threshold Cryptography III: Binance tss-lib’s 9-Round Threshold ECDSA

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 t+1t+1 out of nn 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 GG of large prime order qq, generated by a curve base point gg on the elliptic curve. Additionally, a cryptographic hash function HH maps arbitrary strings to elements in the prime field Zq\mathbb{Z}_q. The notation ++ stands for curve point addition and \bullet stands for scalar multiplication with a curve point. The secret key is a nonzero scalar xZqx \in \mathbb{Z}_q^* (i.e., nonzero elements in \mathbb{Z}_q$), and its public key is the curve point $y = x \bullet g \in G.

Signature Generation

  1. Given a message MM, compute the hash m=H(M)Zqm = H(M) \in \mathbb{Z}_q.
  2. Select a random nonce kZqk \in \mathbb{Z}_q^*.
  3. Compute point R=k1gGR = k^{-1} \bullet g \in G and let rZqr \in \mathbb{Z}_q be its $x$-coordinate.
  4. Then compute s=k(m+xr)s = k \cdot (m+ x \cdot r) mod qq.
  5. The ECDSA signature is σ=(r,s)\sigma = (r, s) where both rr and ss are scalars in Zq\mathbb{Z}_q.

Signature Verification

  1. Given a signature σ=(r,s)\sigma = (r, s), verify r,sZqr, s \in \mathbb{Z}_q.
  2. Compute R=(ms1)g+(rs1)yR' = (m \cdot s^{-1}) \bullet g + (r \cdot s^{-1}) \bullet y, where m=H(M)Zqm = H(M) \in \mathbb{Z}_q and yy is the public key.
  3. The signature σ\sigma is valid if the x$-coordinate of $R' equals to rr.

Challenge in ECDSA Threshold Signing

Unlike EdDSA, the challenge to create threshold ECDSA lies in the nonlinear terms k1k^{-1} and kxk \cdot x during the signature generation. Simply distributing the nonce k=ikik = \sum_i k_i and private key x=iωix = \sum_i \omega_i among t+1t+1 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 γ\gamma, then computing δ=kγ\delta = k \cdot \gamma, and rewriting k1=δ1γk^{-1} = \delta^{-1} \cdot \gamma.

If γ=iγi\gamma =\sum_i \gamma_i is additively shared among the t+1t+1 parties, then δ=kγ=ikiiγi=i,jkiγj\delta = k \cdot \gamma = \sum_i k_i \cdot \sum_i \gamma_i = \sum_{i,j} k_i \cdot \gamma_j is publicly revealed, while σσ=kx=ikiiωi=i,jkiωjσ\sigma =k \cdot x = \sum_i k_i \cdot \sum_i \omega_i = \sum_{i,j} k_i \cdot \omega_j remains secretly shared.

Defining intermediate values δi=kijγj=kiγi+kiijγj\delta_i = k_i \sum_j \gamma_j = k_i \cdot \gamma_i + k_i \cdot \sum_{i \ne j}\gamma_j and σi=kiωi+kiijωj\sigma_i = k_i \cdot \omega_i + k_i \cdot \sum_{i \ne j} \omega_j, then δ=iδi\delta = \sum_i \delta_i and σ=iσi\sigma = \sum_i \sigma_i, so each party holds one share δi\delta_i and σi\sigma_i.

As long as the multiplicative shares aba \cdot b (i.e., each term kiγjk_i \cdot \gamma_j in kiijγjk_i \cdot \sum_{i \ne j} \gamma_j and kiωjk_i \cdot \omega_j in k_i \cdot \sum_{i \ne j} \omega_j$) can be converted to additive share $\alpha and β\beta such that ab=α+βa \cdot b = \alpha + \beta, then each party will hold the additive shares δi\delta_i and σi\sigma_i of the product δ=kγ\delta = k \cdot \gamma and σ=kx\sigma = k \cdot x.

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 nn parties (for example, with methods on secret sharing schemes in the first post) so that each holds a secret share and any t+1t+1 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 t+1\geq t+1. For simplicity, we assume that only t+1t+1 parties P1,,Pt+1P_1, \cdots,P_{t+1} in the group participate in the ECDSA threshold signing.

Prepare

Given the t+1t+1 parties, each party PiP_i 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 pjp_j is the participant identifier associated to PjP_j used in the key sharing (Note that the first post on distributed key generation assumes pj=jp_j = j for simplicity). Additionally, PiP_i computes all the public key shares of the t+1t+1 parties by taking scalar multiplication with the Lagrange coefficients.

Refer to GG18 [3], Page 11:

Code 1

Round 1

Each party PiP_i checks that the hash of message mm is within the range of the scalar field of the Secp256k1 curve, then every PiP_i starts to run the MtA protocol with every other peer to convert the multiplicative shares to additive shares.

  1. PiP_i selects nonce share kiZqk_i \in \mathbb{Z}_q^* and auxiliary random value γiZq\gamma_i \in \mathbb{Z}_q^*.
  2. Computes point Γi=γig\Gamma_i = \gamma_i \bullet g and creates its commitment (i.e., hash of the point Γi\Gamma_i and a random value rr.).
  3. With every other P_j$’s Paillier public key, $P_i invokes AliceInit() to encrypt the nonce share kik_i (Alice’s share a$) and create range proof of $k_i for each PjP_j.
  4. PiP_i sends the encrypted value (ciphertext) of kik_i and its range proof to every corresponding PjP_j via the p2p channel.
  5. PiP_i broadcasts the commitment to γig\gamma_i \bullet g.

Round 1

Refer to GG18 [3], Page 11:

Code 2

Refer to GG18 [3], Page 9:

Code 3

Round 2

  1. Each party PjP_j invokes BobMid() to

    • verify the range proof from round 1.
    • report the party with invalid range proof.
    • call ProveBob() to create its share βi,j\beta_{i,j} and encrypt the share with γj\gamma_j (Bob’s share $b$) and $P_i$’s Paillier public key, then generate the Bob proof.
    • Aborts if an error occurs.
  2. PjP_j 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 νi,j\nu_{i,j} and encrypt the share with its private key share ωj\omega_j (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.
  3. PjP_j sends encrypted shares and Bob proofs to the corresponding peer PiP_i.

Round 2

Refer to GG18 [3], Page 9:

Code 4

Round 3

  1. Each party PiP_i invokes AliceEnd() to

    • verify the Bob proof.
    • report the party with invalid Bob proof.
    • decrypt the encrypted share and compute its share αi,j\alpha_{i,j}.
    • Aborts if an error occurs.
  2. Each party PiP_i 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 μi,j\mu_{i,j}.
    • Aborts if an error occurs.
  3. Each party PiP_i computes the δi=kiγi+ijαi,j+ijβj,i\delta_i = k_i \cdot \gamma_i + \sum_{i \ne j} \alpha_{i,j} + \sum_{i \ne j} \beta_{j,i} and σi=kiωi+ijμi,j+ijνj,i\sigma_i = k_i \cdot \omega_i + \sum_{i \ne j} \mu_{i,j} + \sum_{i \ne j} \nu_{j,i}, where kiγj=αi,j+βi,jk_i \cdot \gamma_j = \alpha_{i,j} + \beta_{i,j} and kiωj=μi,j+νi,jk_i \cdot \omega_j = \mu_{i,j} + \nu_{i,j}.

  4. PiP_i broadcasts δi\delta_i to other participants.

Round 3

Refer to GG18 [3], Page 9:

Code 5

Refer to GG18 [3], Page 11:

Page 11

Round 4

  1. Each party PiP_i sums over all the δi\delta_i mod qq and computes its inverse mod qq.
  2. PiP_i creates a Schnorr proof to γi\gamma_i.
  3. PiP_i broadcasts the Schnorr proof with the decommitment in round 1.

Round 4

Refer to GG18 [3], Page 11:

Page 11.2

Round 5

  1. Each party PiP_i verifies P_j$'s commitment and extracts $\Gamma_j from it, then verifies its Schnorr proof.
  2. PiP_i computes the curve point R=δ1(jΓj)R = \delta^{-1} \bullet (\sum_j \Gamma_j) (equal to k^{-1} \bullet g$) and gets its $x$-coordinate, $r.
  3. PiP_i computes its signature share si=mki+rσis_i = m \cdot k_i + r \cdot \sigma_i with the hash of the signing message mm and the share σi\sigma_i.
  4. PiP_i selects random values lil_i, ρi\rho_i, then computes Vi=siR+ligV_i = s_i \bullet R + l_i \bullet g, Ai=ρigA_i = \rho_i \bullet g and creates hash commitment to ViV_i, AiA_i.
  5. PiP_i broadcasts the hash commitment.

Round 5

Refer to GG18 [3], Page 11:

Code 8

Round 6

  1. Each party PiP_i creates Schnorr proof to si,lis_i, l_i with Vi=siR+ligV_i = s_i \bullet R + l_i \bullet g and Schnorr proof to ρi\rho_i with Ai=ρigA_i = \rho_i \bullet g.
  2. PiP_i broadcasts the decommitment in round 5 and Schnorr proofs.

Round 6

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

2 Codes

Round 7

  1. Each party PiP_i verifies the hash commitment to ViV_i and AiA_i.
  2. PiP_i verifies the Schnorr proofs.
  3. Reports the party with invalid Bob proof with check. Aborts if it fails.
  4. PiP_i computes V=(m)g+(r)y+jVjV = (-m) \bullet g + (-r) \bullet y + \sum_j V_j and A=jAjA = \sum_j A_j.
  5. PiP_i continues to compute Ui=ρiVU_i = \rho_i \bullet V and Ti=liAT_i = l_i \bullet A.
  6. PiP_i creates the hash commitment to UiU_i and TiT_i.
  7. PiP_i broadcasts the hash commitment.

Round 7

Refer to GG18 [3], Page 12:

Player

Round 8

  1. Each party PiP_i broadcasts the decommitment to ViV_i and AiA_i from round 7.

Round 8

Refer to GG18 [3], Page 12:

5D

Round 9

  1. Each party PiP_i computes U=jUjU = \sum_j U_j and T=jTjT = \sum_j T_j.
  2. PiP_i verifies if U==TU == T. Aborts if it is not.
  3. Until this point, it is safe for PiP_i to broadcast its signature share sis_i.

Round 9

Refer to GG18 [3], Page 12:

Player P1

Finalize

  1. Each party PiP_i computes s=jsjs = \sum_j s_j.
  2. PiP_i creates the signature (r,s)(r, s) and converts it to a standard format with recovery ID to prevent signature malleability.
  3. PiP_i 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

  1. Binance: https://github.com/bnb-chain/tss-lib
  2. Binance: Binance Open-Sources Threshold Signature Scheme Library
  3. Rosario Gennaro, Steven Goldfeder, 2018: Fast Multiparty Threshold ECDSA with Fast Trustless Setup (GG18)
  4. Ran Canetti, Rosario Gennaro, Steven Goldfeder, Nikolaos Makriyannis, Udi Peled, 2021: UC Non-Interactive, Proactive, Threshold ECDSA with Identifiable Aborts (CGGMP21)

相关博客

Skynet Wrench Attacks Report

Skynet Wrench Attacks Report

In 2025, wrench attacks unfortunately crossed a critical threshold. What was once treated as an edge-case risk has become a structural threat to digital asset ownership. Attackers are no longer acting opportunistically; they are operating as organized, transnational groups that combine OSINT-driven targeting, social engineering, and extreme physical violence to extract private keys.

SoftBank Expands Web3 Push with PayPay–Binance Japan Deal

SoftBank Expands Web3 Push with PayPay–Binance Japan Deal

SoftBank expands in Japan’s crypto market via PayPay, which will acquire 40% of Binance Japan to let users buy crypto directly from PayPay accounts. This aligns with Japan’s booming digital asset market and builds on SoftBank’s Web3 investments—including $60M in CertiK for security, plus Cipher Mining, The Sandbox and Aleo—targeting compliant, accessible Web3 services.

Threshold Cryptography V: Auxiliary Zero-knowledge Proofs

Threshold Cryptography V: Auxiliary Zero-knowledge Proofs

In this post, we analyze the specific ZKP constructions implemented in Binance’s tss-lib [1]. These proofs address previously identified weaknesses in the Multiplicative-to-Additive (MtA) protocol, Paillier encryption parameters, and auxiliary RSA modulus generation. Our discussion is grounded in the improvements formalized by the specifications in CGGMP21 [4], which strengthen the robustness of threshold ECDSA against known attacks.