Notes on NEAR's MPC

 

tl;dr: The good: Audit went well. Lúcás Meier’s Cait-Sith threshold ECDSA protocol seems like a reasonable, conservative choice. All MPC nodes now run in TEEs. The pretty good: Near’s MPC currently works in an 11 out of 16 setting (as of October 23rd, 2026). The bad: No proactive refresh.

Thoughts

Very good

  • MPC’s configuration is transparent, on-chain $\Rightarrow$ can monitor for suspicious membership changes
  • “uses the Cait-Sith protocol in a secure manner”1
  • “we did not identify any issues related to Beaver triple or nonce reuse that could compromise the security of a shared key”1
  • NEAR only used Cait-Sith on mainnet (as of May 1st, 2026)
    • (The MPC committee can change this over time, of course.)
    • FROST threshold signatures were added (as of October 23rd, 2026)
  • All MPC nodes on mainnet are TEE-backed (as of October 23rd, 2026)
    • They were off as of May 1st, 2026, but were turned on since

Pretty good

  • 11 out of 16 secret-sharing on mainnet, as of October 23rd, 2026 (see here)
    • It was 5 out of 8 as of May 1st, 2026
    • The Ronin Bridge attack compromised exactly $t=5$ out of $n=9$ and drained $650 million
    • The 2023 Orbit Bridge attackers obtained valid signatures from 7 out of 10 signers of Orbit’s 7-of-10 ETH Vault multisig (per the vault’s on-chain required() and getOwners()), and used them to drain $81.5 million, e.g., in this 30M USDT withdrawal.

Unclear

Somewhat concerning

  • Claude Code identified four unaddressed items from the Trails of Bits audit; they are not high-severity though:
    • #4 Ciphertext swapping (DB AAD missing) – Informational, Cryptography
    • #5 Hash function used as KDF (derive_tweak) – Informational, Cryptography
    • #6 P2P identity misbinding (duplicate p2p public keys) – Medium, Data Validation
    • #10 AES-GCM nonce reuse (96-bit random, no rotation) – Medium, Cryptography
  • NEAR modified the Cait-Sith scheme1
    • multiplicative rerandomization of pre-signatures

