From 0abc0ef11a0e5e94f4eaa0b17210a684d8249107 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 14:06:03 +0000 Subject: [PATCH 1/6] book: Revert to the previous nullifier design We examined the nullifier designs more closely, and determined that the previously-selected design was actually fine, but for a somewhat-subtle reason: even though an adversary with knowledge of a victim's full viewing key could choose psi to cancel out Hash_nk(rho), the nullifier still directly depends on rho via the note commitment. --- book/src/design/nullifiers.md | 83 +++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index 7471187c..20e3cb13 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -2,34 +2,25 @@ The nullifier design we use for Orchard is -$$\mathsf{nf} = [Hash_{\mathsf{nk}}(\psi)] H + [\mathsf{rnf}] \mathcal{I},$$ +$$\mathsf{nf} = [F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm},$$ where: -- $Hash$ is a keyed circuit-efficient hash (such as Rescue). -- $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$. +- $F$ is a keyed circuit-efficient PRF (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 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. - $\psi$ is sender-controlled randomness. It is not required to be unique, and in practice 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})$. + $$\psi = KDF^\psi(\rho, \mathsf{rseed}).$$ +- $\mathcal{G}$ is a fixed independent base. This gives a note structure of -$$(addr, v, H, \psi, \mathsf{rnf}, \mathsf{rcm}).$$ +$$(addr, v, \rho, \psi, \mathsf{rcm}).$$ -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$. +The note plaintext includes $\mathsf{rseed}$ in place of $\psi$ and $\mathsf{rcm}$, and +omits $\rho$ (which is a public part of the action). ## Security properties @@ -60,6 +51,8 @@ We care about several security properties for our nullifiers: 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. @@ -69,19 +62,25 @@ $$ \begin{array}{|l|l|} \text{Balance} & DL_E \\ \text{Note Privacy} & HashDH^{KDF}_E \\ -\text{Note Privacy (OOB)} & \text{Perfect} \\ -\text{Spend Unlinkability} & DDH_E^\dagger \vee PRF_{Hash} \\ -\text{Faerie Resistance} & (RO_{GH} \vee (Coll_{GH} \wedge RO_{Hash})) \wedge DL_E \\ +\text{Note Privacy (OOB)} & \text{Near perfect} \ddagger \\ +\text{Spend Unlinkability} & DDH_E^\dagger \vee PRF_F \\ +\text{Faerie Resistance} & DL_E \\ \end{array} $$ -$HashDH^{F}_E$ is computational Diffie-Hellman using $F$ for the key derivation, with +$HashDH^{KDF}_E$ is computational Diffie-Hellman using $KDF$ for the key derivation, with 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}$.) +> $\{F_{\mathsf{nk}}(x) : \mathsf{nk} \in E\}$ gives a scalar in an adequate range for +> $DDH_E$. (Otherwise, $F$ could be trivial, e.g. independent of $\mathsf{nk}$.) +> +> $\ddagger$ Statistical distance $< 2^{-167.8}$ from perfect. ## Considered alternatives @@ -92,26 +91,36 @@ not fully rigorous. $$ \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} & \text{Rejected because} \\\hline +\mathsf{nf} & Note & \text{Balance} & \text{Note Privacy} & \text{Note Privacy (OOB)} & \text{Spend Unlinkability} & \text{Faerie Resistance} & \text{Reason not to use} \\\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} & (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 +[F_{\mathsf{nk}}(\psi)] [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{Performance (2 variable-base)} \\\hline +[F_{\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_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline +[F_{\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_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline +[F_{\mathsf{nk}}(\psi)] H + \mathsf{cm} & (addr, v, H, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline +[F_{\mathsf{nk}}(\rho)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline +[F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G_v} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Near perfect} \ddagger & DDH_E^\dagger \vee PRF_F & \color{red}{\text{broken}} & \text{broken for FR} \\\hline +[F_{\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_F & DL_E & \text{Performance (2 fixed-base)} \\\hline +[F_{\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_F & DL_E & \text{Performance (2 fixed-base)} \\\hline \end{array} $$ In the above alternatives: -- $\mathcal{G}$ is an fixed independent base, independent of $\mathcal{I}$ and any others +- $Hash$ is a keyed circuit-efficient hash (such as Rescue). +- $\mathcal{I}$ is an fixed independent base, independent of $\mathcal{G}$ and any others returned by $GH$. +- $\mathcal{G_v}$ is a pair of fixed independent bases (independent of all others), where + the specific choice of base depends on whether the note has zero value. +- $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. + - For zero-valued notes, $H$ is constrained by the circuit to a fixed base independent + of $\mathcal{I}$ and any others returned by $GH$. 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 From f3a36457d7647e6615fd8f854ec4580d496ae187 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 20 Jan 2021 14:11:24 +0000 Subject: [PATCH 2/6] book: Add rationale for nullifier design --- book/src/design.md | 1 - book/src/design/nullifiers.md | 105 ++++++++++++++++++++++++++++++++-- 2 files changed, 100 insertions(+), 6 deletions(-) diff --git a/book/src/design.md b/book/src/design.md index 1c927c26..de393ccf 100644 --- a/book/src/design.md +++ b/book/src/design.md @@ -29,7 +29,6 @@ Group hashing uses the isogeny. - nsk goes away; `nk` is now a field element - TODO: ak / nk split enables splitting the security argument, but could consider merging. Merging would help with ivk derivation perf (though as a commitment now it's pretty cheap) -- TODO: nullifier computation ZIP 32 integration - Use same Sapling design? diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index 20e3cb13..dac6db35 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -122,8 +122,103 @@ In the above alternatives: - For zero-valued notes, $H$ is constrained by the circuit to a fixed base independent of $\mathcal{I}$ and any others returned by $GH$. -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 -intermediate representation of $\mathsf{cm}$ as a group element, that is only used in -nullifier computation. +## Rationale + +In order to satisfy the **Balance** security property, we require that the circuit must be +able to enforce that only one nullifier is accepted for a given note. As in Sprout and +Sapling, we achieve this by ensuring that the nullifier deterministically depends only on +values committed to (directly or indirectly) by the note commitment. + +### Use of $\rho$ + +**Faerie Resistance** requires that nullifiers be unique. This is primarily achieved by +taking a unique value (checked for uniqueness by the public consensus rules) as an input +to the nullifier. However, it is also necessary to ensure that the transformations applied +to this value preserve its uniqueness. Meanwhile, to achieve **Spend Unlinkability**, we +require that the nullifier does not reveal any information about the unique value it is +derived from. + +The design alternatives fall into two categories in terms of how they balance these +requirements: + +- Publish a unique value $\rho$ at note creation time, and blind that value within the + nullifier computation. + - This is similar to the approach taken in Sprout and Sapling, which both implemented + nullifiers as PRF outputs; Sprout uses the compression function from SHA-256, while + Sapling uses BLAKE2s. +- Derive a unique base $H$ from some unique value, publish that unique base at note + creation time, and then blind the base (either additively or multiplicatively) during + nullifier computation. + +For **Spend Unlinkability**, the only value unknown to the adversary is $\mathsf{nk}$, and +the cryptographic assumptions only involve the first term (other terms like $\mathsf{cm}$ +or $[\mathsf{rnf}] \mathcal{I}$ cannot be extracted directly from the observed nullifiers, +but can be subtracted from them). We therefore ensure that the first term does not commit +directly to the note (to avoid a DL-breaking adversary from immediately breaking **SU**). + +We were considering using a design involving $H$ with the goal of eliminating all usages +of a PRF inside the circuit, for two reasons: +- Instantiating $PRF_F$ with a traditional hash function is expensive in the circuit. +- We didn't want to solely rely on an algebraic hash function satisfying $PRF_F$ to + achieve **Spend Unlinkability**. + +However, those designs rely on both $RO_{GH}$ and $DL_E$ for **Faerie Resistance**, while +still requiring $DDH_E$ for **Spend Unlinkability**. (There are two designs for which this +is not the case, but they rely on $DDH_E^\dagger$ for **Note Privacy (OOB)** which was not +acceptable). + +By contrast, several designs involving $\rho$ (including the chosen design) have weaker +assumptions for **Faerie Resistance** (only relying on $DL_E$), and **Spend Unlinkability** +does not require $PRF_F$ to hold: they can fall back on the same $DDH_E$ assumption as the +$H$ designs (along with an additional assumption about the output of $F$ which is easily +satisfied). + +### Use of $\psi$ + +Most of the designs include either a multiplicative blinding term $[\theta] H$, or an +additive blinding term $[\mathsf{rnf}] \mathcal{I}$, in order to achieve perfect +**Note Privacy (OOB)** (to an adversary who does not know the note). The chosen design is +effectively using $[\psi] \mathcal{G}$ for this purpose; a DL-breaking adversary only +learns $F_{\mathsf{nk}}(\rho) + \psi \pmod{p}$. This reduces **Note Privacy (OOB)** from +perfect to statistical, but given that $\psi$ is from a distribution statistically close +to uniform on $[0, q)$, this is statistically close to better than $2^{-128}$. The benefit +is that it does not require an additional scalar multiplication, making it more efficient +inside the circuit. + +$\psi$'s derivation has two motivations: +- Deriving from a random value $\mathsf{rseed}$ enables multiple derived values to be + conveyed to the recipient within an action (such as the ephemeral secret $\mathsf{esk}$, + per [ZIP 212](https://zips.z.cash/zip-0212)), while keeping the note plaintext short. +- Mixing $\rho$ into the derivation ensures that the sender can't repeat $\psi$ across two + notes, which could have enabled spend linkability attacks in some designs. + +The note that is committed to, and which the circuit takes as input, only includes $\psi$ +(i.e. the circuit does not check the derivation from $\mathsf{rseed}$). However, an +adversarial sender is still constrained by this derivation, because the recipient +recomputes $\psi$ during note decryption. If an action were created using an arbitrary +$\psi$ (for which the adversary did not have a corresponding $\mathsf{rseed}$), the +recipient would derive a note commitment that did not match the action's commitment field, +and reject it (as in Sapling). + +### Use of $\mathsf{cm}$ + +The nullifier commits to the note value via $\mathsf{cm}$ for two reasons: +- It domain-separates nullifiers for zero-valued notes from other notes. This is necessary + because we do not require zero-valued notes to exist in the commitment tree. +- Designs that bind the nullifier to $F_{\mathsf{nk}}(\rho)$ require $Coll_F$ to achieve + **Faerie Resistance** (and similarly where $Hash$ is applied to a value derived from + $H$). Adding $\mathsf{cm}$ to the nullifier avoids this assumption: all of the bases + used to derive $\mathsf{cm}$ are fixed and independent of $\mathcal{G}$, and so the + nullifier can be viewed as a Pedersen hash where the input includes $\rho$ directly. + +The $Commit^{\mathsf{nf}}$ variants were considered to avoid 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 intermediate representation of +$\mathsf{cm}$ as a group element, that is only used in nullifier computation. The circuit +already needs to compute $\mathsf{cm}$, so this improves performance by removing + +We also considered variants that used a choice of fixed bases $\mathcal{G_v}$ to provide +domain separation for zero-valued notes. The most performant design (similar to the chosen +design) does not achieve **Faerie Resistance** for an adversary that knows the recipient's +full viewing key ($\psi$ could be brute-forced to cancel out $F_{\mathsf{nk}}(\rho)$, +causing a collision), and the other variants require assuming $Coll_F$ as mentioned above. From 3ca9704d30f38b47ff81c3813ea039875f74de6c Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 21 Jan 2021 00:05:47 +0000 Subject: [PATCH 3/6] Swap ak and nk in the input to ShortCommit^{ivk}. Signed-off-by: Daira Hopwood --- book/src/design/commitments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/design/commitments.md b/book/src/design/commitments.md index cc838123..37c0771b 100644 --- a/book/src/design/commitments.md +++ b/book/src/design/commitments.md @@ -17,7 +17,7 @@ $$\mathsf{cv} = HomomorphicCommit^{\mathsf{cv}}_{\mathsf{rcv}}(v)$$ We instantiate $Commit$ and $ShortCommit$ with Sinsemilla, and use them for all other commitments: -$$\mathsf{ivk} = ShortCommit^{\mathsf{ivk}}_{\mathsf{rivk}}(\mathsf{nk}, \mathsf{ak})$$ +$$\mathsf{ivk} = \mathit{ShortCommit}^{\mathsf{ivk}}_{\mathsf{rivk}}(\mathsf{ak}, \mathsf{nk})$$ $$\mathsf{cm} = Commit^{\mathsf{cm}}_{\mathsf{rcm}}(\text{rest of note})$$ This is the same split (and rationale) as in Sapling, but using the more PLONK-efficient From db071913b641bc425687776a12b6636564328d5e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 21 Jan 2021 00:06:50 +0000 Subject: [PATCH 4/6] Explain in more detail the argument for Balance. Signed-off-by: Daira Hopwood --- book/src/design/nullifiers.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index dac6db35..7a8c837e 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -127,7 +127,17 @@ In the above alternatives: In order to satisfy the **Balance** security property, we require that the circuit must be able to enforce that only one nullifier is accepted for a given note. As in Sprout and Sapling, we achieve this by ensuring that the nullifier deterministically depends only on -values committed to (directly or indirectly) by the note commitment. +values committed to (directly or indirectly) by the note commitment. As in Sapling, +this involves arguing that: + +- There can be only one $\mathsf{ivk}$ for a given $\mathit{addr}$. This is true because + the circuit checks that $\mathsf{pk_d} = [\mathsf{ivk}] \mathsf{g_d}$, and the mapping + $\mathsf{ivk} \mapsto [\mathsf{ivk}] \mathsf{g_d}$ is an injection for any $\mathsf{g_d}$. + ($\mathsf{ivk}$ is in the base field of $E$, which must be smaller than its scalar field, + as is the case for Pallas.) +- There can be only one $\mathsf{nk}$ for a given $\mathsf{ivk}$. This is true because the + circuit checks that $\mathsf{ivk} = \mathit{ShortCommit}^{\mathsf{ivk}}_{\mathsf{rivk}}(\mathsf{ak}, \mathsf{nk})$ + where $\mathit{ShortCommit}$ is binding (see [Commitments](commitments.html)). ### Use of $\rho$ From 265ff91cc6177207fb978de75dc520e5b6d07db7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 21 Jan 2021 00:07:21 +0000 Subject: [PATCH 5/6] F might be Poseidon. Signed-off-by: Daira Hopwood --- book/src/design/nullifiers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index 7a8c837e..90492706 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -5,7 +5,7 @@ The nullifier design we use for Orchard is $$\mathsf{nf} = [F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm},$$ where: -- $F$ is a keyed circuit-efficient PRF (such as Rescue). +- $F$ is a keyed circuit-efficient PRF (such as Rescue or Poseidon). - $\rho$ is unique to this output. 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 From d6fd00b5b3a96c0acaf771afac72099aea2c31b4 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 21 Jan 2021 00:07:38 +0000 Subject: [PATCH 6/6] Cosmetics and Markdown formatting. Signed-off-by: Daira Hopwood --- book/src/design/commitments.md | 24 +++++++------- book/src/design/nullifiers.md | 58 +++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/book/src/design/commitments.md b/book/src/design/commitments.md index 37c0771b..6eff53d1 100644 --- a/book/src/design/commitments.md +++ b/book/src/design/commitments.md @@ -1,28 +1,28 @@ # Commitments -As in Sapling, we require two kinds of commitment schemes in Pollard: -- $HomomorphicCommit$ is a linearly homomorphic commitment scheme with perfect hiding, and +As in Sapling, we require two kinds of commitment schemes in Orchard: +- $\mathit{HomomorphicCommit}$ is a linearly homomorphic commitment scheme with perfect hiding, + and strong binding reducible to DL. +- $\mathit{Commit}$ and $\mathit{ShortCommit}$ are commitment schemes with perfect hiding, and strong binding reducible to DL. -- $Commit$ and $ShortCommit$ are commitment schemes with perfect hiding, and strong - binding reducible to DL. By "strong binding" we mean that the scheme is collision resistant on the input and randomness. -We instantiate $HomomorphicCommit$ with a Pedersen commitment, and use it for value -commitments: +We instantiate $\mathit{HomomorphicCommit}$ with a Pedersen commitment, and use it for +value commitments: -$$\mathsf{cv} = HomomorphicCommit^{\mathsf{cv}}_{\mathsf{rcv}}(v)$$ +$$\mathsf{cv} = \mathit{HomomorphicCommit}^{\mathsf{cv}}_{\mathsf{rcv}}(v)$$ -We instantiate $Commit$ and $ShortCommit$ with Sinsemilla, and use them for all other -commitments: +We instantiate $\mathit{Commit}$ and $\mathit{ShortCommit}$ with Sinsemilla, and use them +for all other commitments: $$\mathsf{ivk} = \mathit{ShortCommit}^{\mathsf{ivk}}_{\mathsf{rivk}}(\mathsf{ak}, \mathsf{nk})$$ -$$\mathsf{cm} = Commit^{\mathsf{cm}}_{\mathsf{rcm}}(\text{rest of note})$$ +$$\mathsf{cm} = \mathit{Commit}^{\mathsf{cm}}_{\mathsf{rcm}}(\text{rest of note})$$ This is the same split (and rationale) as in Sapling, but using the more PLONK-efficient -Sinsemilla instead of Bowe-Hopwood Pedersen hashes. +Sinsemilla instead of Bowe--Hopwood Pedersen hashes. -Note that we also deviate from Sapling by using $ShortCommit$ to deriving $\mathsf{ivk}$ +Note that we also deviate from Sapling by using $\mathit{ShortCommit}$ to deriving $\mathsf{ivk}$ instead of a full PRF. This removes an unnecessary (large) PRF primitive from the circuit, at the cost of requiring $\mathsf{rivk}$ to be part of the full viewing key. diff --git a/book/src/design/nullifiers.md b/book/src/design/nullifiers.md index 90492706..dbe76667 100644 --- a/book/src/design/nullifiers.md +++ b/book/src/design/nullifiers.md @@ -5,6 +5,7 @@ The nullifier design we use for Orchard is $$\mathsf{nf} = [F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G} + \mathsf{cm},$$ where: + - $F$ is a keyed circuit-efficient PRF (such as Rescue or Poseidon). - $\rho$ is unique to this output. 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 @@ -29,22 +30,26 @@ We care about several security properties for our nullifiers: - **Balance:** can I forge money? - **Note Privacy:** can I gain information about notes only from the public block chain? + - This describes notes sent in-band. - **Note Privacy (OOB):** can I gain information about notes sent out-of-band, only from the public block chain? + - In this case, we assume privacy of the channel over which the note is sent, and that the adversary does not have access to any notes sent to the same address which are then spent (so that the nullifier is on the block chain somewhere). - **Spend Unlinkability:** given the incoming viewing key for an address, and not the full viewing key, can I (possibly the sender) detect spends of any notes sent to that address? - - We're giving $ivk$ 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 + + - We're giving $\mathsf{ivk}$ 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. - **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. @@ -60,15 +65,17 @@ For our chosen design, our desired security properties rely on the following ass $$ \begin{array}{|l|l|} +\hline \text{Balance} & DL_E \\ -\text{Note Privacy} & HashDH^{KDF}_E \\ +\text{Note Privacy} & \mathit{HashDH}^{KDF}_E \\ \text{Note Privacy (OOB)} & \text{Near perfect} \ddagger \\ \text{Spend Unlinkability} & DDH_E^\dagger \vee PRF_F \\ \text{Faerie Resistance} & DL_E \\ +\hline \end{array} $$ -$HashDH^{KDF}_E$ is computational Diffie-Hellman using $KDF$ for the key derivation, with +$\mathit{HashDH}^{KDF}_E$ is computational Diffie-Hellman using $KDF$ for the key derivation, with one-time ephemeral keys. This assumption is heuristically weaker than $DDH_E$ but stronger than $DL_E$. @@ -92,31 +99,33 @@ $$ \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} & \text{Reason not to use} \\\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 -[F_{\mathsf{nk}}(\psi)] [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{Performance (2 variable-base)} \\\hline -[F_{\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_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline -[F_{\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_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline -[F_{\mathsf{nk}}(\psi)] H + \mathsf{cm} & (addr, v, H, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{NP(OOB) not perfect} \\\hline -[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline -[F_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline -[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline -[F_{\mathsf{nk}}(\rho)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline -[F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G_v} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & HashDH^{KDF}_E & \text{Near perfect} \ddagger & DDH_E^\dagger \vee PRF_F & \color{red}{\text{broken}} & \text{broken for FR} \\\hline -[F_{\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_F & DL_E & \text{Performance (2 fixed-base)} \\\hline -[F_{\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_F & DL_E & \text{Performance (2 fixed-base)} \\\hline +[\mathsf{nk}] [\theta] H & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & \mathit{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 & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E & RO_{GH} \wedge DL_E & \text{No SU for DL-breaking} \\\hline +\mathit{Hash}([\mathsf{nk}] [\theta] H) & (addr, v, H, \theta, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{\mathit{Hash}} & Coll_{\mathit{Hash}} \wedge RO_{GH} \wedge DL_E & Coll_{\mathit{Hash}} \text{ for FR} \\\hline +\mathit{Hash}([\mathsf{nk}] H + [\mathsf{rnf}] \mathcal{I}) & (addr, v, H, \mathsf{rnf}, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E \vee Pre_{\mathit{Hash}} & Coll_{\mathit{Hash}} \wedge RO_{GH} \wedge DL_E & Coll_{\mathit{Hash}} \text{ for FR} \\\hline +[F_{\mathsf{nk}}(\psi)] [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{Performance (2 variable-base)} \\\hline +[F_{\mathsf{nk}}(\psi)] H + [\mathsf{rnf}] \mathcal{I} & (addr, v, H, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline +[F_{\mathsf{nk}}(\psi)] \mathcal{G} + [\theta] H & (addr, v, H, \theta, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{Performance (1 variable- + 1 fixed-base)} \\\hline +[F_{\mathsf{nk}}(\psi)] H + \mathsf{cm} & (addr, v, H, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & RO_{GH} \wedge DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathsf{cm} & (addr, v, \rho, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & DDH_E^\dagger & DDH_E^\dagger \vee PRF_F & DL_E & \text{NP(OOB) not perfect} \\\hline +[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline +[F_{\mathsf{nk}}(\rho)] \mathcal{G_v} + [\mathsf{rnf}] \mathcal{I} & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & Coll_F \wedge DL_E & Coll_F \text{ for FR} \\\hline +[F_{\mathsf{nk}}(\rho) + \psi \pmod{p}] \mathcal{G_v} & (addr, v, \rho, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Near perfect} \ddagger & DDH_E^\dagger \vee PRF_F & \color{red}{\text{broken}} & \text{broken for FR} \\\hline +[F_{\mathsf{nk}}(\rho, \psi)] \mathcal{G} + \mathit{Commit}^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \psi, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & DL_E & \text{Performance (2 fixed-base)} \\\hline +[F_{\mathsf{nk}}(\rho)] \mathcal{G} + \mathit{Commit}^{\mathsf{nf}}_{\mathsf{rnf}}(v, \rho) & (addr, v, \rho, \mathsf{rnf}, \mathsf{rcm}) & DL_E & \mathit{HashDH}^{KDF}_E & \text{Perfect} & DDH_E^\dagger \vee PRF_F & DL_E & \text{Performance (2 fixed-base)} \\\hline \end{array} $$ In the above alternatives: -- $Hash$ is a keyed circuit-efficient hash (such as Rescue). + +- $\mathit{Hash}$ is a keyed circuit-efficient hash (such as Rescue). - $\mathcal{I}$ is an fixed independent base, independent of $\mathcal{G}$ and any others returned by $GH$. - $\mathcal{G_v}$ is a pair of fixed independent bases (independent of all others), where the specific choice of base depends on whether the note has zero value. - $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. - For zero-valued notes, $H$ is constrained by the circuit to a fixed base independent @@ -153,9 +162,11 @@ requirements: - Publish a unique value $\rho$ at note creation time, and blind that value within the nullifier computation. + - This is similar to the approach taken in Sprout and Sapling, which both implemented nullifiers as PRF outputs; Sprout uses the compression function from SHA-256, while Sapling uses BLAKE2s. + - Derive a unique base $H$ from some unique value, publish that unique base at note creation time, and then blind the base (either additively or multiplicatively) during nullifier computation. @@ -168,6 +179,7 @@ directly to the note (to avoid a DL-breaking adversary from immediately breaking We were considering using a design involving $H$ with the goal of eliminating all usages of a PRF inside the circuit, for two reasons: + - Instantiating $PRF_F$ with a traditional hash function is expensive in the circuit. - We didn't want to solely rely on an algebraic hash function satisfying $PRF_F$ to achieve **Spend Unlinkability**. @@ -196,6 +208,7 @@ is that it does not require an additional scalar multiplication, making it more inside the circuit. $\psi$'s derivation has two motivations: + - Deriving from a random value $\mathsf{rseed}$ enables multiple derived values to be conveyed to the recipient within an action (such as the ephemeral secret $\mathsf{esk}$, per [ZIP 212](https://zips.z.cash/zip-0212)), while keeping the note plaintext short. @@ -213,15 +226,16 @@ and reject it (as in Sapling). ### Use of $\mathsf{cm}$ The nullifier commits to the note value via $\mathsf{cm}$ for two reasons: + - It domain-separates nullifiers for zero-valued notes from other notes. This is necessary because we do not require zero-valued notes to exist in the commitment tree. - Designs that bind the nullifier to $F_{\mathsf{nk}}(\rho)$ require $Coll_F$ to achieve - **Faerie Resistance** (and similarly where $Hash$ is applied to a value derived from + **Faerie Resistance** (and similarly where $\mathit{Hash}$ is applied to a value derived from $H$). Adding $\mathsf{cm}$ to the nullifier avoids this assumption: all of the bases used to derive $\mathsf{cm}$ are fixed and independent of $\mathcal{G}$, and so the nullifier can be viewed as a Pedersen hash where the input includes $\rho$ directly. -The $Commit^{\mathsf{nf}}$ variants were considered to avoid directly depending on +The $\mathit{Commit}^{\mathsf{nf}}$ variants were considered to avoid 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 intermediate representation of $\mathsf{cm}$ as a group element, that is only used in nullifier computation. The circuit