Skip to content

ZIP 2005: flesh out security arguments and instantiate H^{qk} as BLAKE3#1264

Merged
nuttycom merged 10 commits into
zcash:mainfrom
daira:zip-2005-security-argument
May 12, 2026
Merged

ZIP 2005: flesh out security arguments and instantiate H^{qk} as BLAKE3#1264
nuttycom merged 10 commits into
zcash:mainfrom
daira:zip-2005-security-argument

Conversation

@daira
Copy link
Copy Markdown
Collaborator

@daira daira commented May 5, 2026

Security arguments

Flesh out and tighten the informal-to-formal security arguments in the Rationale section:

  • Repair the informal binding-of-ivk argument and remove duplication.
  • Rewrite the informal Spendability argument as a classical-ROM reduction with an explicit theorem and proof sketch.
  • Tighten the key-binding argument:
    • Lift use_qsk and is_internal_rivk into the $\bot$-structure of the witness. This ensures that cross-branch attacks automatically fall into scope.
    • Restructure the proof sketch around a "final random oracle" formulation. WLOG-distinctness is argued per case from predicate determinism rather than from a vague witness-distinctness claim.
    • Correct the bound to $\frac{3 q_{\mathsf{kb}}(q_{\mathsf{kb}} - 1)}{2 r_{\mathbb{P}}}$ to account for the upstream-RO collision residual in the both-internal sub-case (which the previous $\frac{q_{\mathsf{kb}}(q_{\mathsf{kb}} - 1)}{r_{\mathbb{P}}}$ bound missed). Propagate the corrected constant to the Spendability theorem's combined bound.
    • Make explicit that the $y$-sign of $\mathsf{ak}^{\mathbb{P}}$ is intentionally not part of the binding equivalence class — consistent with Orchard's intentional design decision to use $\mathsf{ak}$ as a single $\mathbb{F}_ {q_{\mathbb{P}}}$ element.
  • Update the high-level summary's binding-argument paragraph to describe both branches symmetrically, matching the formal statement.
  • Harmonize the Spendability proof's structure with the key-binding proof: RO model used directly without an explicit lazy-sampling table.

$\mathsf{H}^{\mathsf{qk}}$ instantiation

Switch $\mathsf{H}^{\mathsf{qk}}$ from BLAKE2s-256 to BLAKE3.derive_key with context string "Zcash ZIP 2005 qk-derivation v1" and 32-byte output. Requires one BLAKE3 compression in the $\mathsf{SoK}^{\mathsf{qsk}}$ circuit, with the derive_key context key precomputed as a constant.

Notational consistency

  • Establish a convention to omit $\mathsf{Orchard}$ superscripts in Terminology.
  • Adopt the convention that function names use \mathsf and output values are math-italic.
  • Italic subsection labels in the Spendability proof (Algebraic setup / Independence claim per pair / Bounding the win probability), as in the key-binding proof. Also use the $F_i := \mathsf{F}(\mathsf{notetuple}_i)$ shorthand.

🤖 Filed with Claude Code

daira and others added 9 commits May 6, 2026 02:44
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Terminology entry stating that in this ZIP's discussion sections we
abbreviate H^{rcm,Orchard} as H^{rcm} (and similarly for other Orchard-
specific hash function names). Spec changes and references to other ZIPs
use the full forms.

Drop the now-redundant local abbreviation sentence at the start of the
Cost section, since the convention is established globally in Terminology.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eduction.

The previous argument enumerated specific attack classes (a per-input
bullet list of "this input goes through this hash") and incorrectly
modelled f and g — the Sinsemilla-base lift and the K^Orchard-linear g
— as random oracles. f and g are deterministic functions of their inputs.

Replace with a reduction-based argument: any classical adversary that
finds two valid Recovery Statement witnesses for distinct underlying
notes with colliding nullifiers succeeds with probability bounded by
q(q-1)/r_P (≤ 2^-94 for Pallas with q ≤ 2^80). The reduction simulates
H^{rcm} as a lazily-sampled random oracle, extracts the algebraic
identity H_1 + f_1 + g_1 ≡ ±(H_2 + f_2 + g_2) (mod r_P), and bounds the
probability that two independent uniform RO outputs satisfy a fixed
linear constraint.

The argument does not assume Commit^{ivk}-binding (which would not hold
against a discrete-log-breaking adversary on Pallas) or collision-
resistance of the key-derivation hashes; it uses only H^{rcm}-as-RO plus
the structural fact that f and g are deterministic.

Also: replace "pq-collision-resistant" with "collapsing" in the
rehashed-commitment-tree discussion — the precise post-quantum binding
notion per Unruh 2016.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
…ture; Spendability-proof refinements.

**Make the key-binding argument rigorous** (to support the ε_kb term in
the Spendability proof): hoist the binding-break definition, ε_kb
advantage, and a formal theorem statement into a Security argument for
key binding section, with a proof sketch that mirrors the Spendability
reduction structurally.

