Merge pull request #11 from zcash/new-nullifier-design

book: New nullifier design
This commit is contained in:
str4d 2021-01-09 13:57:16 +13:00 committed by GitHub
commit f3a51fa6f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 43 additions and 48 deletions

View File

@ -2,28 +2,34 @@
The nullifier design we use for Orchard is
$$\mathsf{nf} = [Hash_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm},$$
$$\mathsf{nf} = [Hash_{\mathsf{nk}}(\psi)] H + [\mathsf{rnf}] \mathcal{I},$$
where:
- $Hash$ is a keyed circuit-efficient hash (such as Rescue).
- $\rho$ is unique to this output. As with $\mathsf{h_{Sig}}$ in Sprout, $\rho$ includes
the nullifiers of any Orchard notes being spent.
- If spends and outputs are merged / combined, then we always have a nullifier
(internally derived from a real or dummy note), and can rely on the nullifier
derivation process to prevent an adversary from choosing dummy nullifiers arbitrarily.
- If spends and outputs are *not* merged, then $\rho$ should probably also include
unique information from other parts of the transaction as well.
- TODO: Decide which of the above two cases will be used, and update this.
- $GH$ is a cryptographic hash into the group (such as BLAKE2s with simplified SWU).
- $\mathcal{I}$ is a fixed base, independent of any others returned by $GH$.
- $H$ is a base unique to this output.
- For non-zero-valued notes, $H = GH(\rho)$. As with $\mathsf{h_{Sig}}$ in Sprout,
$\rho$ includes the nullifiers of any Orchard notes being spent in the same action.
Given that an action consists of a single spend and a single output, we set $\rho$ to
be the nullifier of the spent note.
- For zero-valued notes, $H$ is constrained by the circuit to a fixed base independent
of $\mathcal{I}$ and any others returned by $GH$.
- $\psi$ is sender-controlled randomness. It is not required to be unique, and in practice
is derived from a sender-selected random value $\mathsf{rseed}$.
- $\mathcal{G}$ is an fixed independent base.
is derived from both $\rho$ and a sender-selected random value $\mathsf{rseed}$:
$\psi = KDF^\psi(\rho, \mathsf{rseed})$.
- $\mathsf{rnf}$ is a blinding scalar, similarly generated as
$\mathsf{rnf} = KDF^\mathsf{rnf}(\rho, \mathsf{rseed})$.
This gives a note structure of
$$(addr, v, \rho, \psi, \mathsf{rcm}).$$
$$(addr, v, H, \psi, \mathsf{rnf}, \mathsf{rcm}).$$
The nullifier commits to the note value via $\mathsf{cm}$ in order to domain-separate
nullifiers for zero-valued notes from other notes.
The note plaintext includes $\mathsf{rseed}$ in place of $\psi$, $\mathsf{rnf}$, and
$\mathsf{rcm}$. $H$ is omitted entirely from the action:
- Consensus nodes directly derive $GH(\rho)$ and provide it as a public input to the
circuit (which ignores it for zero-valued notes, as with the commitment tree anchor).
- The recipient can recompute the correct $H$ given their additional knowledge of $v$.
## Security properties
@ -48,11 +54,12 @@ We care about several security properties for our nullifiers:
- **Faerie Resistance:** can I perform a Faerie Gold attack (i.e. cause notes to be
accepted that are unspendable)?
- We're giving the full viewing key to the attacker and allowing it to be the sender in
order to make this property as strong as possible: they will have *all* the notes sent
to that address, and be able to derive *every* nullifier.
We assume (and instantiate elsewhere) the following primitives:
- $GH$ is a cryptographic hash into the group (such as BLAKE2s with simplified SWU), used
to derive all fixed independent bases.
- $E$ is an elliptic curve (such as Pallas).
- $KDF$ is the note encryption key derivation function.
@ -62,9 +69,9 @@ $$
\begin{array}{|l|l|}
\text{Balance} & DL_E \\
\text{Note Privacy} & HashDH^{KDF}_E \\
\text{Note Privacy (OOB)} & \text{Near perfect} \ddagger \\
\text{Note Privacy (OOB)} & \text{Perfect} \\
\text{Spend Unlinkability} & DDH_E^\dagger \vee PRF_{Hash} \\
\text{Faerie Resistance} & DL_E \\
\text{Faerie Resistance} & (RO_{GH} \vee (Coll_{GH} \wedge RO_{Hash})) \wedge DL_E \\
\end{array}
$$
@ -72,15 +79,9 @@ $HashDH^{F}_E$ is computational Diffie-Hellman using $F$ for the key derivation,
one-time ephemeral keys. This assumption is heuristically weaker than $DDH_E$ but stronger
than $DL_E$.
We omit $RO_{GH}$ as a security assumption because we only rely on the random oracle
applied to fixed inputs defined by the protocol, i.e. to generate the fixed base
$\mathcal{G}$, not to attacker-specified inputs.
> $\dagger$ We additionally assume that for any input $x$, $\{Hash_{\mathsf{nk}}(x) :
> \mathsf{nk} \in E\}$ gives a scalar in an adequate range for $DDH_E$. (Otherwise, $Hash$
> could be trivial, e.g. independent of $\mathsf{nk}$.)
>
> $\ddagger$ Statistical distance $< 2^{-167.8}$ from perfect.
> $\dagger$ We additionally assume that for any input $x$,
> $\{Hash_{\mathsf{nk}}(x) : \mathsf{nk} \in E\}$ gives a scalar in an adequate range for
> $DDH_E$. (Otherwise, $Hash$ could be trivial, e.g. independent of $\mathsf{nk}$.)
## Considered alternatives
@ -89,35 +90,29 @@ problem(s) each security property depends on. They may not be accurate and are d
not fully rigorous.
$$
\begin{array}{|c|l|c|c|c|c|}
\begin{array}{|c|l|c|c|c|c|c|}
\hline
\mathsf{nf} & Note & \text{Balance} & \text{Note Privacy} & \text{Note Privacy (OOB)} & \text{Spend Unlinkability} & \text{Faerie Resistance} \\\hline
[\mathsf{nk}] [\theta] H & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E & RO_{GH} \wedge DL_E \\\hline
[\mathsf{nk}] H + [\mathsf{rnf}] \mathcal{I} & (addr, v, H, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E & RO_{GH} \wedge DL_E \\\hline
Hash([\mathsf{nk}] [\theta] H) & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{Hash} & Coll_{Hash} \wedge RO_{GH} \wedge DL_E \\\hline
Hash([\mathsf{nk}] H + [\mathsf{rnf}] \mathcal{I}) & (addr, v, H, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{Hash} & Coll_{Hash} \wedge RO_{GH} \wedge DL_E \\\hline
[Hash_{\mathsf{nk}}(\psi)] [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & RO_{GH} \wedge DL_E \\\hline
[Hash_{\mathsf{nk}}(\psi)] H + [\mathsf{rnf}] \mathcal{I} & (addr, v, H, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & RO_{GH} \wedge DL_E \\\hline
\mathsf{nf} & Note & \text{Balance} & \text{Note Privacy} & \text{Note Privacy (OOB)} & \text{Spend Unlinkability} & \text{Faerie Resistance} & \text{Rejected because} \\\hline
[\mathsf{nk}] [\theta] H & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E & RO_{GH} \wedge DL_E & \text{No SU for DL-breaking} \\\hline
[\mathsf{nk}] H + [\mathsf{rnf}] \mathcal{I} & (addr, v, H, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E & RO_{GH} \wedge DL_E & \text{No SU for DL-breaking} \\\hline
Hash([\mathsf{nk}] [\theta] H) & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{Hash} & Coll_{Hash} \wedge RO_{GH} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
Hash([\mathsf{nk}] H + [\mathsf{rnf}] \mathcal{I}) & (addr, v, H, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{Hash} & Coll_{Hash} \wedge RO_{GH} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
[Hash_{\mathsf{nk}}(\psi)] [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & RO_{GH} \wedge DL_E & 2 \text{ variable-base scalar mults} \\\hline
[Hash_{\mathsf{nk}}(\psi)] \mathcal{G} + [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & RO_{GH} \wedge DL_E \\\hline
[Hash_{\mathsf{nk}}(\psi)] H + \mathsf{cm} & (addr, v, H, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + Commit^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + Commit^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + [\mathsf{rnf}] \mathcal{I} + \mathsf{cm} & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + [\mathsf{rnf}] \mathcal{I} + \mathsf{cm} & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & DL_E \\\hline
[Hash_{\mathsf{nk}}(\psi)] H + \mathsf{cm} & (addr, v, H, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & (RO_{GH} \vee (Coll_{GH} \wedge RO_{Hash})) \wedge DL_E & PRF_{Hash} \text{ for NP(OOB)} \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & PRF_{Hash} \text{ for NP(OOB)} \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & PRF_{Hash} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & PRF_{Hash} \text{ for NP(OOB)} \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + Commit^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + Commit^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
[Hash_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + [\mathsf{rnf}] \mathcal{I} + \mathsf{cm} & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
[Hash_{\mathsf{nk}}(\rho)] \mathcal{G} + [\mathsf{rnf}] \mathcal{I} + \mathsf{cm} & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_{Hash} & Coll_{Hash} \wedge DL_E & Coll_{Hash} \text{ for FR} \\\hline
\end{array}
$$
In the above alternatives:
- $H$ is calculated by the sender as $H = GH(\rho)$, and would be provided in the action.
- $\mathcal{I}$ is an fixed independent base, independent of $\mathcal{G}$ and any others
- $\mathcal{G}$ is an fixed independent base, independent of $\mathcal{I}$ and any others
returned by $GH$.
For the options that use $H$, when spending a note,
- if it's a real note, then $H$ is as computed for that note, so it is a unique RO output;
- if it's a dummy note, we enforce that it is some fixed base independent of other bases.
The $Commit^{\mathsf{nf}}$ variants enabled nullifier domain separation based on note
value, without directly depending on $\mathsf{cm}$ (which in its native type is a base
field element, not a group element). We decided instead to follow Sapling by defining an