Concerning

  • No robustness and no identifiable abort (AFACCT)
    • a malicious participant who deviates can make signing fail (abort the protocol) and do so without being identifiable by honest parties $\Rightarrow$ 1 participant can DoS
  • NEAR had a lot of GitHub CI security issues in the Trail of Bits report (#12, #13, #141)
    • #14 could’ve allowed an attacker to release a completely malicious binary (was rated “difficult” though)

Deeply concerning

  • No proactive refresh, even though re-sharing (for nodes leaving and joining) is implemented and would be trivial to call periodically
    • Without proactive refresh, an attacker can slowly take its time and compromise all 11 keys
    • The last re-sharing (and thus refresh) was on October 22nd, 2026
      • Re-sharings have been roughly monthly since May 2026, but only because membership changed; nothing guarantees this cadence
      • $\Rightarrow$ as of May 1st, 2026, there had been no re-sharing for 2 months, so any progress an attacker made during that time was still good progress
    • Why not? Because proactive refresh must invalidate the ECDSA pre-signatures, which lowers performance.
  • The Cait-Sith threshold ECDSA library was not part of the audit; only its use by NEAR’s MPC node implementation was audited1
    • This library may not have been production-ready.

Cryptography

Why no proactive refresh?

Adopting this notation, recall that a pre-signature for $R = k \cdot G$ is a secret sharing:

\[([k^{-1}]_i, [k^{-1}\cdot \sk]_i)_{i\in[n]},\]

where:

  • $[k^{-1}]_i$ is player $i$’s ($t$-out-of-$n$) share of the inverted nonce $k^{-1}$
  • $[k^{-1}\cdot \sk]_i$ is player $i$’s share of $k^{-1}\cdot \sk$

Pre-signatures on their own are indifferent to the secret-sharing of $\sk$ changing: they remain valid. So, we can proactively refresh $\sk$ without invalidating the pre-signatures. So then why isn’t there any proactive refresh on NEAR’s MPC? My best guess? It’s because $\sk$ refresh is only meaningful if presignatures are refreshed too.

In other words, if $\ge t$ shares of a pre-signature leak, then that would reveal $k^{-1}$ and $k^{-1}\cdot \sk$, and thus reveal $\sk$. So an attacker will simply shift from compromising $\sk$ shares over a long period of time, to compromising pre-signature shares. Why aren’t presignatures refreshed? My best guess is that, this would require a lot of work5.

Even if pre-signatures were proactively refreshed, Cait-Sith relies on Beaver triples6 to quickly compute the pre-signatures. For example, to get shares $[k^{-1}\cdot \sk]_i$ from shares $[k^{-1}]_i$7 and $[\sk]_i$, first, assume you have a Beaver triple sharing $([a]_i,[b]_i,[ab]_i)$ where $a,b$ are random. Then, compute shares of masked values: $[\alpha]_i\bydef [k^{-1}]_i + [a]_i$, and $[\beta]_i\bydef [\sk]_i + [b]_i$. Then, reconstruct the masked values: $\alpha = k^{-1} + a$ and $\beta = \sk + b$. These reveal nothing since $a, b$ are random. Then, note that $k^{-1}\cdot\sk = (\alpha - a)\cdot\sk = \alpha\cdot\sk - a \cdot \sk = \alpha\cdot\sk - a\cdot(\beta - b) = \alpha\cdot\sk - \beta\cdot a + ab$, which is linear in the shared $\sk$, $a$ and $ab$. So, each player can locally compute $[k^{-1}\cdot\sk]_i = \alpha\cdot[\sk]_i - \beta\cdot[a]_i + [ab]_i$.

From the above, we can tell that a leak of $a$ (or $b$), once the triple is consumed and $\alpha$ (or $\beta$) is revealed, would leak $k^{-1}$ (or $\sk$). Recall that, given $k^{-1}$ and a signature $(r,s)$ and the signed message $m$, one can recover $\sk$. Therefore, Beaver triples should also be proactively refreshed to minimize the likelihood that a long-term attacker can pull off such a stunt. Again, as with pre-signature refresh5, such Beaver triple refresh is expensive too: 1.5x more expensive, in fact, since Beaver triples have 3 secret-shared values, while pre-signatures have 2.

As of September 2026, NEAR added an online presign-and-sign path, which computes the pre-signature only after the signing request arrives and consumes it immediately, so no pre-signatures are stored. This shrinks the problem a little, since there are no stored pre-signatures left to refresh. But it does not solve it: the Beaver triples are still precomputed and stored, so they would still need to be refreshed.

Why presignature rerandomization exists

tl;dr: Rerandomization prevents an $O(q^{1/3})$-time forgery attack on ECDSA with presignatures and additive key derivation, due to Groth and Shoup8. It does not protect against presignature reuse.

NEAR’s MPC supports additive key derivation: an app’s secret key is $\sk + e$, where the tweak $e = H(\mathsf{app\_id}, \mathsf{path})$ is public. Here, $\mathsf{app\_id}$ identifies the app requesting the signature9 and $\mathsf{path}$ is an arbitrary derivation path chosen by the app (e.g., alice@gmail.com/bitcoin), which lets one app control many keys. A presignature for the master $\sk$ is locally adapted to $\sk + e$ via:

\[[k^{-1}\cdot(\sk + e)]_i = [k^{-1}\cdot \sk]_i + e\cdot [k^{-1}]_i\]

The problem is that, with presignatures, $R$ (and thus $r$) is known before the message $m$ and the tweak $e$ are chosen (e.g., any corrupted MPC node knows it). Groth and Shoup8 show this enables a forgery: find $(m,e)\ne(m^*,e^*)$ such that $H(m) + r\cdot e = H(m^*) + r\cdot e^*$, and ask for a signature on $m$ under tweak $e$. Since $s = k^{-1}(H(m) + r\cdot e + r\cdot\sk) = k^{-1}(H(m^*) + r\cdot e^* + r\cdot\sk)$, it is also a valid signature on $m^*$ under tweak $e^*$. Finding such a pair is a 4-sum problem, which Wagner’s algorithm10 solves in $O(q^{1/3})$ time when enough tweaks are available, faster than the best $O(q^{1/2})$ attack on plain ECDSA.

Groth and Shoup’s fix is to rerandomize the presignature at signing time via $R \gets R + \delta\cdot G$ (i.e., $k\gets k+\delta$), where $\delta$ is public but unpredictable. Since $r$ is now unknown when $(m,e)$ is chosen, the attack no longer works.

NEAR instead rerandomizes multiplicatively: the new nonce is $k’ \bydef \delta\cdot k$, so $R’ = \delta\cdot R$ and $k’^{-1} = \delta^{-1}\cdot k^{-1}$. Combined with the key derivation above, each player computes its shares of the new presignature for $\sk + e$, starting from its old shares $[k^{-1}]_i$ and $[k^{-1}\cdot\sk]_i$. First, the inverted nonce share is simply scaled by $\delta^{-1}$:

\[\delta^{-1}\cdot [k^{-1}]_i = [\delta^{-1}\cdot k^{-1}]_i = \emph{[k'^{-1}]_i}\]

Second, the other share is shifted by $e$ and then scaled by $\delta^{-1}$:

\begin{align} \delta^{-1}\cdot\left([k^{-1}\cdot\sk]_i + e\cdot[k^{-1}]_i\right) &= \delta^{-1}\cdot[k^{-1}\cdot\sk + e\cdot k^{-1}]_i\\
&= \delta^{-1}\cdot[k^{-1}\cdot(\sk + e)]_i\\
&= [\delta^{-1}\cdot k^{-1}\cdot(\sk + e)]_i\\
&= \emph{[k’^{-1}\cdot(\sk + e)]_i} \end{align}

Here, $\delta$ is derived via HKDF from $(\pk, e, H(m), R, \mathsf{participants})$, keyed by the NEAR block’s random value, which the requester cannot predict. Recall that $\pk = \sk\cdot G$ is the master public key; $\mathsf{participants}$ is the set of MPC nodes taking part in this signing session.

As mentioned earlier, NEAR added an online presign-and-sign path, which computes the pre-signature only after the signing request arrives and consumes it immediately, so no pre-signatures are stored. This path skips rerandomization (i.e., $\delta = 1$), since $R$ is only computed after $(m, e)$ is chosen, so the attack above does not apply.

Two caveats:

  • Groth and Shoup only prove security for additive rerandomization with a random $\delta$; they leave hash-derived $\delta$ unanalyzed, and never consider the multiplicative variant.
  • ToB’s audit1 notes NEAR did its own analysis of the multiplicative variant, which ToB reviewed only at a high level, recommending further peer review.

Was not able to find the proof in their repo.

Resources

MPC node operators

Operators:

  • lacksandtech.near,
  • mpc-lgns.near,
  • multichain-mainnet-aurora.near,
  • near-mpc-staking4all-01.near,
  • nodemonster.near,
  • n1-multichain.near,
  • everstake-mpc-1.near,
  • stakin-mpc.near

NEAR-affiliated names visible:

  • n1-multichain.near (NEAR One)
  • multichain-mainnet-aurora.near (Aurora)

The rest are independent operators (Everstake, Stakin, etc.).

Script: Fetch all MPC participants

curl -s -X POST https://rpc.mainnet.near.org -H "Content-Type: application/json" -d '{
    "jsonrpc":"2.0","id":"1","method":"query",
    "params":{"request_type":"call_function","finality":"final",
              "account_id":"v1.signer","method_name":"state","args_base64":"e30="}
  }' | jq -r '.result.result | implode' | jq .

Script: MPC membership over time

Based on visible on-chain history, no pure refresh (same set) has happened on mainnet. Every reshare was triggered by a membership change.

Here’s what each epoch’s vote_new_parameters proposal actually contained (winning proposals only, ordered by epoch):

Epoch Finalized n / threshold Membership delta from previous
3 2025-08-25 8 / 5 (earliest vote_new_parameters call against this contract — see note)
4 2025-09-17 10 / 7 + everstake-mpc-1.near, + stakin-mpc.near
5 2025-11-21 9 / 6 − lifted-mainnet.near
6 2026-03-03 8 / 5 − chain-signatures-hot.near
7 2026-05-19 9 / 6 + mpch-01.near
8 2026-06-22 10 / 7 + svrn-01.near
9 (cancelled) 9 / 7 − n1-multichain.near, via a verify_tee kickout on 2026-07-03; the CKD domain’s re-sharing kept failing, so it was cancelled and n1-multichain.near stayed
10 2026-07-31 11 / 7 + greenfield-mpc01.near
11 2026-08-06 13 / 8 + hashkeympc.near, + natsai-mpc.near
12 2026-08-17 15 / 9 + astrostakers-mainnet.near, + klever-nearmpc-01.near
13 2026-09-17 17 / 11 + bitwise-mpc01.near, + nansen-ai-mpc.near
14 2026-10-22 16 / 11 − blacksandtech.near

Run this vibe-coded script to reproduce these results.

References

For cited works, see below 👇👇

  1. NEAR One MPC Chain Signatures, by Fredrik Dahlgren, Marc Ilunga, and Jim Miller, 2025, [URL] ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  2. Towards Modular Foundations for Protocol Security, by Lúcás Críostóir Meier, in Cryptology {ePrint} Archive, Paper 2023/187, 2023, [URL] ↩

  3. Cait-Sith: Overview, Lucas Meier, April 16th, 2023 ↩

  4. Fast Threshold {ECDSA} with Honest Majority, by Ivan Damgård and Thomas Pelle Jakobsen and Jesper Buus Nielsen and Jakob Illeborg Pagter and Michael Bæksvang Østergård, in Cryptology {ePrint} Archive, Paper 2020/501, 2020, [URL] ↩ ↩2

  5. Specifically, for each presignature, each player refreshes it by dealing two random sharings of 0 to everyone. Then, each player adds the two zero-shares it receives from all players to its two presignature shares. ↩ ↩2

  6. Efficient Multiparty Protocols Using Circuit Randomization, by Beaver, Donald, in Advances in Cryptology — CRYPTO ‘91, 1992 ↩

  7. In fact, computing $([k^{-1}]_i, k\cdot G)$ itself also relies on a $(u, d, ud)$ Beaver triple, plus the public points $u\cdot G$, $d\cdot G$ and $ud\cdot G$. Cait-Sith simply sets $k^{-1} \bydef u$, so the players already hold shares of $k^{-1}$. The problem is that $R\bydef k\cdot G$, but only $k^{-1}\cdot G$ is public, and we can’t invert inside the exponent. Instead, the players open the product $ud = k^{-1}d$ in the clear, which is safe because the random $d$ masks $k^{-1}$. Everyone then computes $R = (k^{-1}d)^{-1}\cdot(d\cdot G) = k\cdot d^{-1}\cdot d\cdot G = k\cdot G$. ↩

  8. On the security of ECDSA with additive key derivation and presignatures, by Jens Groth and Victor Shoup, in Cryptology ePrint Archive, Report 2021/1330, 2021, [URL] ↩ ↩2

  9. Concretely, $\mathsf{app\_id}$ is the NEAR account that calls the MPC contract’s sign method (i.e., the predecessor_id), which is typically an app’s contract, but could also be a user’s account. ↩

  10. A Generalized Birthday Problem, by Wagner, David, in Advances in Cryptology — CRYPTO 2002, 2002 ↩

  11. Cait-Sith threshold ECDSA signatures, by Lúcás Meier, GitHub repo ↩