**Lift flags out of the Recovery Statement and key-binding witness.**
The use_qsk and is_internal_rivk flag information is now encoded in
the witness's null structure: (sk = ⊥) ≠ (qk = ⊥) replaces the use_qsk
flag, and rivk ∈ {rivk_ext, H^{rivk_int}_{rivk_ext}(ak, nk)} replaces
the is_internal_rivk flag. The witness-structure form is strictly
stronger than flag-based: cross-branch attacks (e.g., w_1 with qk ≠ ⊥
and w_2 with sk ≠ ⊥, both opening the same ivk) are now in scope.
Co-nullable witness components are grouped as tuples — (qk, σ_qsk) is
a single (T_1 × T_2) ∪ {(⊥, ⊥)} field rather than two independently-
nullable fields with a separate consistency constraint.

**Fix a pre-existing bug:** rk = SpendAuthSig.RandomizePublic(α, ak^P)
was conditioned on use_qsk = true in the original Recovery Statement;
it should hold unconditionally.

**Spendability-proof tightening:**

* Split the pinning lemma into ivk-pinning (unconditional, per-witness,
  via discrete-log on prime-order Pallas) and PRF^{nf}-pinning (pair-
  conditional, via key-binding break absence).
* Make F's partiality explicit: F is defined under the no-key-binding-
  break conditioning, with (rseed, ρ, ψ) as fields of notetuple and
  PRF^{nf}_{nk}(ρ) pinned via the PRF^{nf}-pinning lemma.
* Handle the F_i = 0 (identity) case via § 5.4.9.7 convention
  Extract_P(O) = 0, citing the new protocol-concreteextractorpallas
  reference.
* Justify K_R being well-defined and nonzero.
* State the non-querying constraint where it does work: deterministic
  shifts in F are independent of H^{rcm} oracle responses.
* Add a tightness paragraph citing Maurer's classical-RO collision
  bound k(k-1)/(2N), with the factor-of-2 derivation for the
  ±-equivalence in our win condition.
* Drop "or extracts from internal state" from the ε_{kb} definition.
* Rename ε_{Commit^{ivk}}(A) to ε_{kb}(A, q_{kb}) — parameterized by
  query count, scoped to "key-binding" rather than just Commit^{ivk}.
* Add the substituted concrete bound: by the key-binding theorem,
  ε_{kb}(A, q_{kb}) ≤ q_{kb}(q_{kb}-1)/r_P, so the overall Spendability
  bound is at most (q_{rcm}(q_{rcm}-1) + q_{kb}(q_{kb}-1))/r_P.

**Notation cleanup:**

* F → \mathsf{F} (function names sans-serif; F_1, F_2 stay italic as
  values).
* q → q_{rcm} / q_{kb} (subscripted by which RO is being counted).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Daira-Emma Hopwood <daira@jacaranda.org>
Restructure the key-binding theorem's proof sketch around a "final
random oracle" formulation, absorbing the previous internal-IVK case
into the others; tighten each case's WLOG step to derive distinctness
from predicate determinism rather than from a vague witness-distinctness
claim. Correct the bound to 3 q_kb(q_kb-1)/(2 r_P) to account for the
upstream-RO collision residual in the both-internal sub-case, which the
previous bound q_kb(q_kb-1)/r_P missed; propagate the corrected constant
to the Spendability theorem's combined bound.

Update G notation (function mathsf, output values italic) to match
the F convention.

Update the high-level summary's binding-argument paragraph to describe
both branches symmetrically, matching the lifted formal statement.

Define the break event at the projection level (distinct
(qk, sk, ak, nk, rivk)), making explicit that the y-sign of ak^P is
intentionally not part of the binding equivalence class — consistent
with Orchard's existing design choice to use ak as a single
F_{q_P} element.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Use BLAKE3.derive_key with context string "Zcash ZIP 2005 qk-derivation v1"
and 32-byte output. Requires one BLAKE3 compression in the SoK^{qsk}
circuit, with the derive_key context key precomputed as a constant.

Add a BLAKE3 reference.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@daira daira force-pushed the zip-2005-security-argument branch from 95f5014 to ce4b2da Compare May 6, 2026 01:44
Apply the conciseness improvements that landed in the key-binding
proof: italic subsection labels (Algebraic setup / Independence claim
per pair / Bounding the win probability), F_i := F(notetuple_i)
shorthand for output values, RO model used directly without an
explicit lazy-sampling table, single union-bound paragraph instead
of three.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@ValarDragon ValarDragon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update LGTM.

Summarizing:

H^{qk} is now Blake3 - perfectly fine. We want to use the most small-field friendly, field-agnostic, quantum safe hash. Blake3 seems like clearly the best choice.

Witness derivation for recovery is cleaned up, with some bug fixes.

Fixes a missing collision term in key-binding soundness claim. TL:DR in my understanding. We ignore y-coordinate, so standard birthday bound would be: choose(q_kb, 2) * 2/r_P. However, we also have a chance for an upstream collision elsewhere as well. (e.g. H^rivk_ext(qk, ak, nk) = H^rivk_legacy(sk)) That adds another target per choice of q_sk, and therefore another 1/R_p chance of bad thing.

So we update our bound to be choose(q_kb, 2) * 3/r_P. And then thread through accordingly.

Copy link
Copy Markdown
Collaborator

@ValarDragon ValarDragon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, per above comment

Copy link
Copy Markdown
Contributor

@nuttycom nuttycom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cursory ACK; I did not review the security proof

@nuttycom nuttycom merged commit 4f3e784 into zcash:main May 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants