Attacks on Threshold Schemes: Part 2

Security

Dec 16, 2025

mpc-attacks-p2-image

In Part 1, we covered implementation bugs - the missing checks, skipped validations, and encoding ambiguities that turn provably secure protocols into exploitable systems. Those were failures at the code level: developers trusting inputs they should validate, using insufficient security parameters, or misunderstanding the cryptographic requirements. This part goes deeper. Here we examine attacks that stem from the protocols themselves, design decisions that look sound in the paper but break under adversarial conditions the original authors didn't fully consider. We'll also look at a recent theoretical result that challenges the adaptive security of widely-deployed threshold Schnorr schemes. These aren't bugs you can fix with a parameter check or an extra validation. They're fundamental issues that require protocol redesign or careful understanding of when a protocol's security guarantees actually hold.

The MtA Oracle Attack

The Multiplicative-to-Additive (MtA) share conversion is everywhere in threshold ECDSA. This protocol uses Paillier encryption. Party Alice holds secret aa and a Paillier keypair (EA,DA)(E_A, D_A) with modulus NN. Party Bob holds secret bb. They proceed:

  1. Alice encrypts: Computes cA=EA(a)c_A = E_A(a) along with a zero-knowledge range proof that aa is in the correct range and sends (cA,πA)(c_A, \pi_A) to Bob.

  2. Bob responds:

    • Verifies Alice's proof πA\pi_A
    • Picks random βZN\beta' \in \mathbb{Z}_N
    • Sets β=βmodq\beta = -\beta' \bmod q (his output share)
    • Computes cB=b×EcA+EEA(β)c_B = b \times_E c_A +_E E_A(\beta') using Paillier homomorphism (where ×E\times_E and +E+_E are scalar multiplication and addition in the ciphertext space)
    • Sends (cB,πB)(c_B, \pi_B) where πB\pi_B is a range proof
  3. Alice decrypts: Verifies Bob's proof πB\pi_B then computes α=DA(cB)modq\alpha = D_A(c_B) \bmod q (her output share)

The range proofs ensure that aa and bb are small enough that the decryption doesn't overflow. Specifically, α=DA(cB)=ab+β\alpha' = D_A(c_B) = ab + \beta' (computed over the integers), and then α=αmodq\alpha = \alpha' \bmod q. If aa and bb are in range, α\alpha' doesn't wrap around modulo qq, and we get α+β=abmodq\alpha + \beta = ab \bmod q as desired.

The "Fast" Version

The GG18 paper proposed a variant (MtAwc) that omits the range proofs. Instead (B,B)(B, B') are published and the authors conjectured that the public values B=gbB = g^b and B=gβB' = g^{\beta'} "do not leak any additional data and compensate for the missing range proof." They were wrong.

The Attack

The attacker (say, Alice/Party 1) chooses a=2Nqa = \lfloor \frac{2N}{q} \rfloor. This is much larger than the protocol expects, aa should be roughly qq-sized, but this aa is about 2N2N.

Bob proceeds honestly: computes cB=bcA+EEA(β)c_B = b \cdot c_A +_E E_A(\beta') and sends (cB,B=gb,B=gβ)(c_B, B = g^b, B' = g^{\beta'}).

Alice decrypts: α=DA(cB)=ab+β\alpha = D_A(c_B) = ab + \beta'. Let's denote α\alpha' the original value over the integers (without modular reduction)

Now, βZN\beta' \in \mathbb{Z}_N, so β[0,N)\beta' \in [0, N). The key observation: depending on the size of α\alpha', it will fall into one of three disjoint ranges:

  1. If α[0,N)\alpha' \in [0, N): Then αmodq=α\alpha' \mod q = \alpha, so:
gabgβ=gα=gαg^{ab} \cdot g^{\beta'} = g^{\alpha'} = g^\alpha
  1. If α[N,2N)\alpha' \in [N, 2N): Then αmodq=α+N\alpha' \mod q = \alpha + N, so:
gabgβ=gα=gαgNg^{ab} \cdot g^{\beta'} = g^{\alpha'} = g^{\alpha} \cdot g^N
  1. If α[2N,3N)\alpha' \in [2N, 3N): Then αmodq=α+2N\alpha' \mod q = \alpha + 2N, and:
gabgβ=gα=gαg2Ng^{ab} \cdot g^{\beta'} = g^{\alpha'} = g^{\alpha} \cdot g^{2N}

Alice computes gabgβ=gaBBg^{ab} \cdot g^{\beta'} = g^a \cdot B \cdot B' (using the public values BB and BB') and checks which case holds. This reveals which interval α\alpha' belongs to, which in turn reveals information about bb:

  • Since α=ab+β\alpha' = ab + \beta' and β[0,N)\beta' \in [0, N), if α[sN,(s+1)N)\alpha' \in [sN, (s+1)N), then ab[(s1)N,(s+1)N)ab \in [(s-1)N, (s+1)N).
  • With a=2Nqa = \lfloor \frac{2N}{q} \rfloor, we get b[(s1)q2,(s+1)q2]b \in \left[\frac{(s-1)q}{2}, \frac{(s+1)q}{2}\right].

Alice just learned a constraint on Bob's secret bb from a single MtA execution.

Generalizing the Attack

Alice can choose a=MNqa = \lfloor \frac{MN}{q} \rfloor for some integer MM. Now α\alpha' will fall into one of M+1M+1 intervals [sN,(s+1)N)[sN, (s+1)N) for s0,1,,Ms \in {0, 1, \ldots, M}. Each signature reveals which interval, giving Alice a constraint:

b[(s1)qM,(s+1)qM]b \in \left[\frac{(s-1)q}{M}, \frac{(s+1)q}{M}\right]

After just a few signatures (each with a different malicious aa value), Alice reconstructs Bob's entire secret key.

Why It Happens

The "additional data" B=gbB = g^b and B=gβB' = g^{\beta'} was supposed to prevent leakage. But when Alice chooses out-of-range aa, the decryption creates a side channel: the relationship between gabgβg^{ab} \cdot g^{\beta'} and gαg^\alpha reveals how much modular reduction occurred, which leaks information about bb.

This is the Attack on absent range proofs from "Alpha-Rays: Key Extraction Attacks on Threshold ECDSA Implementations". The paper reports impact on ZenGo and ING libraries.

The Fix: Use the "slow" version with range proofs. Modern protocols like CGGMP20 include proper range proofs for all MtA inputs. Don't skip them.

Oops, We Deleted Too Early

Key resharing protocols are supposed to refresh shares without changing the underlying secret. This maintains continuous access to funds while limiting the damage from gradual key compromise. But if the protocol lacks proper coordination around when to delete old shares, an attacker can weaponize it into a permanent wallet lockout.

The Reshare Protocol

The vulnerable implementation uses VSS-based resharing in a (t,n)(t, n) threshold setting. The high-level flow:

  1. Convert to additive shares: The t+1t+1 old parties convert their Shamir shares into additive shares: sk=w1++wt+1sk = w_1 + \cdots + w_{t+1}, where each old party Pi0P_i^0 knows wiw_i.
  2. Distribute via VSS: Each old party Pi0P_i^0 samples a random degree-tt polynomial with constant term wiw_i (their additive share becomes the secret).
  3. Broadcast commitments: Each Pi0P_i^0 broadcasts commitments to their polynomial coefficients (as in Feldman VSS).
  4. Send new shares: Each old party Pi0P_i^0 sends evaluations of their polynomial to each of the nn' new parties.
  5. Verify and sum: Each new party PjP_j verifies the shares they received using the VSS commitments, then sums them to get their new share wjw_j'.
  6. Check public key: New parties verify that the public key reconstructed from new shares matches the old public key.
  7. Delete old shares: If all checks pass, parties delete their old shares wiw_i and keep only the new shares wiw_i'.

The Attack

The adversary (one of the old parties) exploits step 4 by sending selectively malformed shares:

  • Send valid shares to some new parties (say, parties P1,,PkP_1, \ldots, P_k)
  • Send invalid shares to the rest (parties Pk+1,,PnP_{k+1}, \ldots, P_{n'})

At step 5, the verification outcome splits the new parties into two groups:

  • Group A (received valid shares): Verification passes. They proceed to step 7 and delete their old shares, replacing them with new shares.
  • Group B (received invalid shares): Verification fails. They abort the protocol and keep their old shares, not updating anything.

Now here's the problem: there's no synchronization before deletion. Parties in Group A don't know that Group B aborted. They delete their old shares and switch to the new ones.

The Consequence: The secret can no longer be reconstructed: mixing old and new shares doesn't work, they're not additive shares of the same secret anymore. Even if all parties cooperate, they can't generate a valid signature. The wallet is permanently locked.

image

This is the Forget-and-Forgive attack described in "Attacking Threshold Wallets".

The Fix Add a blame phase before deletion. After verification (step 5), parties must coordinate:

  1. Each new party broadcasts whether their verification succeeded or failed
  2. If any party reports a failure, everyone aborts, no one deletes old shares
  3. Only if all nn' new parties report success does anyone proceed to delete old shares

Nonce Reuse via Deterministic Derivation

Nonce reuse in digital signatures is a classic footgun. Everyone knows the story: reuse your nonce in ECDSA or Schnorr, and your private key leaks. The standard defenses are either (1) sample a fresh random nonce for every signature, or (2) derive the nonce deterministically as n=H(msk)n = H(m | sk) .

Option 2 seems perfect for single-party signing, it's deterministic, so you can't accidentally reuse randomness, and it binds the nonce to both the message and the secret key. But in threshold signatures, determinism becomes a weapon.

Why Nonce Reuse Breaks Schnorr

Quick reminder of why nonce reuse is fatal. Suppose you sign two different messages m1,m2m_1, m_2 with the same nonce nn:

s1=n+c1sk,s2=n+c2sks_1 = n + c_1 \cdot sk, \quad s_2 = n + c_2 \cdot sk

where c1=H(nGpkm1)c_1 = H(nG | pk | m_1) and c2=H(nGpkm2)c_2 = H(nG | pk | m_2). Subtract:

s1s2=(c1c2)sk    sk=s1s2c1c2s_1 - s_2 = (c_1 - c_2) \cdot sk \implies sk = \frac{s_1 - s_2}{c_1 - c_2}

Game over. The attacker recovers your secret key from two signatures.

The Threshold Setting

Now consider two-party Schnorr (a toy model, but the idea generalizes). Alice and Bob each hold shares sk1,sk2sk_1, sk_2 of the secret key, with public key pk=(sk1+sk2)Gpk = (sk_1 + sk_2) \cdot G. To sign message mm:

  1. Nonce generation: Each party deterministically derives their nonce:
n1=H(msk1),n2=H(msk2)n_1 = H(m | sk_1), \quad n_2 = H(m | sk_2)

They exchange public nonces N1=n1GN_1 = n_1 \cdot G and N2=n2GN_2 = n_2 \cdot G. The aggregate public nonce is N=N1+N2N = N_1 + N_2. 2. Partial signatures: Each computes the challenge c=H(Npkm)c = H(N | pk | m) and produces:

s1=n1+csk1,s2=n2+csk2s_1 = n_1 + c \cdot sk_1, \quad s_2 = n_2 + c \cdot sk_2
  1. Aggregate: The final signature is over (N,s1+s2)(N, s_1 + s_2).

So far, so good. Each party's nonce depends on their own secret key and the message, so it looks safe.

The Attack

Here's the problem: Alice (the attacker) controls her own nonce. She can choose to use a different nonce on the second signing request, even if the message is the same.

First signature (on message mm):

  • Alice honestly uses n1=H(msk1)n_1 = H(m | sk_1), sends N1=n1GN_1 = n_1 \cdot G
  • Bob uses n2=H(msk2)n_2 = H(m | sk_2), sends N2=n2GN_2 = n_2 \cdot G
  • Public nonce: N=N1+N2N = N_1 + N_2
  • Challenge: c=H(Npkm)c = H(N | pk | m)
  • Bob's partial signature: s2=n2+csk2s_2 = n_2 + c \cdot sk_2

Second signature (on the same message mm):

  • Alice picks a fresh random nonce n1n_1' (ignoring determinism), sends N1=n1GN_1' = n_1' \cdot G
  • Bob, being honest, derives the same nonce n2=H(msk2)n_2 = H(m | sk_2) again (determinism!)
  • New public nonce: N=N1+N2N' = N_1' + N_2
  • New challenge: c=H(Npkm)c' = H(N' | pk | m) (different because NNN' \neq N)
  • Bob's partial signature: s2=n2+csk2s_2' = n_2 + c' \cdot sk_2

Alice now has two partial signatures from Bob:

s2=n2+csk2,s2=n2+csk2s_2 = n_2 + c \cdot sk_2, \quad s_2' = n_2 + c' \cdot sk_2

Bob reused n2n_2, but with different challenges. Subtract:

s2s2=(cc)sk2    sk2=s2s2ccs_2 - s_2' = (c - c') \cdot sk_2 \implies sk_2 = \frac{s_2 - s_2'}{c - c'}

Alice extracts Bob's secret share. With both sk1sk_1 (her own) and sk2sk_2 (stolen), she can now sign arbitrary messages unilaterally.

This scenario was also covered in one of Jake Craige's articles.

Theoretic attacks

Most threshold signature schemes are proven secure under static corruption: the adversary chooses which parties to corrupt before the protocol starts. But what about adaptive corruption, where the adversary can corrupt parties at any time, even after seeing public keys, commitments, and partial signatures?

Adaptive security is harder to achieve and harder to prove. A recent paper asks: are widely-deployed threshold Schnorr schemes actually adaptively secure? The answer might be no, if a certain computational problem turns out to be easier than we think.

The Setup

Consider a (t,n)(t, n) threshold Schnorr scheme where:

  1. Public key shares pk1,,pknpk_1, \ldots, pk_n are public
  2. Keys are derived from a degree-(t1)(t-1) polynomial q(Z)=x0+x1Z++xt1Zt1q(Z) = x_0 + x_1 Z + \cdots + x_{t-1} Z^{t-1} over Zp\mathbb{Z}_p (where pp is the curve order):
pk=gq(0),pki=gq(zi)pk = g^{q(0)}, \quad pk_i = g^{q(z_i)}

where ziz_i are public evaluation points and ski=q(zi)sk_i = q(z_i) are the secret shares. 3. Signatures are Schnorr-compatible: verification checks gz=?Rpkcg^z \stackrel{?}{=} R \cdot pk^c where c=H(R,pk,m)c = H(R, pk, m).

This describes FROST and most modern threshold Schnorr variants.

The Problem

The authors propose a computational problem. If this problem is solvable in polynomial time, adaptive security collapses for the above schemes.

Subset-Span Problem: Given a target vector vZpt\mathbf{v} \in \mathbb{Z}_p^t and vectors k1,,knZpt\mathbf{k}_1, \ldots, \mathbf{k}_n \in \mathbb{Z}_p^t, find a subset F1,,nF \subset {1, \ldots, n} with F=ft1|F| = f \leq t-1 such that vspan(kiiF)\mathbf{v} \in \text{span}({\mathbf{k}*i}*{i \in F}) (if one exists).

In other words: can you find a small subset of vectors whose span contains the target?

The Attack

Suppose the adversary wants to forge a signature on a fresh message mm^*. They need to produce (R,z)(R^*, z^*) such that gz=Rpkcg^{z^*} = R^* \cdot pk^{c^*} where c=H(R,pk,m)c^* = H(R^*, pk, m^*). This requires knowing logg(Rpkc)\log_g(R^* \cdot pk^{c^*}), the discrete log of the verification equation's right-hand side.

Here's the plan:

Step 1: Choose RR^* carefully

Let Xi=gxiX_i = g^{x_i} be the commitments to the polynomial coefficients (note: given pk1,,pknpk_1, \ldots, pk_n, you can compute X0,,Xt1X_0, \ldots, X_{t-1} via change of basis). Set:

R=X0α0X1α1Xt1αt1R^* = X_0^{\alpha_0} X_1^{\alpha_1} \cdots X_{t-1}^{\alpha_{t-1}}

for random α0,,αt1\alpha_0, \ldots, \alpha_{t-1}. Since X0=gx0=gq(0)=pkX_0 = g^{x_0} = g^{q(0)} = pk, we have:

Rpkc=X0α0+cX1α1Xt1αt1R^* \cdot pk^{c^*} = X_0^{\alpha_0 + c^*} X_1^{\alpha_1} \cdots X_{t-1}^{\alpha_{t-1}}

where c=H(R,pk,m)c^* = H(R^*, pk, m^*) depends on our choice of RR^* (and can be computed).

Step 2: Express as a linear combination of public keys

Define vectors:

  • K0=(1,0,0,,0)ZptK_0 = (1, 0, 0, \ldots, 0) \in \mathbb{Z}_p^t
  • Kj=(1,zj,zj2,,zjt1)ZptK_j = (1, z_j, z_j^2, \ldots, z_j^{t-1}) \in \mathbb{Z}_p^t for each party jj

Note that:

XK0=i=0t1Xi(K0)i=X0=pkX^{K_0} = \prod_{i=0}^{t-1} X_i^{(K_0)*i} = X_0 = pk XKj=i=0t1Xizji=gi=0t1xizji=gq(zj)=pkjX^{K_j} = \prod*{i=0}^{t-1} X_i^{z_j^i} = g^{\sum_{i=0}^{t-1} x_i z_j^i} = g^{q(z_j)} = pk_j

Now, if we can find coefficients μ1,,μf\mu_1, \ldots, \mu_f and a subset F1,,nF \subset {1, \ldots, n} with F=ft1|F| = f \leq t-1 such that:

(α0+c,α1,,αt1)=jFμjKj(\alpha_0 + c^*, \alpha_1, \ldots, \alpha_{t-1}) = \sum_{j \in F} \mu_j K_j

then:

Rpkc=X(α0+c,α1,,αt1)=XjFμjKj=jF(XKj)μj=jFpkjμjR^* \cdot pk^{c^*} = X^{(\alpha_0 + c^*, \alpha_1, \ldots, \alpha_{t-1})} = X^{\sum_{j \in F} \mu_j K_j} = \prod_{j \in F} (X^{K_j})^{\mu_j} = \prod_{j \in F} pk_j^{\mu_j}

Taking discrete logs:

logg(Rpkc)=jFμjskj\log_g(R^* \cdot pk^{c^*}) = \sum_{j \in F} \mu_j sk_j

Step 3: Adaptive corruption

The attacker now adaptively corrupts the parties in FF, learning their secret shares skjsk_j for jFj \in F. Since Ft1|F| \leq t-1 (below the threshold), this is within the corruption budget. They compute:

z=jFμjskjz^* = \sum_{j \in F} \mu_j sk_j

and output the forged signature (R,z)(R^*, z^*). Verification passes by construction.

Why This Might Work

For any fixed subset FF of size ff, the probability that a random target vector v\mathbf{v} lies in the span of kjjF{\mathbf{k}*j}*{j \in F} is roughly pftp^{f-t} (very small). But there are (nf)\binom{n}{f} possible subsets, exponentially many. If nn is large enough , the union bound suggests that some subset FF will work with non-negligible probability.

The question is: can we find that subset efficiently? If the problem is solvable in polynomial time, then adaptive security breaks.

The above idea is described in detail in the paper "A Plausible Attack on the Adaptive Security of Threshold Schnorr Signatures".

Closing Thoughts

Implementation bugs are fixable with better testing, stricter validation, and careful reading of security proofs. Protocol issues require understanding what security properties you actually have versus what you think you have. The MtA oracle attack works because the protocol's security argument relied on range proofs that were omitted. The reshare attack works because the protocol lacked synchronization primitives. The adaptive security question for threshold Schnorr shows that even well-analyzed protocols might not hold up under stronger adversarial models.

Threshold schemes remain one of our best tools for distributed trust, but the gap between theory and practice is real and multifaceted. Make sure your implementation and your threat model match what the security proofs actually guarantee.

Attacks on Threshold Schemes: Part 2