Skip to content
ZIPs.tools

ZIP 2005

Ironwood Quantum Recoverability

  • Proposed
Proposal metadata
ID
2005
Status
Proposed
Category
Consensus
Owners
  • Daira-Emma Hopwood
  • Jack Grigg
Created
2025-03-31
License
MIT
Contents
  1. Terminology
  2. Abstract
  3. Motivation
  4. Requirements
  5. Non-requirements
  6. High-level summary of changes
  7. Flow diagram for the Orchard protocol
  8. Specification
  9. Proactive movement of funds to recoverable notes
  10. Usage with FROST
  11. Usage with hardware wallets
  12. Usage with other proposals requiring note plaintext format changes
  13. Specification Updates
Preamble
ZIP
2005
Title
Ironwood Quantum Recoverability
Credits
  • Sean Bowe
  • Dev Ojha
  • Kris Nuttycombe
Status
Proposed
Category
Consensus
Created
2025-03-31
License
MIT

Terminology

The key words "MUST", "SHOULD", and "MAY" in this document are to be interpreted as described in BCP 14 1 when, and only when, they appear in all capitals.

The term "network upgrade" in this document is to be interpreted as described in ZIP 200. 2

The character § is used when referring to sections of the Zcash Protocol Specification. 3

The terms "Mainnet" and "Testnet" are to be interpreted as described in § 3.12 ‘Mainnet and Testnet’. 4

We use the convention followed in the protocol specification that an underlined‾\underline{\mathsf{underlined}} variable indicates a byte sequence, and a variable suffixed with ⋆\star indicates a bit-sequence encoding of an elliptic curve point.

The notation (kn){k \choose n} denotes the binomial coefficient — the number of ways of choosing nn items from a set of kk, which is equal to k!n!(k−n)!\frac{k!}{n!(k-n)!} for 0≤n≤k0 \leq n \leq k.

For brevity, in the discussion sections of this ZIP we abbreviate Hrcm,Orchard\mathsf{H^{rcm,Orchard}} as Hrcm\mathsf{H^{rcm}}, PRFnfOrchard\mathsf{PRF^{nfOrchard}} as PRFnf\mathsf{PRF^{nf}}, KOrchard\mathcal{K}^{\mathsf{Orchard}} as K\mathcal{K}, and similarly for other Orchard-protocol-specific hash function names. The changes to the protocol specification and to other ZIPs use the full forms.

We will use the syntax Constructor1(T1)∣Constructor2(T2)\mathsf{Constructor}_1(T_1) \mid \mathsf{Constructor}_2(T_2) for a tagged union type with tags Constructor1\mathsf{Constructor}_1 and Constructor2\mathsf{Constructor}_2. Such types can be destructured using a match\text{match} construct:

match e with{Constructor1(t1) ⁣ ⁣ ⁣⇒f(t1)Constructor2(t2) ⁣ ⁣ ⁣⇒g(t2).\hspace{2em}\text{match } e \text{ with} \begin{cases} \mathsf{Constructor}_1(t_1) \!\!\!&\Rightarrow f(t_1) \\ \mathsf{Constructor}_2(t_2) \!\!\!&\Rightarrow g(t_2)\textsf{.} \end{cases}

The terms "Ironwood pool" and "Orchard pool" are to be interpreted as described in 5. Following the convention in the protocol specification, we use slanted text to refer to pool names, in order to more clearly distinguish them from shielded protocols.

The terms "recoverable note" and "recoverable note plaintext" refer to a note or note plaintext that was created according to this proposal. As initially deployed, these are necessarily Ironwood-pool notes or note plaintexts.

The term "Recovery Protocol" refers to a potential new shielded protocol that would allow recovery of funds held in recoverable Ironwood-pool notes. This ZIP describes the Recovery Protocol in outline but not in detail: many of its design decisions are intentionally left open. The Recovery Protocol would also allow recovering notes created according to the ZSA extension to the Orchard protocol 6 7 if that were deployed.

Abstract

This ZIP proposes a change to the construction of notes, to be deployed for the Ironwood pool 5, designed to improve Zcash's long-term resilience against a significant potential threat to its security from quantum computers. It does not by itself make the protocol secure against quantum adversaries, but is intended to support a smoother transition to future versions of Zcash designed to be so.

The existing Zcash shielded protocols are dependent on the hardness of finding discrete logarithms; an adversary who can do so (via quantum computers or otherwise) would be able to steal or forge funds. In the event of needing to disable these protocols in order to prevent such attacks, it will be possible to use a Recovery Protocol to recover funds from the Ironwood pool. This Recovery Protocol is expected to remain secure against discrete-logarithm-breaking and quantum adversaries. This change does not by itself make Zcash secure against attacks using quantum computers, but is a necessary and substantial step toward that goal.

Recovery would not be possible for funds still in the Sprout, Sapling, or Orchard pools; all such funds would be inaccessible after their respective protocols are disabled. They should be migrated to the Ironwood pool in order to take advantage of this change.

Motivation

If quantum computers —or any other attack that allows finding discrete logarithms on the elliptic curves used in Zcash— were to become practical, it would raise difficult issues for the Zcash community. An adversary able to compute discrete logarithms (in fact, a single discrete logarithm is sufficient) could cause arbitrary inflation or steal users' funds.

Critically, the note commitment algorithms used by the Sapling and Orchard shielded protocols are not post-quantum binding. This means that even if the proof system were upgraded to one that is believed to be secure against quantum computers, and even if the note commitment tree were to be reconstructed (from public information) to use a suitable hash function, it would still be possible for a quantum or discrete-logarithm-breaking adversary to forge and spend notes that are not actually in the commitment tree — thus breaking the Balance property.

This ZIP proposes a small change to the way Orchard-protocol notes are derived, that would apply to all notes in the new Ironwood pool. If this change is made well in advance of quantum computers becoming viable, it would provide time for users to move their funds to the Ironwood pool, keeping them safe and recoverable after a subsequent post-quantum transition. This would not require any change to the Orchard-protocol (or proposed OrchardZSA-protocol) circuits for the time being, and would not require deciding on the particular proof system or note commitment tree hash used in the future protocol.

Recovering these funds after the post-quantum transition would involve checking a more expensive and complicated statement in zero knowledge, but it is expected that this will be entirely practical for the intended usage of recovering funds into another shielded pool. The current privacy properties of the Orchard protocol would be retained against pre-quantum adversaries, and also against post-quantum adversaries without knowledge of the notes' addresses. 8

To reduce overall protocol complexity and analysis effort, we do not propose a similar change for Sapling. Instead, Sapling funds can be migrated to the Ironwood pool in order to make them quantum-recoverable. (Note that this analysis effort needs to include the child and internal key derivations defined in ZIP 32, which differ significantly between the Sapling 9 10 and Orchard 11 12 protocols.)

This proposal is implementable at low risk, and required changes to existing libraries and wallets are small. It is compatible with Memo Bundles 13 and/or ZSAs 6.

Requirements

  • Ironwood-pool notes constructed according to this proposal should be spendable via a Recovery Protocol (to be introduced, potentially, in a future upgrade) that is expected to be secure against discrete-logarithm-breaking and quantum adversaries.
  • No particular choice of post-quantum proving system or commitment tree hash should be assumed for that alternate protocol.
  • The proposed scheme should be fully compatible with FROST threshold multisignatures 14, hardware wallets, and the combination of both.
  • The proposed scheme should not require regeneration of existing non-multisignature keys or addresses.
  • It should be possible for wallets to identify what subset of a user's funds have been made recoverable.
  • The changes made to the pre-quantum protocol should not cause a significant regression in performance, applicability, or security against any given adversary class, or require significant re-analysis of that protocol's pre-quantum security.
  • The Recovery Protocol should ensure no loss of security against pre-quantum adversaries — including when FROST threshold multisignatures and/or hardware wallets are used.
  • Recovery of funds from hardware wallets that support this protocol should not require exposing the pre-quantum spend authorizing key ask\mathsf{ask} to theft.
  • The proposal should be compatible with Zcash Shielded Assets with minimal additional complexity 6 7.

Non-requirements

  • It is not required to address discrete-logarithm-breaking or quantum attacks on privacy with this proposal, as long as it does not cause any regression in privacy properties.
  • It is not required to add support for the Recovery Protocol to consensus rules now.
  • It is not required for spends using the Recovery Protocol to be as efficient as spends using the Orchard or Sapling protocols.
  • It is not anticipated that spends using the Recovery Protocol will need to be indistinguishable from non-Recovery spends.

High-level summary of changes

This subsection and the flow diagram below are non-normative.

This proposal defines a new note plaintext format to be used for recoverable notes (that is, those in the Ironwood pool), with lead byte 0x03\mathtt{0x03}. The pre_rcm\mathsf{pre\_rcm} value is computed differently for this new format, by including all of the note fields in pre_rcm\mathsf{pre\_rcm}. This means that an adversary constrained to treat the PRF used to derive rcm\mathsf{rcm} from pre_rcm\mathsf{pre\_rcm} as a random oracle, could not vary any note field without producing a different rcm\mathsf{rcm}. This lets us argue that the overall commitment scheme is post-quantum binding, as long as the new derivation of rcm\mathsf{rcm} is checked in the Recovery Protocol.

Essentially the same technique also needs to be applied to the function Commitivk\mathsf{Commit^{ivk}} that is used to derive Orchard-protocol incoming viewing keys. The randomness rivk\mathsf{rivk} in Commitivk\mathsf{Commit^{ivk}} is derived directly or indirectly from rivk_ext\mathsf{rivk\_ext}, which is in turn derived from one of two random oracles, depending on which key material the user holds:

  • For existing Orchard-protocol keys, rivk_ext\mathsf{rivk\_ext} is derived from the secret key sk\mathsf{sk} via Hrivk_legacy(sk)\mathsf{H^{rivk\_legacy}}(\mathsf{sk}), with ak\mathsf{ak} and nk\mathsf{nk} also derived from sk\mathsf{sk}. The Recovery Protocol checks all three derivations.
  • For keys generated via FROST distributed key generation, or for hardware wallets where exporting sk\mathsf{sk} is undesirable, an alternative "quantum spending key" qsk\mathsf{qsk} and "quantum intermediate key" qk\mathsf{qk} are used, with rivk_ext=Hqkrivk_ext(ak,nk)\mathsf{rivk\_ext} = \mathsf{H^{rivk\_ext}_{qk}}(\mathsf{ak}, \mathsf{nk}). The Recovery Protocol checks this derivation together with a SoKqsk\mathsf{SoK^{qsk}} proof of knowledge of qsk\mathsf{qsk} such that Hqk(qsk)=qk\mathsf{H^{qk}}(\mathsf{qsk}) = \mathsf{qk}.

Both branches (and both cases rivk∈{rivk_ext,Hrivk_extrivk_int(ak,nk)}\mathsf{rivk} \in \{ \mathsf{rivk\_ext}, \mathsf{H^{rivk\_int}_{rivk\_ext}}(\mathsf{ak}, \mathsf{nk}) \}) are covered uniformly by the Security argument for key binding: each binds the keys (ak,nk,rivk)(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk}) —and qk\mathsf{qk}, including whether it is in use— to the incoming-viewing key ivk\mathsf{ivk} post-quantumly, up to a small advantage against collision-finding in the random oracles used for rivk\mathsf{rivk} derivation. The FROST and hardware-wallet use cases are described in Usage with FROST and Usage with hardware wallets.

