From 206ac7e65f06a480db5aeee64238ebf26f19320b Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Mon, 1 Jun 2020 16:59:13 +1200 Subject: [PATCH] ZIP 304: Sapling Address Signatures --- zip-0304.rst | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 zip-0304.rst diff --git a/zip-0304.rst b/zip-0304.rst new file mode 100644 index 00000000..f3e042a9 --- /dev/null +++ b/zip-0304.rst @@ -0,0 +1,286 @@ +:: + + ZIP: 304 + Title: Sapling Address Signatures + Owners: Jack Grigg + Credits: Daira Hopwood + Sean Bowe + Status: Draft + Category: Wallet + Created: 2020-06-01 + License: MIT + + +Terminology +=========== + +The key word "SHOULD" in this document is to be interpreted as described in RFC 2119. +[#RFC2119]_ + + +Abstract +======== + +This proposal describes a mechanism for creating signatures with Sapling addresses, +suitable for use by the ``signmessage`` and ``verifymessage`` RPC methods in ``zcashd``. + + +Motivation +========== + +There are a variety of situations where it is useful for a user to be able to prove that +they control a given payment address. For example, before a high-value transfer of funds, +the sender may want to verify that the recipient will definitely be able to spend them, +to ensure that the funds won't be stuck in an invalid or unusable address. + +A payment address is analogous (in some cases, identical) to a public key in a signature +scheme. A transaction that spends funds received by the address, is authorized by making +(the equivalent of) a signature with the corresponding spending key. This authorization +protocol can be repurposed to instead sign a message provided by a third party. + +Bitcoin Core's ``bitcoind`` provides a ``signmessage`` RPC method that implements message +signing for Bitcoin addresses, leveraging the fact that a Bitcoin private key is just a +``secp256k`` private key, and a Bitcoin transaction authorizes spends with a signature. +``zcashd`` inherited this RPC method, and it can be used to make signatures for +transparent Zcash addresses. + +However, support for signing messages with shielded addresses was not possible when Zcash +launched, because of the design of the Sprout protocol (and the state of zero-knowledge +proof R&D at the time). Shielded transactions, by design, do not expose the payment +address of the sender when creating a transaction; in Sprout, this meant that the spending +key was a private input to the zero-knowledge proof, and not a key that could be used to +create a signature. + +One of the R&D achievements behind the Sapling protocol was the ability to use elliptic +curves inside a circuit. With this primitive available, Sapling keys and payment addresses +could be designed such that transaction authorization involved a signature. While this was +designed to enable hardware wallets (which lack the power to create zero-knowledge proofs, +but can easily create signatures), it also enables the creation of a mechanism for signing +arbitrary messages. That mechanism is the subject of this ZIP. + + +Conventions +=========== + +The following constants and functions used in this ZIP are defined in the Zcash protocol +specification: [#protocol-spec]_ + +- :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and + :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` [#constants]_ +- :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}` [#merkle-crh]_ +- :math:`\mathsf{DiversifyHash}(d)` [#diversify-hash]_ +- :math:`\mathsf{MixingPedersenHash}(cm, position)` [#mixing-pedersen-hash]_ +- :math:`\mathsf{PRF}^\mathsf{nfSapling}_nk(ρ)` [#prfs]_ +- :math:`\mathsf{SpendAuthSig.RandomizePrivate}(α, sk)`, + :math:`\mathsf{SpendAuthSig.RandomizePublic}(α, vk)`, + :math:`\mathsf{SpendAuthSig.Sign}(sk, m)`, and + :math:`\mathsf{SpendAuthSig.Verify}(vk, m, σ)` [#spend-auth-sig]_ +- :math:`\mathsf{NoteCommit}^\mathsf{Sapling}_rcm(g_d, pk_d, value)` [#note-commit]_ +- :math:`\mathsf{ValueCommit}_rcv(value)` [#value-commit]_ + +We also reproduce some notation and functions here for convenience: + +- :math:`a\,||\,b` means the concatenation of sequences :math:`a` then :math:`b`. + +- :math:`\mathsf{repr}_\mathbb{J}(P)` is the representation of the Jubjub elliptic curve + point :math:`P` as a bit sequence, defined in [#jubjub]_. + +- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)` refers to unkeyed BLAKE2b-256 in + sequential mode, with an output digest length of 32 bytes, 16-byte personalization + string :math:`p`, and input :math:`x`. + + +Requirements +============ + +Given a payment address, a message, and a valid signature, the following properties should +hold: + +- **Authentication:** the signature will not verify with any other payment address. + +- **Binding:** the signature will not verify with any modification, extension, or + truncation of the message. + +- **Non-malleability:** it should not be possible to obtain a second valid signature (with + a different encoding) for the same payment address and message without access to the + spending key for that payment address. + + +Non-requirements +================ + +Multiple signatures by a single payment addresses are not required to be unlinkable. + + +Specification +============= + +A Sapling address signature is created by taking the process for creating a Sapling Spend +description, and running it with fixed inputs: + +- A fake Sapling note with a value of 1 zatoshi and rcm = 0. +- A Sapling commitment tree that is empty except for the commitment for the fake note. + +Signature algorithm +------------------- + +The inputs to the signature algorithm are: + +- The payment address :math:`(d, pk_d)`, +- Its corresponding expanded spending key :math:`(ask, nsk, ovk)`, +- The SLIP-44 [#slip-0044]_ coin type, and +- The message :math:`msg` to be signed. + +The signature is created as follows: + +- Derive the full viewing key :math:`(ak, nk, ovk)` from the expanded spending key. + +- Let :math:`g_d = \mathsf{DiversifyHash}(d)`. + +- Let :math:`cm = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(g_d), \mathsf{repr}_\mathbb{J}(pk_d), 1)`. + +- Let :math:`rt` be the root of a Merkle tree with depth + :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and hashing function + :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}`, containing :math:`cm` at position 0, and + :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` at all other positions. + +- Let :math:`path` be the Merkle path from position 0 to :math:`rt`. [#merkle-path]_ + +- Let :math:`cv = \mathsf{ValueCommit}_0(1)`. + + - This is a constant and may be pre-computed. + +- Let :math:`nf = \mathsf{PRF}^\mathsf{nfSapling}_{\mathsf{repr}_\mathbb{J}(nk)}(\mathsf{repr}_\mathbb{J}(\mathsf{MixingPedersenHash}(cm, 0)))`. + +- Select a random :math:`α`. + +- Let :math:`rk = \mathsf{SpendAuthSig.RandomizePublic}(α, ak)`. + +- Let :math:`zkproof` be a Sapling spend proof with primary input :math:`(rt, cv, nf, rk)` + and auxiliary input :math:`(path, 0, g_d, pk_d, 1, 0, cm, 0, α, ak, nsk)`. + [#spend-statement]_ + +- Let :math:`rsk = \mathsf{SpendAuthSig.RandomizePrivate}(α, ask)`. + +- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index + form, not its hardened form (i.e. 133 for mainnet Zcash). + +- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`. + +- Let :math:`spendAuthSig = \mathsf{SpendAuthSig.Sign}(rsk, digest)`. + +- Return :math:`(nf, rk, zkproof, spendAuthSig)`. + +Verification algorithm +---------------------- + +The inputs to the verification algorithm are: + +- The payment address :math:`(d, pk_d)`, +- The SLIP-44 [#slip-0044]_ coin type, +- The message :math:`msg` that is claimed to be signed, and +- The ZIP 304 signature :math:`(nf, rk, zkproof, spendAuthSig)`. + +The signature is verified as follows: + +- Let :math:`coinType` be the 4-byte little-endian encoding of the coin type in its index + form, not its hardened form (i.e. 133 for mainnet Zcash). + +- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`. + +- If :math:`\mathsf{SpendAuthSig.Verify}(rk, digest, spendAuthSig) = 0`, return false. + +- Let :math:`cm = \mathsf{NoteCommit}^\mathsf{Sapling}_0(\mathsf{repr}_\mathbb{J}(\mathsf{DiversifyHash}(d)), \mathsf{repr}_\mathbb{J}(pk_d), 1)`. + +- Let :math:`rt` be the root of a Merkle tree with depth + :math:`\mathsf{MerkleDepth}^\mathsf{Sapling}` and hashing function + :math:`\mathsf{MerkleCRH}^\mathsf{Sapling}`, containing :math:`cm` at position 0, and + :math:`\mathsf{Uncommitted}^\mathsf{Sapling}` at all other positions. + +- Let :math:`path` be the Merkle path from position 0 to :math:`rt`. [#merkle-path]_ + +- Let :math:`cv = \mathsf{ValueCommit}_0(1)`. + + - This is a constant and may be pre-computed. + +- Verify :math:`zkproof` as a Sapling spend proof with primary input + :math:`(rt, cv, nf, rk)`. [#spend-statement]_ If verification fails, return false. + +- Return true. + +Signature encoding +------------------ + +The raw encoding of a ZIP 304 signature is :math:`nf\,||\,rk\,||\,zkproof\,||\,spendAuthSig`, for a +total size of 320 bytes. + +When encoding a ZIP 304 signature in a human-readable format, implementations **SHOULD** +use standard Base64 for compatibility with the ``signmessage`` and ``verifymessage`` RPC +methods in ``zcashd``. ZIP 304 signatures in this form are 428 bytes. + + +Rationale +========= + +We use a fake note within the signature scheme in order to reuse the Sapling Spend circuit +and its parameters. It is possible to construct a signature scheme with a smaller encoded +signature, but this would require a new circuit and another parameter-generation ceremony +(if Groth16 were used). + +We use a note value of 1 zatoshi instead of zero to ensure that the payment address is +fully bound to :math:`zkproof`. Notes with zero value have certain constraints disabled +inside the circuit. + +We set :math:`rcm` and :math:`rcv` to zero because we do not need the hiding properties of +the note commitment or value commitment schemes (as we are using a fixed-value fake note), +and can thus omit both :math:`rcm` and :math:`rcv` from the signature. + + +Security and Privacy Considerations +=================================== + +A normal (and desired) property of signature schemes is that all signatures for a specific +public key are linkable if the public key is known. ZIP 304 signatures have the additional +property that all signatures for a specific payment address are linkable without knowing +the payment address, as the first 32 bytes of each signature will be identical. + +A signature is bound to a specific diversified address of the spending key. Signatures for +different diversified addresses of the same spending key are unlinkable, as long as +:math:`α` is never re-used across signatures. + +Most of the data within a ZIP 304 signature is inherently non-malleable: + +- :math:`nullifier` is a binary public input to :math:`zkproof`. +- :math:`rk` is internally bound to :math:`spendAuthSig` by the design of RedJubjub. +- RedJubjub signatures are themselves non-malleable. + +The one component that is inherently malleable is :math:`zkproof`. The zero-knowledge +property of a Groth16 proof implies that anyone can take a valid proof, and re-randomize +it to obtain another valid proof with a different encoding. We prevent this by binding the +encoding of :math:`zkproof` to :math:`spendAuthSig`, by including :math:`zkproof` in the +message digest. + + +Reference implementation +======================== + +https://github.com/zcash/librustzcash/pull/210 + + +References +========== + +.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#protocol-spec] `Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#constants] `Section 5.3: Constants. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#merkle-crh] `Section 5.4.1.3: Merkle Tree Hash Function. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#diversify-hash] `Section 5.4.1.6: DiversifyHash Hash Function. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#mixing-pedersen-hash] `Section 5.4.1.8: Mixing Pedersen Hash Function. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#prfs] `Section 5.4.2: Pseudo Random Functions. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#spend-auth-sig] `Section 5.4.6.1: Spend Authorization Signature. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#note-commit] `Section 5.4.7.2: Windowed Pedersen commitments. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#value-commit] `Section 5.4.7.3: Homomorphic Pedersen commitments. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#jubjub] `Section 5.4.8.3: Jubjub. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#slip-0044] `SLIP-0044 : Registered coin types for BIP-0044 `_ +.. [#merkle-path] `Section 4.8: Merkle path validity. Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_ +.. [#spend-statement] `Section 4.15.2: Spend Statement (Sapling). Zcash Protocol Specification, Version 2020.1.4 or later [Overwinter+Sapling+Blossom+Heartwood] `_