Flow diagram for the Orchard protocol

This diagram shows, approximately, the derivation of Orchard-protocol keys, addresses, notes, note commitments, and nullifiers. All of the flow diagrams in this ZIP omit type conversions between curve points, field elements, byte sequences, and bit sequences, and so are not sufficiently precise to be used directly as a guide for implementation.

---
title: "Key to flow diagrams"
---
graph BT
  classDef default stroke:#111111;
  classDef func fill:#d0ffb8;
  classDef cefunc fill:#a0e0a0;
  classDef sensitive fill:#ffb0b0;
  classDef semi_sensitive fill:#ffb0ff;
  classDef keybox stroke:#808080, fill:#ffffff;
  classDef spacer opacity:0;

  key([sensitive key]):::sensitive ~~~ function:::func
  value([value]) ~~~ cond{{conditional value}}
  dummyA( ) -->|existing| dummyB( )
  dummyC( ) ==>|new| dummyD( )
  dummyE( ) -.->|optional| dummyF( )

The bold lines are changes introduced by this ZIP, which all take the form of additional inputs to derivation functions or alternative derivations. The derivations shown in the box labelled Proposed Recovery Statement are, roughly speaking, those enforced by the section of that name. The diagram shows the recoverable-note case (leadByte=0x03\mathsf{leadByte} = \mathtt{0x03}); for leadByte=0x02\mathsf{leadByte} = \mathtt{0x02} the existing Orchard-protocol derivation rcm=ToScalarOrchard(PRFrseedexpand([0x05] ∣∣ ρ‾))\mathsf{rcm} = \mathsf{ToScalar^{Orchard}}\big(\mathsf{PRF^{expand}_{rseed}}([\mathtt{0x05}] \,||\, \underline{\text{ρ}})\kern-0.1em\big) applies, and the additional fields feeding into pre_rcm\mathsf{pre\_rcm} are absent.

graph BT
  classDef default stroke:#111111;
  classDef func fill:#d0ffb8;
  classDef cefunc fill:#a0e0a0;
  classDef sensitive fill:#ffb0b0;
  classDef semi_sensitive fill:#ffb0ff;
  classDef circuit stroke:#000000, fill:#fffff0;
  classDef spacer opacity:0;

  PostQC:::circuit
  subgraph PostQC[<div style="margin:1.1em;font-size:20px"><b>Proposed Recovery Statement</b></div>]
    direction BT
    rivk_ext([rivk_ext]) --> Hrivk_int[H<sup>rivk_int</sup>]:::func
    ak([ak]) --> Hrivk_int[H<sup>rivk_int</sup>]:::func
    nk --> Hrivk_int
    rivk_ext -->|¬is_internal_rivk| rivk
    Hrivk_int -->|is_internal_rivk| rivk{{rivk}}
    rivk --> Commitivk[Commit<sup>ivk</sup>]:::func
    ak([ak]) ----> Commitivk
    nk([nk]) ----> Commitivk
    Commitivk ---> ivk([ivk])
    gd ---> ivkmul[[ivk]g<sub>d</sub>&nbsp;]:::func
    ivk --> ivkmul
    rseed --> Hpsi[H<sup>ψ</sup>]:::func
    rho --> Hpsi
    v([#8239;v#8239;]) ==> pre_rcm([pre_rcm])
    pkd ====> pre_rcm
    gd ==> pre_rcm
    psi ===> pre_rcm
    rho([#8239;ρ#8239;]) --> pre_rcm
    v ~~~~ rcm
    ivkmul --> pkd([pk<sub>d</sub>])
    pre_rcm --> Hrcm[H<sup>rcm</sup>]:::func
    rseed([rseed]) --> Hrcm
    Hrcm --> rcm([rcm])
    Hpsi --> psi([#8239;ψ#8239;])
    gd --> NoteCommit:::func
    pkd --> NoteCommit
    psi --> NoteCommit
    v --> NoteCommit
    rcm --> NoteCommit
    rho --> NoteCommit
    cm --> DeriveNullifier:::func
    psi --> DeriveNullifier
    rho --> DeriveNullifier
    nk --> DeriveNullifier
    NoteCommit --> cm([cm])
    DeriveNullifier --> nf([nf])
    cm --> cmx([cm<sub><i>x</i></sub>])
  end

  d([#8239;d#8239;]) --> HashToCurve:::func ------> gd([g<sub>d</sub>])

Specification

Proactive movement of funds to recoverable notes

Once this proposal is deployed, wallets SHOULD move all of the funds they control (including transparent, Sprout, and Sapling funds) into recoverable Ironwood-pool notes as soon as practically possible. Other wallets are REQUIRED, as part of supporting the NU6.3 upgrade, to be able to receive these notes.

Non-recoverable funds may be received after existing funds have been made recoverable. Wallets SHOULD therefore treat the movement of funds to recoverable notes as an ongoing process.

Usage with FROST

When generating Orchard-protocol keys for FROST, ak\mathsf{ak} will be derived jointly from the participants' shares of ask\mathsf{ask} according to the FROST Distributed Key Generation (DKG) protocol.

This ZIP further constrains FROST key generation for the Orchard procotol as follows: participants MUST privately agree on a value sk\mathsf{sk}, and then use it with use_qsk=true\mathsf{use\_qsk} = \mathsf{true} to derive nk\mathsf{nk}, qsk\mathsf{qsk}, qk\mathsf{qk}, and (using the ak\mathsf{ak} output by the DKG protocol) rivk_ext\mathsf{rivk\_ext}, as specified in § 4.2.3 ‘Orchard Key Components’ 15.

graph BT
  classDef default stroke:#111111;
  classDef func fill:#d0ffb8;
  classDef cefunc fill:#a0e0a0;
  classDef sensitive fill:#ffb0b0;
  classDef semi_sensitive fill:#ffb0ff;
  classDef circuit stroke:#000000, fill:#fffff0;
  classDef spacer opacity:0;

  sk([sk]):::sensitive --> Hnk[H<sup>nk</sup>]:::func ----> nk([nk])
  sk --> Hqsk[H<sup>qsk</sup>]:::func --> qsk([qsk]):::sensitive
  qk ==> Hrivk_ext
  nk ==> Hrivk_ext
  FROST_DKG --> ak([ak]) --> FROST_Sign
  FROST_DKG ~~~ s( ):::spacer ~~~ FROST_Sign
  FROST_DKG --> ask([ask<sub>i</sub>]):::sensitive --> FROST_Sign
  ak ==> Hrivk_ext[H<sup>rivk_ext</sup>]:::func
  Hrivk_ext ==>|use_qsk| rivk_ext([rivk_ext])

  HWW1:::circuit
  subgraph HWW1[<div style="margin:1.6em;font-size:20px"><br><br><br><br><br><br><br><br><br><b>SoK<sup>qsk</sup></b></div>]
    qsk([qsk]):::sensitive ==> Hqk[H<sup>qk</sup>]:::cefunc
    Hqk ==> qk([qk]):::semi_sensitive
  end

The protocol MUST ensure that all participants obtain the same values for ak\mathsf{ak}, nk\mathsf{nk}, and rivk_ext\mathsf{rivk\_ext}. (Provided that the participants have followed § 4.2.3, this implies that they have the same qsk\mathsf{qsk} and qk\mathsf{qk}, by collision resistance of Hqk\mathsf{H^{qk}} and Hrivk_ext\mathsf{H^{rivk\_ext}}.)

Each participant MUST treat qsk\mathsf{qsk} as a secret held at least as securely and reliably as ask\mathsf{ask}. Note that qsk\mathsf{qsk} will not be needed to sign unless and until the Recovery Protocol is needed, but it is essential that it be retained, otherwise funds could be lost if and when the current Orchard protocol is disabled.

The Recovery Protocol will still require a RedDSA signature verifiable by the Spend validating key ak\mathsf{ak}, in addition to knowledge of qsk\mathsf{qsk}. RedDSA is not secure in the long term against a quantum or discrete-logarithm-breaking adversary. However, during any period in which the adversary cannot find discrete logarithms on the Pallas curve, checking this RedDSA signature will ensure that spend authorization continues to require a tt-of-nn threshold of participants. An important advantage of FROST —that the parties can sign using their shares without reconstructing ask\mathsf{ask}, the Spend authorizing key— is retained.

Note that a quantum adversary may be able to steal the funds with only access to qsk\mathsf{qsk}, which is held by every participant (see below for more detail on Key storage options). Therefore, it is RECOMMENDED that as soon as a fully post-quantum protocol that supports threshold multisignatures is available, all funds held under FROST keys be transferred into that protocol's shielded pool.

Usage with hardware wallets

The same use_qsk\mathsf{use\_qsk} option can help to improve the efficiency of using the Recovery Protocol with hardware wallets. If the keys rivk_ext\mathsf{rivk\_ext}, nk\mathsf{nk}, and ak\mathsf{ak} are generated from sk\mathsf{sk}, then the circuit for the Recovery Protocol will need to prove their correct derivation using Hrivk_legacy\mathsf{H^{rivk\_legacy}}, Hnk\mathsf{H^{nk}}, Hask\mathsf{H^{ask}}, and DerivePublic\mathsf{DerivePublic} as shown in the SoKsk\mathsf{SoK^{sk}} box of the diagram below.

graph BT
  classDef default stroke:#111111;
  classDef func fill:#d0ffb8;
  classDef cefunc fill:#a0e0a0;
  classDef sensitive fill:#ffb0b0;
  classDef semi_sensitive fill:#ffb0ff;
  classDef circuit stroke:#000000, fill:#fffff0;
  classDef spacer opacity:0;

  HWW1:::circuit
  subgraph HWW1[<div style="margin:1.1em;font-size:20px"><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><b>SoK<sup>sk</sup></b></div>]
    sk --> Hrivk_legacy[H<sup>rivk_legacy</sup>]:::func ----> rivk_legacy
    DerivePublic --> ak([ak])
    sk([sk]):::sensitive --> Hnk[H<sup>nk</sup>]:::func ----> nk([nk])
    sk --> Hask[H<sup>ask</sup>]:::func --> ask([ask]):::sensitive
    ask --> DerivePublic:::func
  end

  HWW2:::circuit
  subgraph HWW2[<div style="margin:1.6em;font-size:20px"><br><br><br><br><br><br><br><br><br><b>SoK<sup>qsk</sup></b></div>]
    qsk([qsk]):::sensitive ==> Hqk[H<sup>qk</sup>]:::cefunc
    Hqk ==> qk([qk]):::semi_sensitive
  end

  sk -.-> Hqsk[H<sup>qsk</sup>]:::func -.-> qsk
  qk ==> Hrivk_ext[H<sup>rivk_ext</sup>]:::func
  nk([nk]) ==> Hrivk_ext
  ak ==> Hrivk_ext
  Hrivk_ext ==>|use_qsk| rivk_ext{{rivk_ext}}
  rivk_legacy([rivk_legacy]) -->|¬use_qsk| rivk_ext

When use_qsk\mathsf{use\_qsk} is used, on the other hand, it is possible for the Recovery Protocol to support spend authorization using a simpler statement that only uses Hqk\mathsf{H^{qk}} and a commitment scheme. For example, for some hiding and collapse-binding commitment

clink=LinkCommitr(qk,sighash)\mathsf{c_{link}} = \mathsf{LinkCommit}_r(\mathsf{qk}, \mathsf{sighash})

the hardware wallet could prove knowledge of (qsk,r)(\mathsf{qsk}, r) such that

clink=LinkCommitr(Hqk(qsk),sighash).\mathsf{c_{link}} = \mathsf{LinkCommit}_r(\mathsf{H^{qk}}(\mathsf{qsk}), \mathsf{sighash})\textsf{.}

This statement, labelled as SoKqsk\mathsf{SoK^{qsk}} in the diagram, can be implemented in a much smaller circuit, so it might be feasible to do the proof in quite constrained hardware.

The commitment clink\mathsf{c_{link}} would be a public input opened to (qk,sighash)(\mathsf{qk}, \mathsf{sighash}) in the Recovery Statement, ensuring that the hardware wallet has authorized the spend for the correct key. Because LinkCommit\mathsf{LinkCommit} is hiding and the proofs are zero knowledge, no information is leaked about which qk\mathsf{qk} is being used.

Key storage options and analysis

By host wallet, we mean the device that builds the spend transaction and produces the rest of the Recovery Statement proof. In a multi-signer FROST setup, this would be the Coordinator 16. The host wallet is given nk\mathsf{nk}, ak\mathsf{ak}, and (assuming use_qsk\mathsf{use\_qsk} is true) qk\mathsf{qk}, for use in the Recovery Statement. Then two options are possible for storage of qsk\mathsf{qsk}:

Option A — The SoKqsk\mathsf{SoK^{qsk}} proof is produced inside the hardware wallet, and qsk\mathsf{qsk} is retained there.

Option B — Alternatively, if the hardware wallet is unable to support proving SoKqsk\mathsf{SoK^{qsk}}, it could be updated to permit exporting qsk\mathsf{qsk} to the host wallet, and the SoKqsk\mathsf{SoK^{qsk}} proof would be produced there.

In either option, ask\mathsf{ask} would remain on the hardware wallet which would continue to produce RedDSA spend authorization signatures (or perform its part of the FROST multi-signing protocol).

Threat model

The Recovery Statement is assumed below to require both of:

  • an SoKqsk\mathsf{SoK^{qsk}} proof verifying knowledge of qsk\mathsf{qsk} such that Hqk(qsk)=qk\mathsf{H^{qk}}(\mathsf{qsk}) = \mathsf{qk} for the spent note's qk\mathsf{qk}; and
  • a RedDSA signature on ak\mathsf{ak}, which under FROST is constructed by cooperation of tt-of-nn hardware-wallet signers, each contributing using its share of ask\mathsf{ask}.

Under this assumed structure, with FROST + hardware-wallet deployment, spend authorization is broken only by either:

  1. qsk\mathsf{qsk} possession + finding discrete logarithms on the Pallas curve. The variants differ only in how qsk\mathsf{qsk} is obtained:

    1. the adversary is an authorized FROST signer — they hold a copy of qsk\mathsf{qsk} by construction;
    2. qsk\mathsf{qsk} is extracted from a hardware wallet, defeating Option A by a physical-device or side-channel attack;
    3. qsk\mathsf{qsk} is obtained after export to the host wallet, by compromising the host wallet or intercepting it during export.
  2. Breaking a primitive or scheme. RedDSA, FROST, the DKG, or the proving system has a cryptographic weakness or implementation flaw.

Choosing between Options A and B

Option A is preferred where the target hardware wallet is capable of proving SoKqsk\mathsf{SoK^{qsk}} on-device. Option B is a fallback for cases where it cannot — for instance, due to memory or secure-element constraints, uncertainty about the proof system that will be chosen and what will be tractable on small devices, or the device having been obsoleted before firmware support could be added.

Under Option A, the host wallet holds only the full viewing key (ak\mathsf{ak}, nk\mathsf{nk}) —which the pre-Quantum-Recoverability protocol already entrusted to it— plus qk\mathsf{qk}. The qsk\mathsf{qsk} attack surface is then 1.a. or 1.b. only.

Option B additionally places qsk\mathsf{qsk} on the host wallet, admitting case 1.c. as well. This has the disadvantage that host-wallet compromise is a substantially larger attack surface than hardware-wallet extraction. However, even with qsk\mathsf{qsk} in hand, an adversary would still need to break RedDSA or find discrete logarithms on the Pallas curve to steal funds.

Note: with ZIP 32 hierarchical derivation, qsk\mathsf{qsk} need not be backed up separately from the seed phrase. When use_qsk\mathsf{use\_qsk} is true, qsk=Hqsk(sk)\mathsf{qsk} = \mathsf{H^{qsk}}(\mathsf{sk}) where sk\mathsf{sk} is the HD-derived spending key, and so qsk\mathsf{qsk} can be re-derived from the seed phrase (with or without SLIP 39 Shamir backup 17). A deployment that does not use ZIP 32 is responsible for the security of its own backup arrangements.

Usage with other proposals requiring note plaintext format changes

This proposal was originally designed to be deployed alongside ZSAs 6 7 and memo bundles 13, which also defined a new note plaintext format. Since this proposal now defines lead byte 0x03\mathtt{0x03}, those proposals will need to use a new lead byte value or values.

Specification Updates

This is written as a set of changes relative to version 2026.7.0 of the protocol specification 18, and to the contents of ZIPs as of July 2026. The protocol specification changes will be applied in version 2026.8.0 3.

Changes to the Protocol Specification

§ 3.2.1 ‘Note Plaintexts and Memo Fields’

Replace the paragraph

Define allowedLeadBytesprotocol(height,txVersion)=\mathsf{allowedLeadBytes^{protocol}}(\mathsf{height}, \mathsf{txVersion}) = {{0x01}, ⁣ ⁣ ⁣if height<CanopyActivationHeight{0x01,0x02}, ⁣ ⁣ ⁣if CanopyActivationHeight≤height<CanopyActivationHeight+ZIP212GracePeriod{0x02}, ⁣ ⁣ ⁣otherwise.\hspace{2em} \begin{cases} \{ \mathtt{0x01} \},&\!\!\!\textsf{if } \mathsf{height} < \mathsf{CanopyActivationHeight} \\ \{ \mathtt{0x01}, \mathtt{0x02} \},&\!\!\!\textsf{if } \mathsf{CanopyActivationHeight} \leq \mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod} \\ \{ \mathtt{0x02} \},&\!\!\!\textsf{otherwise.} \end{cases}

with

Let pool  ⦂  {SaplingPool,OrchardPool,IronwoodPool }\textit{pool} \;{\small ⦂}\; \{ \textit{SaplingPool}, \textit{OrchardPool}, \textit{IronwoodPool}\, \} be the chain value pool of the note.

Define allowedLeadBytespool(height,txVersion)=\mathsf{allowedLeadBytes}^{\textit{pool}}(\mathsf{height}, \mathsf{txVersion}) = {{0x01}, ⁣ ⁣ ⁣if height<CanopyActivationHeight{0x01,0x02}, ⁣ ⁣ ⁣if CanopyActivationHeight≤height<CanopyActivationHeight+ZIP212GracePeriod{0x02}, ⁣ ⁣ ⁣if CanopyActivationHeight+ZIP212GracePeriod≤height and pool≠IronwoodPool{0x03}, ⁣ ⁣ ⁣otherwise.\hspace{2em} \begin{cases} \{ \mathtt{0x01} \},&\!\!\!\textsf{if } \mathsf{height} < \mathsf{CanopyActivationHeight} \\ \{ \mathtt{0x01}, \mathtt{0x02} \},&\!\!\!\textsf{if } \mathsf{CanopyActivationHeight} \leq \mathsf{height} < \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod} \\ \{ \mathtt{0x02} \},&\!\!\!\textsf{if } \mathsf{CanopyActivationHeight} + \mathsf{ZIP212GracePeriod} \leq \mathsf{height} \textsf{ and } \textit{pool} \neq \textit{IronwoodPool} \\ \{ \mathtt{0x03} \},&\!\!\!\textsf{otherwise.} \end{cases}

Replace the non-normative note:

  • It is intentional that the definition of allowedLeadBytes\mathsf{allowedLeadBytes} does not currently depend on protocol\mathsf{protocol} or txVersion\mathsf{txVersion}. It might do so in future.

with

  • It is intentional that the definition of allowedLeadBytes\mathsf{allowedLeadBytes} does not currently depend on txVersion\mathsf{txVersion}. It might do so in future.

Add the non-normative note:

  • For Ironwood-pool note plaintexts, the only allowed lead byte value is 0x03\mathtt{0x03}.
§ 4.1.2 ‘Pseudo Random Functions’

In the list of places where PRFexpand\mathsf{PRF^{expand}} is used:

Replace

  • [NU5 onward] in § 4.2.3 ‘Orchard Key Components’ 19, with inputs [0x06][\mathtt{0x06}], [0x07][\mathtt{0x07}], [0x08][\mathtt{0x08}], and with first byte 0x82\mathtt{0x82};
  • in the processes of sending (§ 4.7.2 ‘Sending Notes (Sapling)’ 20 and § 4.7.3 ‘Sending Notes (Orchard)’ 21) and of receiving (§ 4.20 ‘In-band secret distribution (Sapling and Orchard)’ 22) notes, for Sapling with inputs [0x04][\mathtt{0x04}] and [0x05][\mathtt{0x05}], and for Orchard [t]∣∣ρ‾[t] || \underline{\text{ρ}} with t∈{0x05,0x04,0x09}t \in \{ \mathtt{0x05}, \mathtt{0x04}, \mathtt{0x09} \};

with

  • [NU5 onward] in § 4.2.3 ‘Orchard Key Components’ 19, with inputs [0x06][\mathtt{0x06}], [0x07][\mathtt{0x07}], [0x08][\mathtt{0x08}], and with first byte in {0x0C,0x0D,0x82}\{ \mathtt{0x0C}, \mathtt{0x0D}, \mathtt{0x82} \} (0x0C\mathtt{0x0C} and 0x0D\mathtt{0x0D} are also specified in [ZIP 2005]);
  • in the processes of sending (§ 4.7.2 ‘Sending Notes (Sapling)’ 20 and § 4.7.3 ‘Sending Notes (Orchard)’ 21) and of receiving (§ 4.20 ‘In-band secret distribution (Sapling and Orchard)’ 22) notes, for Sapling with inputs [0x04][\mathtt{0x04}] and [0x05][\mathtt{0x05}], and for Orchard with first byte in {0x05,0x04,0x09,0x0A,0x0B}\{ \mathtt{0x05}, \mathtt{0x04}, \mathtt{0x09}, \mathtt{0x0A}, \mathtt{0x0B} \} (0x0A\mathtt{0x0A} and 0x0B\mathtt{0x0B} are also specified in [ZIP 2005]);

Add

  • in [ZIP 2005], with first byte in {0x0A,0x0B,0x0C,0x0D}\{ \mathtt{0x0A}, \mathtt{0x0B}, \mathtt{0x0C}, \mathtt{0x0D} \}.
§ 4.2.3 ‘Orchard Key Components’

Add ℓqsk\ell_{\mathsf{qsk}} and ℓqk\ell_{\mathsf{qk}} to the constants obtained from § 5.3 ‘Constants’ 23.

Replace from "From this spending key" up to and including the line "let ak=ExtractP(akP)\mathsf{ak} = \mathsf{Extract}_{\mathbb{P}}(\mathsf{ak}^{\mathbb{P}})" in the algorithm with:

Under normal circumstances, the Spend authorizing key ask  ⦂  FrP∗\mathsf{ask} \;{\small ⦂}\; \mathbb{F}^{*}_{r_{\mathbb{P}}} is derived directly from sk\mathsf{sk}. However, this might not be the case for protocols that require distributed generation of shares of ask\mathsf{ask}, such as FROST's Distributed Key Generation 24 (see [ZIP 2005, Usage with Frost] for further discussion). To support this we define an alternative derivation method using an additional "quantum spending key", qsk\mathsf{qsk}, and "quantum intermediate key", qk\mathsf{qk}.

There can also be advantages to not deriving ask\mathsf{ask} directly from sk\mathsf{sk} for hardware wallets, in order to separate the authority to make proofs for the Recovery Protocol from the spend authorization key that is kept on the device (see [ZIP 2005, Usage with hardware wallets]). The derivation from qsk\mathsf{qsk} can also be used in that case.

Let use_qsk  ⦂  B\mathsf{use\_qsk} \;{\small ⦂}\; \mathbb{B} be a flag indicating whether qsk\mathsf{qsk} and qk\mathsf{qk} are generated and used in the derivation of rivk\mathsf{rivk}. (In cases where it is desired for the generation of key components to match versions of this specification prior to 2026.8.0, use_qsk\mathsf{use\_qsk} needs to be set to false.)

Define:

  • Hask(sk)=ToScalarOrchard(PRFskexpand([0x06]))\mathsf{H^{ask}}(\mathsf{sk}) = \mathsf{ToScalar^{Orchard}}\big(\mathsf{PRF^{expand}_{sk}}([\mathtt{0x06}])\kern-0.1em\big)
  • Hnk(sk)=ToBaseOrchard(PRFskexpand([0x07]))\mathsf{H^{nk}}(\mathsf{sk}) = \mathsf{ToBase^{Orchard}}\big(\mathsf{PRF^{expand}_{sk}}([\mathtt{0x07}])\kern-0.1em\big)
  • Hrivk(sk)=ToScalarOrchard(PRFskexpand([0x08]))\mathsf{H^{rivk}}(\mathsf{sk}) = \mathsf{ToScalar^{Orchard}}\big(\mathsf{PRF^{expand}_{sk}}([\mathtt{0x08}])\kern-0.1em\big)
  • Hqsk(sk)=truncate32(PRFskexpand([0x0C]))\mathsf{H^{qsk}}(\mathsf{sk}) = \mathsf{truncate}_{32}\big(\mathsf{PRF^{expand}_{sk}}([\mathtt{0x0C}])\kern-0.1em\big)
  • Hqk(qsk)=BLAKE3.derive_key(“Zcash ZIP 2005 qk-derivation v1”,qsk,32)\mathsf{H^{qk}}(\mathsf{qsk}) = \mathsf{BLAKE3.derive\_key}(\texttt{“Zcash ZIP 2005 qk-derivation v1”}, \mathsf{qsk}, 32) 25.
  • Hqkrivk_ext(ak,nk)=ToScalarOrchard(PRFqkexpand([0x0D] ∣∣ I2LEOSP256(ak) ∣∣ I2LEOSP256(nk)))\mathsf{H}^{\mathsf{rivk\_ext}}_{\mathsf{qk}}(\mathsf{ak}, \mathsf{nk}) = \mathsf{ToScalar^{Orchard}}\big(\mathsf{PRF^{expand}_{qk}}\big([\mathtt{0x0D}] \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP}_{256}(\mathsf{nk})\kern-0.1em\big)\kern-0.15em\big).

ask  ⦂  FrP∗\mathsf{ask} \;{\small ⦂}\; \mathbb{F}^{*}_{r_{\mathbb{P}}}, the Spend validating key ak  ⦂  {1 .. qP−1}\mathsf{ak} \;{\small ⦂}\; \{ 1\,..\,q_{\mathbb{P}}-1 \}, the nullifier deriving key nk  ⦂  FqP\mathsf{nk} \;{\small ⦂}\; \mathbb{F}_{q_{\mathbb{P}}}, the optional quantum spending key qsk  ⦂  BY[ℓqsk/8]∪{⊥}\mathsf{qsk} \;{\small ⦂}\; \mathbb{B}^{{\kern-0.1em\tiny\mathbb{Y}}[\ell_{\mathsf{qsk}}/8]} \cup \{\bot\} and quantum intermediate key qk  ⦂  BY[ℓqk/8]∪{⊥}\mathsf{qk} \;{\small ⦂}\; \mathbb{B}^{{\kern-0.1em\tiny\mathbb{Y}}[\ell_{\mathsf{qk}}/8]} \cup \{\bot\} the Commitivk\mathsf{Commit^{ivk}} randomness rivk  ⦂  FrP\mathsf{rivk} \;{\small ⦂}\; \mathbb{F}_{r_{\mathbb{P}}}, the diversifier key dk  ⦂  BY[ℓdk/8]\mathsf{dk} \;{\small ⦂}\; \mathbb{B}^{{\kern-0.1em\tiny\mathbb{Y}}[\ell_{\mathsf{dk}}/8]}, the KAOrchard\mathsf{KA^{Orchard}} private key ivk  ⦂  {1 .. qP−1}\mathsf{ivk} \;{\small ⦂}\; \{ 1\,..\,q_{\mathbb{P}}-1 \}, the outgoing viewing key ovk  ⦂  BY[ℓovk/8]\mathsf{ovk} \;{\small ⦂}\; \mathbb{B}^{{\kern-0.1em\tiny\mathbb{Y}}[\ell_{\mathsf{ovk}}/8]}, and corresponding “internal” keys MUST be derived as follows:

\hspace{1.0em} let nk=Hnk(sk)\mathsf{nk} = \mathsf{H^{nk}}(\mathsf{sk})
\hspace{1.0em} if use_qsk\mathsf{use\_qsk}:
\hspace{2.5em} obtain a SpendAuthSigOrchard\mathsf{SpendAuthSig^{Orchard}} public key akP  ⦂  P∗\mathsf{ak}^{\mathbb{P}} \;{\small ⦂}\; \mathbb{P}^* by any suitably secure
\hspace{3.5em} method that ensures the last bit of reprP(akP)\mathsf{repr}_{\mathbb{P}}(\mathsf{ak}^{\mathbb{P}}) is 00 (see below).
\hspace{2.5em} let ak=ExtractP(akP)\mathsf{ak} = \mathsf{Extract}_{\mathbb{P}}(\mathsf{ak}^{\mathbb{P}})
\hspace{2.5em} let qsk=Hqsk(sk)\mathsf{qsk} = \mathsf{H^{qsk}}(\mathsf{sk})
\hspace{2.5em} let qk=Hqk(qsk)\mathsf{qk} = \mathsf{H^{qk}}(\mathsf{qsk})
\hspace{2.5em} let rivk=Hqkrivk_ext(ak,nk)\mathsf{rivk} = \mathsf{H}^{\mathsf{rivk\_ext}}_{\mathsf{qk}}(\mathsf{ak}, \mathsf{nk})
\hspace{1.0em} else:
\hspace{2.5em} let mutable ask←Hask(sk)\mathsf{ask} \leftarrow \mathsf{H^{ask}}(\mathsf{sk})
\hspace{2.5em} let akP=SpendAuthSigOrchard.DerivePublic(ask)\mathsf{ak}_{\mathbb{P}} = \mathsf{SpendAuthSig^{Orchard}.DerivePublic}(\mathsf{ask})
\hspace{2.5em} if the last bit (that is, the y~\tilde{y} bit) of reprP(akP)\mathsf{repr}_{\mathbb{P}}(\mathsf{ak}_{\mathbb{P}}) is 11:
\hspace{4.0em} set ask←−ask\mathsf{ask} \leftarrow -\mathsf{ask}

\hspace{2.5em} let ak=ExtractP(akP)\mathsf{ak} = \mathsf{Extract}_{\mathbb{P}}(\mathsf{ak}_{\mathbb{P}})
\hspace{2.5em} let qsk=qk=⊥\mathsf{qsk} = \mathsf{qk} = \bot (there are no quantum spending/intermediate keys in this case)
\hspace{2.5em} let rivk=Hrivk(sk)\mathsf{rivk} = \mathsf{H^{rivk}}(\mathsf{sk})

Add before "As explained in § 3.1":

When use_qsk\mathsf{use\_qsk} is true, possible methods of generating akP\mathsf{ak}^{\mathbb{P}} include direct generation of an Orchard-protocol Spend authorizing key ask  ⦂  FrP∗\mathsf{ask} \;{\small ⦂}\; \mathbb{F}^{*}_{r_{\mathbb{P}}} followed by akP=SpendAuthSigOrchard.DerivePublic(ask)\mathsf{ak}^{\mathbb{P}} = \mathsf{SpendAuthSig^{Orchard}.DerivePublic}(\mathsf{ask}), or FROST distributed key generation 24 in which the corresponding spend-authorization material is tt-of-nn shared among the participants.

Add the following notes:

  • If ask\mathsf{ask}, ak\mathsf{ak}, nk\mathsf{nk}, rivk\mathsf{rivk}, and rivk_internal\mathsf{rivk\_internal} are not generated as specified in this section, then it may not be possible to recover the resulting notes as specified in [ZIP 2005] in the event that attacks using quantum computers become practical. In addition, to recover notes it is necessary to retain, or be able to rederive sk\mathsf{sk}, and also to know whether use_qsk\mathsf{use\_qsk} was used to derive the ivk\mathsf{ivk} and addresses. When FROST is being used, it is also necessary to retain the group verifying key ak\mathsf{ak} and (collectively among the signers) the key material needed to make spend authorization signatures that can be verified using ak\mathsf{ak}.

    See [ZIP 2005, Key storage options and analysis] for further discussion of storage requirements for sk\mathsf{sk} and qsk\mathsf{qsk}.

§ 4.7.2 ‘Sending Notes (Sapling)’

Add after the definition of leadByte\mathsf{leadByte}:

Citation graph

Hover or tap a node to see its title and citations.
Loading citation graph…