From 9a87098e0ce8b894fc74db2d5a5b05ca7d785ff8 Mon Sep 17 00:00:00 2001 From: str4d Date: Wed, 30 May 2018 15:39:30 +1200 Subject: [PATCH 01/52] ZIP 32: Shielded Hierarchical Deterministic Wallets --- zip-0032.rst | 296 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 zip-0032.rst diff --git a/zip-0032.rst b/zip-0032.rst new file mode 100644 index 00000000..77ffec25 --- /dev/null +++ b/zip-0032.rst @@ -0,0 +1,296 @@ +:: + + ZIP: 32 + Title: Shielded Hierarchical Deterministic Wallets + Author: Jack Grigg + Daira Hopwood + Credits: Pieter Wuille + Marek Palatinus + Pavol Rusnak + Category: Standards Track + Created: 2018-05-22 + License: MIT + + +Terminology +=========== + +The key words "MUST" and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ + + +Abstract +======== + +This proposal defines a mechanism for extending hierarchical deterministic wallets (as decribed in BIP 32 +[#bip-0032]_) to support Zcash's shielded addresses. + +The specification has three parts. The first part defines a system for deriving a tree of Sapling key +components from a single seed. The second part defines an equivalent, but independent, system for Sprout key +components (which have a different internal construction). The third part shows how to use these trees in the +context of existing BIP 44 [#bip-0044]_ wallets. + + +Motivation +========== + +BIP 32 [#bip-0032]_ is the standard mechanism by which wallets for Bitcoin and its derivatives (including +Zcash's transparent addresses [#slip-0044]_) generate keys and addresses deterministically. This has several +advantages over random generation: + +- Wallets only need to store a single seed (particularly useful for hardware wallets). +- A one-time backup of the seed (usually stored as a word phrase [#bip-0039]_) can be used to recover funds + from all future addresses. +- Keys are arranged into a tree of chains, enabling wallets to represent "accounts" or other high-level + structures. +- View authority or spend authority can be delegated independently for sub-trees without compromising the + master seed. + +At present, no such equivalent exists for Zcash's shielded addresses. This is of particular concern for +hardware wallets; all currently-marketed devices only store a seed internally, and have trained their users to +only backup that seed. Given that the Sapling upgrade will make it feasible to use hardware wallets with +shielded addresses, it is desirable to have a standard mechanism for deriving them. + + +Conventions +=========== + +Most of the notation and functions used in this ZIP are defined in the Sapling protocol specification +[#sapling-spec]_. They are reproduced here for convenience: + +- truncate\ :sub:`k`\ (*S*) means the sequence formed from the first *k* elements of *S*. + +- *a* || *b* means the concatenation of sequences *a* then *b*. + +- [*k*] *P* means scalar multiplication in the group *P*. + +- LEOS2IP\ :sub:`l`\ (*S*) is the integer in range {0..2\ :sup:`l`\ -1} represented in little-endian order + by the byte sequence *S* of length *l*/8. + +- BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 + bytes, 16-byte personalization string *p*, and input *x*. + +- PRF\ :sup:`expand`\ (*sk, t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) + +- ToScalar(*x*) := LEOS2IP(*x*) (mod *r*\ :sub:`J`\ ) + +We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to +indicate hardened derivation as in BIP 44 [#bip-0044]_: + +- CDKsk(CDKsk(CDKsk(m\ :sub:`Sprout`\ , a'), b), c) is written as m\ :sub:`Sprout` / a' / b / c +- CDKfvk(CDKfvk(CDKfvk(M\ :sub:`Sapling`\ , a), b'), c) is written as M\ :sub:`Sapling` / a / b' / c + + +Specification: Sapling key derivation +===================================== + +Sapling extended keys +--------------------- + +BIP 32 defines a method to derive a number of child keys from a parent key. In order to prevent these from +depending solely on the parent key itself, both the private and public keys are extended with a 32-byte chain +code. We similarly extend Sapling keys with a chain code here. However, the concepts of "private" and "public" +keys in BIP 32 do not map cleanly to Sapling's key components. We take the following approach: + +- We derive child Sapling expanded spending keys, rather than Sapling spending keys. This enables us to + implement both hardened and non-hardened derivation modes (the latter being incompatible with Sapling + spending keys). + +- We do not derive Sapling public keys directly, as this would prevent the use of diversified addresses. + Instead, we derive Sapling full viewing keys, from which payment addresses can be generated. This maintains + the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all + transactions involving that address, which a Sapling full viewing key also enables. + +We represent a Sapling extended spending key as (*ask, nsk, ovk, c*), where (*ask, nsk, ovk*) is the normal +Sapling expanded spending key, and *c* is the chain code. + +We represent a Sapling extended full viewing key as (*ak, nk, ovk, c*), where (*ak, nk, ovk*) is the normal +Sapling full viewing key, and *c* is the chain code. + +Master key generation +--------------------- + +Let *S* be a seed byte sequence of a chosen length. + +- Calculate *I* = BLAKE2b-512("ZcashIP32Sapling", *S*). +- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . +- Use *I*\ :sub:`L` as the master spending key *s*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code + *c*\ :sub:`m`\ . +- Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , + *ovk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation [#sapling-key-components]_: + + - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x00)) + - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x01)) + - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x02)) + - **TODO** *d*\ :sub:`m` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x03 || *i*))) + +Child key derivation +-------------------- + +As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index *i*, +depends on the type of key being derived, and whether this is a hardened or non-hardened derivation. + +Deriving a child extended spending key +`````````````````````````````````````` +CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → +(*ask*\ :sub:`i`\ , *nsk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) + +- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). + + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x04 || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x05 || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + +- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x06)) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x07)) +- Return: + + - *ask*\ :sub:`i` = *I*\ :sub:`ask` + *ask*\ :sub:`par` + - *nsk*\ :sub:`i` = *I*\ :sub:`nsk` + *nsk*\ :sub:`par` + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x08 || *ovk*\ :sub:`par`\ )) + - *c*\ :sub:`i` = *I*\ :sub:`R` + - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x09 || *d*\ :sub:`par,0` || *j* || *i*))) + +Deriving a child extended full viewing key +`````````````````````````````````````````` +CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → +(*ak*\ :sub:`i`\ , *nk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) + +- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). + + - If so (hardened child): return failure + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x05 || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + +- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x06)) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x07)) +- Return: + + - *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] *G* + *ak*\ :sub:`par` + - *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] *G* + *nk*\ :sub:`par` + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x08 || *ovk*\ :sub:`par`\ )) + - *c*\ :sub:`i` = *I*\ :sub:`R` + - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x09 || *d*\ :sub:`par,0` || *j* || *i*))) + + +Specification: Sprout key derivation +==================================== + +For completeness, we define a system for deriving a tree of Sprout keys components. It is unlikely that this +will garner much usage once Sapling activates, but is presented for those users who may require it. + +Sprout extended keys +-------------------- + +Due to the way Sprout keys are constructed and used, it is not possible to derive incoming viewing keys or +payment addresses in parallel with spending keys. Nor is it possible to implement non-hardened derivation. +We therefore only define and derive Sprout extended spending keys. + +We represent a Sprout extended spending key as (*a*\ :sub:`sk`\ , *c*), where *a*\ :sub:`sk` is the normal +Sprout spending key, and *c* is the chain code. + +Master key generation +--------------------- + +Let *S* be a seed byte sequence of a chosen length. + +- Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*). +- Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ . +- Use *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m`\ , and *I*\ :sub:`R` as the master chain code + *c*\ :sub:`m`\ . + +Child key derivation +-------------------- + +CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , *c*\ :sub:`i`\ ) + +- Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). + + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x80 || *a*\ :sub:`sk,par` || *i*) + - If not (normal child): return failure + +- Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . +- Use *I*\ :sub:`L` as the child spending key *a*\ :sub:`sk,i`\ , and *I*\ :sub:`R` as the child chain code + *c*\ :sub:`m`\ . + + +Specification: Wallet usage +=========================== + +Existing Zcash-supporting HD wallets all use BIP 44 [#bip-0044]_ to organize their derived keys. In order to +more easily mesh with existing user experiences, we broadly follow BIP 44's design here. However, we have +altered the design where it makes sense to leverage features of shielded addresses. + +Key path levels +--------------- + +Both Sprout and Sapling key paths have the following three path levels at the top, all of which use hardened +derivation: + +- ``purpose``: a constant set to 32' (or 0x80000020) following the BIP 43 recommendation. It indicates that + the subtree of this node is used according to this specification. + +- ``coin_type``: a constant identifying the cybercoin that this subtree's keys are used with. For + compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 + [#slip-0044]_. + +- ``account``: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44 [#bip-0044]_. + +Unlike BIP 44, neither Sprout nor Sapling have a `change` path level. This is because shielded addresses are +never publicly visible in transactions, which means that sending change back to the originating address is +indistinguishable from using a change address. + +Sapling key path +---------------- + +Sapling provides a mechanism to allow the efficient creation of diversified payment addresses with the same +spending authority. A group of such addresses shares the same full viewing key and incoming viewing key, and +so creating as many unlinkable addresses as needed does not increase the cost of scanning the block chain for +relevant transactions. + +The above key path levels include an account identifier, which in all user interfaces is represented as a +"bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling +ZIP 32 derivation MUST support the following path:: + + m_Sapling / purpose' / coin_type' / account' + +Wallets MUST support generating the default payment address (corresponding to the default diversifier). They +MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the +user experience of giving a unique address to each recipient. Note that a given account can have a maximum of +2\ :sup:`88` payment addresses. + +If in certain circumstances a wallet needs to derive independent spend authorities within a single account, +they MAY additionally support a non-hardened ``address_index`` path level as in BIP 44:: + + m_Sapling / purpose' / coin_type' / account' / address_index + +Sprout key path +--------------- + +Wallets implementing Sprout ZIP 32 derivation MUST support the following path:: + + m_Sprout / purpose' / coin_type' / account' / address_index + + +Test Vectors +============ + +TBC + + +Reference Implementation +======================== + +https://github.com/zcash/zcash/pull/XXXX + + +References +========== + +.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#bip-0032] `BIP 32: Hierarchical Deterministic Wallets `_ +.. [#bip-0039] `BIP 39: Mnemonic code for generating deterministic keys `_ +.. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ +.. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ +.. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ +.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ +.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ From a5309ed60e0dc19747bed55fa53499a6bce3a78f Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 08:42:37 +1200 Subject: [PATCH 02/52] Address Daira's comments --- zip-0032.rst | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 77ffec25..26131950 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -61,7 +61,7 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - *a* || *b* means the concatenation of sequences *a* then *b*. -- [*k*] *P* means scalar multiplication in the group *P*. +- [*k*] *P* means scalar multiplication of the elliptic curve point *P* by the scalar *k*. - LEOS2IP\ :sub:`l`\ (*S*) is the integer in range {0..2\ :sup:`l`\ -1} represented in little-endian order by the byte sequence *S* of length *l*/8. @@ -69,7 +69,7 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string *p*, and input *x*. -- PRF\ :sup:`expand`\ (*sk, t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) +- PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) - ToScalar(*x*) := LEOS2IP(*x*) (mod *r*\ :sub:`J`\ ) @@ -175,7 +175,7 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:` Specification: Sprout key derivation ==================================== -For completeness, we define a system for deriving a tree of Sprout keys components. It is unlikely that this +For completeness, we define a system for deriving a tree of Sprout key components. It is unlikely that this will garner much usage once Sapling activates, but is presented for those users who may require it. Sprout extended keys @@ -231,13 +231,14 @@ derivation: - ``coin_type``: a constant identifying the cybercoin that this subtree's keys are used with. For compatibility with existing BIP 44 implementations, we use the same constants as defined in SLIP 44 - [#slip-0044]_. + [#slip-0044]_. Note that in keeping with that document, all cybercoin testnets share ``coin_type`` index 1. - ``account``: numbered from index 0 in sequentially increasing manner. Defined as in BIP 44 [#bip-0044]_. -Unlike BIP 44, neither Sprout nor Sapling have a `change` path level. This is because shielded addresses are -never publicly visible in transactions, which means that sending change back to the originating address is -indistinguishable from using a change address. +Unlike BIP 44, neither Sprout nor Sapling have a `change` path level. The use of change addresses in Bitcoin +is a (failed) attempt to increase the difficulty of tracking users on the transaction graph, by segregating +external and internal address usage. Shielded addresses are never publicly visible in transactions, which +means that sending change back to the originating address is indistinguishable from using a change address. Sapling key path ---------------- @@ -255,8 +256,10 @@ ZIP 32 derivation MUST support the following path:: Wallets MUST support generating the default payment address (corresponding to the default diversifier). They MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the -user experience of giving a unique address to each recipient. Note that a given account can have a maximum of -2\ :sup:`88` payment addresses. +user experience of giving a unique address to each recipient. + +Note that a given account can have a maximum of approximately 2\ :sup:`87` payment addresses, because each +diversifier has around a 50% chance of being invalid. If in certain circumstances a wallet needs to derive independent spend authorities within a single account, they MAY additionally support a non-hardened ``address_index`` path level as in BIP 44:: From 4ed0316834b10c73824e54fd0d4ff0118699fa7f Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 08:43:51 +1200 Subject: [PATCH 03/52] Use byte sequences for constant single-byte inputs to PRF_expand --- zip-0032.rst | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 26131950..b0dd7614 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -118,10 +118,10 @@ Let *S* be a seed byte sequence of a chosen length. - Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , *ovk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation [#sapling-key-components]_: - - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x00)) - - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x01)) - - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x02)) - - **TODO** *d*\ :sub:`m` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x03 || *i*))) + - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x00])) + - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x01])) + - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x02])) + - **TODO** *d*\ :sub:`m` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x03, *i*]))) Child key derivation -------------------- @@ -136,19 +136,19 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub: - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x04 || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x05 || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x04] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x05] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x06)) -- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x07)) +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x06])) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x07])) - Return: - *ask*\ :sub:`i` = *I*\ :sub:`ask` + *ask*\ :sub:`par` - *nsk*\ :sub:`i` = *I*\ :sub:`nsk` + *nsk*\ :sub:`par` - - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x08 || *ovk*\ :sub:`par`\ )) + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x08] || *ovk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` - - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x09 || *d*\ :sub:`par,0` || *j* || *i*))) + - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x09] || *d*\ :sub:`par,0` || *j* || *i*))) Deriving a child extended full viewing key `````````````````````````````````````````` @@ -158,18 +158,18 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:` - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x05 || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x05] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x06)) -- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x07)) +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x06])) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x07])) - Return: - *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] *G* + *ak*\ :sub:`par` - *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] *G* + *nk*\ :sub:`par` - - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , 0x08 || *ovk*\ :sub:`par`\ )) + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x08] || *ovk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` - - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , 0x09 || *d*\ :sub:`par,0` || *j* || *i*))) + - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x09] || *d*\ :sub:`par,0` || *j* || *i*))) Specification: Sprout key derivation @@ -205,7 +205,7 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , 0x80 || *a*\ :sub:`sk,par` || *i*) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *a*\ :sub:`sk,par` || *i*) - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . From c73733ae1348512dab26df9d0704a77932c4640d Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 08:56:24 +1200 Subject: [PATCH 04/52] Define a diversifier key dk --- zip-0032.rst | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index b0dd7614..1ef4580e 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -100,11 +100,11 @@ keys in BIP 32 do not map cleanly to Sapling's key components. We take the follo the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all transactions involving that address, which a Sapling full viewing key also enables. -We represent a Sapling extended spending key as (*ask, nsk, ovk, c*), where (*ask, nsk, ovk*) is the normal -Sapling expanded spending key, and *c* is the chain code. +We represent a Sapling extended spending key as (*ask*, *nsk*, *ovk*, *dk*, *c*), where (*ask*, *nsk*, *ovk*) +is the normal Sapling expanded spending key, *dk* is a diversifier key, and *c* is the chain code. -We represent a Sapling extended full viewing key as (*ak, nk, ovk, c*), where (*ak, nk, ovk*) is the normal -Sapling full viewing key, and *c* is the chain code. +We represent a Sapling extended full viewing key as (*ak*, *nk*, *ovk*, *dk*, *c*), where (*ak*, *nk*, *ovk*) +is the normal Sapling full viewing key, *dk* is the same diversifier key as above, and *c* is the chain code. Master key generation --------------------- @@ -116,12 +116,13 @@ Let *S* be a seed byte sequence of a chosen length. - Use *I*\ :sub:`L` as the master spending key *s*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . - Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , - *ovk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation [#sapling-key-components]_: + *ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation + [#sapling-key-components]_: - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x00])) - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x01])) - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x02])) - - **TODO** *d*\ :sub:`m` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x03, *i*]))) + - *dk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x10])) Child key derivation -------------------- @@ -131,45 +132,45 @@ depends on the type of key being derived, and whether this is a hardened or non- Deriving a child extended spending key `````````````````````````````````````` -CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → -(*ask*\ :sub:`i`\ , *nsk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) +CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → +(*ask*\ :sub:`i`\ , *nsk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *dk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x04] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x05] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x06])) -- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x07])) +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x14])) - Return: - *ask*\ :sub:`i` = *I*\ :sub:`ask` + *ask*\ :sub:`par` - *nsk*\ :sub:`i` = *I*\ :sub:`nsk` + *nsk*\ :sub:`par` - - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x08] || *ovk*\ :sub:`par`\ )) + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x15] || *ovk*\ :sub:`par`\ )) + - *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` - - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x09] || *d*\ :sub:`par,0` || *j* || *i*))) Deriving a child extended full viewing key `````````````````````````````````````````` -CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → -(*ak*\ :sub:`i`\ , *nk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) +CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → +(*ak*\ :sub:`i`\ , *nk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *dk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x05] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x06])) -- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x07])) +- Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) +- Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x14])) - Return: - *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] *G* + *ak*\ :sub:`par` - *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] *G* + *nk*\ :sub:`par` - - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x08] || *ovk*\ :sub:`par`\ )) + - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x15] || *ovk*\ :sub:`par`\ )) + - *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` - - **TODO** *d*\ :sub:`i,j` = FirstValid(*i*, truncate\ :sub:`11`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x09] || *d*\ :sub:`par,0` || *j* || *i*))) Specification: Sprout key derivation From aa36706f381665edfe804170687df5f961981e7a Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 14:27:30 +1200 Subject: [PATCH 05/52] Fix usage of LEOS2IP in definition of ToScalar --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1ef4580e..d62d6de3 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -71,7 +71,7 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) -- ToScalar(*x*) := LEOS2IP(*x*) (mod *r*\ :sub:`J`\ ) +- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ) We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to indicate hardened derivation as in BIP 44 [#bip-0044]_: From efd68a4474db66e48c5286a28e36ede52d6cffb1 Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 14:37:50 +1200 Subject: [PATCH 06/52] Define I2LEOSP_l(k) and use it to encode the child key indices Note that this means they are encoded in little-endian order, which is the opposite of BIP 32. --- zip-0032.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index d62d6de3..fd21b807 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -73,6 +73,11 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ) +We also define the following conversion function: + +- I2LEOSP\ :sub:`l`\ (*k*) is the byte sequence *S* of length *l*/8 representing in little-endian order the + integer *k* in range {0..2\ :sup:`l`\ -1}. It is the reverse operation of LEOS2IP\ :sub:`l`\ (*S*). + We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to indicate hardened derivation as in BIP 44 [#bip-0044]_: @@ -137,8 +142,8 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -159,7 +164,7 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || *i*) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -206,7 +211,7 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *a*\ :sub:`sk,par` || *i*) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *a*\ :sub:`sk,par` || I2LEOSP\ :sub:`32`\ (*i*)) - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . From f07b6d26133d59c701251b1572f873b16bf46df8 Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 14:42:49 +1200 Subject: [PATCH 07/52] Define how to derive diversifiers from Sapling extended keys --- zip-0032.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index fd21b807..1cb601a1 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -177,6 +177,18 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` +Diversifier derivation +---------------------- + +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*\ :sub:`i`\ . In +order to reach the maximum possible diversifier range without running into the birthday bound, we use the PRP +defined in [#diversifier-prp]_ as follows: + +- Let *j* be the index of the desired diversifier. +- *d*\ :sub:`i,j` = PRP(*dk*\ :sub:`i`\ , I2LEOSP\ :sub:`88`\ (*j*)) + +The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,0`\ . + Specification: Sprout key derivation ==================================== @@ -301,5 +313,6 @@ References .. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ +.. [#diversifier-prp] `TODO`_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ From a01dbbbcbcd39b3e0d1db508599bf1b3c6518fe4 Mon Sep 17 00:00:00 2001 From: str4d Date: Fri, 8 Jun 2018 14:42:56 +1200 Subject: [PATCH 08/52] Note that ZIP 32 is consistently little-endian --- zip-0032.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index 1cb601a1..60d4c30d 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -78,6 +78,9 @@ We also define the following conversion function: - I2LEOSP\ :sub:`l`\ (*k*) is the byte sequence *S* of length *l*/8 representing in little-endian order the integer *k* in range {0..2\ :sup:`l`\ -1}. It is the reverse operation of LEOS2IP\ :sub:`l`\ (*S*). +Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling +specification), which is the opposite of BIP 32. + We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to indicate hardened derivation as in BIP 44 [#bip-0044]_: From 9596aedaa0833435188af0b5526c943281f15218 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 00:15:45 +0100 Subject: [PATCH 09/52] ZIP 32: use FF1-AES256 as the PRP. Signed-off-by: Daira Hopwood --- zip-0032.rst | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 60d4c30d..18f494d5 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -66,6 +66,8 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - LEOS2IP\ :sub:`l`\ (*S*) is the integer in range {0..2\ :sup:`l`\ -1} represented in little-endian order by the byte sequence *S* of length *l*/8. +- I2LEBSP\ :sub:`l`\ (*k*) is the sequence of *l* bits representing *k* in little-endian order. + - BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string *p*, and input *x*. @@ -73,6 +75,12 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ) +The following algorithm standardized in [#NIST-SP-800-38G]_ is also used: + +- FF1-AES256.Encrypt(*key*, *tweak*, *x*) refers to the FF1 encryption algorithm using AES with a + 256-bit *key*, and parameters *radix = 2*, *minlen = 88*, *maxlen = 88*. It will be used only with + the empty string as the *tweak*. *x* is a sequence of 88 bits, as is the output. + We also define the following conversion function: - I2LEOSP\ :sub:`l`\ (*k*) is the byte sequence *S* of length *l*/8 representing in little-endian order the @@ -183,12 +191,12 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: Diversifier derivation ---------------------- -The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*\ :sub:`i`\ . In -order to reach the maximum possible diversifier range without running into the birthday bound, we use the PRP -defined in [#diversifier-prp]_ as follows: +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*\ :sub:`i`\ . +In order to reach the maximum possible diversifier range without running into the birthday bound, we use +FF1-AES256 as a Pseudo-Random Permutation as follows: - Let *j* be the index of the desired diversifier. -- *d*\ :sub:`i,j` = PRP(*dk*\ :sub:`i`\ , I2LEOSP\ :sub:`88`\ (*j*)) +- *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*)) The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,0`\ . @@ -316,6 +324,7 @@ References .. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ -.. [#diversifier-prp] `TODO`_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ +.. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ + From da683d31b9524028f1ec17993aac6c2a8452db66 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Wed, 4 Jul 2018 00:24:42 +0100 Subject: [PATCH 10/52] Remove hardening from example public-key HD path Hardened derivation is undefined for an extended FVK --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 18f494d5..451749eb 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -93,7 +93,7 @@ We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, indicate hardened derivation as in BIP 44 [#bip-0044]_: - CDKsk(CDKsk(CDKsk(m\ :sub:`Sprout`\ , a'), b), c) is written as m\ :sub:`Sprout` / a' / b / c -- CDKfvk(CDKfvk(CDKfvk(M\ :sub:`Sapling`\ , a), b'), c) is written as M\ :sub:`Sapling` / a / b' / c +- CDKfvk(CDKfvk(CDKfvk(M\ :sub:`Sapling`\ , a), b), c) is written as M\ :sub:`Sapling` / a / b / c Specification: Sapling key derivation From 3f2815838efdf4c80b05c28e81e1c52a10599283 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 07:39:25 +0100 Subject: [PATCH 11/52] Cosmetic improvements. Signed-off-by: Daira Hopwood --- zip-0032.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 451749eb..282983a9 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -75,11 +75,11 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ) -The following algorithm standardized in [#NIST-SP-800-38G]_ is also used: +The following algorithm standardized in [#NIST-SP-800-38G]_ is used: - FF1-AES256.Encrypt(*key*, *tweak*, *x*) refers to the FF1 encryption algorithm using AES with a - 256-bit *key*, and parameters *radix = 2*, *minlen = 88*, *maxlen = 88*. It will be used only with - the empty string as the *tweak*. *x* is a sequence of 88 bits, as is the output. + 256-bit *key*, and parameters *radix* = 2, *minlen* = 88, *maxlen* = 88. It will be used only with + the empty string "" as the *tweak*. *x* is a sequence of 88 bits, as is the output. We also define the following conversion function: From 1b3ea422fed707ed115bf933763006fb24d539f3 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 07:39:52 +0100 Subject: [PATCH 12/52] Reference version 2018.0-beta-21 or later of the Sapling protocol spec. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 282983a9..4f037630 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -324,7 +324,7 @@ References .. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ -.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ +.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From f94b9a4c67c9b192e98606722704552813d04875 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 08:10:58 +0100 Subject: [PATCH 13/52] Define r_J. Signed-off-by: Daira Hopwood --- zip-0032.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 4f037630..8aef6aec 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -73,7 +73,8 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) -- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ) +- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J`\ is the order + of the Jubjub large prime subgroup. The following algorithm standardized in [#NIST-SP-800-38G]_ is used: From ff5affbc77066ee3bbc2ba3591f4b017aecac87f Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 08:14:26 +0100 Subject: [PATCH 14/52] Cosmetics. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 8aef6aec..d54b40c9 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -73,7 +73,7 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) -- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J`\ is the order +- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J` \ is the order of the Jubjub large prime subgroup. The following algorithm standardized in [#NIST-SP-800-38G]_ is used: From de065cf34400faae897d37a89c856a9d65de28ff Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 4 Jul 2018 08:20:47 +0100 Subject: [PATCH 15/52] Update another reference to the Sapling spec version. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index d54b40c9..f883951e 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -326,6 +326,6 @@ References .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ -.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] `_ +.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From 8a49de84f6461247d7be5c7f0eb9159a391da232 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 13:56:29 +0100 Subject: [PATCH 16/52] Cosmetics. Signed-off-by: Daira Hopwood --- zip-0032.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index f883951e..1a27e72b 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -21,8 +21,8 @@ The key words "MUST" and "MAY" in this document are to be interpreted as describ Abstract ======== -This proposal defines a mechanism for extending hierarchical deterministic wallets (as decribed in BIP 32 -[#bip-0032]_) to support Zcash's shielded addresses. +This proposal defines a mechanism for extending hierarchical deterministic wallets, as decribed in BIP 32 +[#bip-0032]_, to support Zcash's shielded addresses. The specification has three parts. The first part defines a system for deriving a tree of Sapling key components from a single seed. The second part defines an equivalent, but independent, system for Sprout key @@ -46,8 +46,8 @@ advantages over random generation: master seed. At present, no such equivalent exists for Zcash's shielded addresses. This is of particular concern for -hardware wallets; all currently-marketed devices only store a seed internally, and have trained their users to -only backup that seed. Given that the Sapling upgrade will make it feasible to use hardware wallets with +hardware wallets; all currently-marketed devices only store a seed internally, and have trained their users +to only backup that seed. Given that the Sapling upgrade will make it feasible to use hardware wallets with shielded addresses, it is desirable to have a standard mechanism for deriving them. @@ -292,7 +292,7 @@ Note that a given account can have a maximum of approximately 2\ :sup:`87` payme diversifier has around a 50% chance of being invalid. If in certain circumstances a wallet needs to derive independent spend authorities within a single account, -they MAY additionally support a non-hardened ``address_index`` path level as in BIP 44:: +they MAY additionally support a non-hardened ``address_index`` path level as in [#bip-0044]_:: m_Sapling / purpose' / coin_type' / account' / address_index From b3c051eb4fae6d302bc31e27bad18da17330cea1 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 13:57:11 +0100 Subject: [PATCH 17/52] Say that ZIP 32 does not supplant the use of BIPs 32 & 44 for transparent addresses. Signed-off-by: Daira Hopwood --- zip-0032.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index 1a27e72b..768dd840 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -29,6 +29,9 @@ components from a single seed. The second part defines an equivalent, but indepe components (which have a different internal construction). The third part shows how to use these trees in the context of existing BIP 44 [#bip-0044]_ wallets. +This specification is not intended to supplant the existing use by some Zcash wallets of BIP 32 and BIP 44 +for transparent Zcash addresses. + Motivation ========== From 6f85acb9b1ff195fc4f13070245ce345cb5ea275 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 13:57:44 +0100 Subject: [PATCH 18/52] Specify the range of j when generating diversifiers. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 768dd840..be90a210 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -199,7 +199,7 @@ The 88-bit diversifiers for a Sapling extended key are derived from its diversif In order to reach the maximum possible diversifier range without running into the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows: -- Let *j* be the index of the desired diversifier. +- Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1. - *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*)) The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,0`\ . From 0fc7c704a77e57d6090b65bd335aecf7b5bc9993 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 16:57:49 +0100 Subject: [PATCH 19/52] Add specifications of key fingerprints, tags, and encodings. Signed-off-by: Daira Hopwood --- zip-0032.rst | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index be90a210..b575ccbf 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -71,8 +71,11 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - I2LEBSP\ :sub:`l`\ (*k*) is the sequence of *l* bits representing *k* in little-endian order. -- BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 - bytes, 16-byte personalization string *p*, and input *x*. +- BLAKE2b-256(*p*, *x*) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of + 32 bytes, 16-byte personalization string *p*, and input *x*. + +- BLAKE2b-512(*p*, *x*) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of + 64 bytes, 16-byte personalization string *p*, and input *x*. - PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) @@ -307,6 +310,88 @@ Wallets implementing Sprout ZIP 32 derivation MUST support the following path:: m_Sprout / purpose' / coin_type' / account' / address_index +Specification: Fingerprints and Tags +==================================== + +Sapling Full Viewing Key Fingerprints and Tags +---------------------------------------------- + +A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding *FVK* (as specified +in [#sapling-spec]_ section 5.6.7) is given by:: + + BLAKE2b-256("ZcashSaplingFVFP", *FVK*) + +It MAY be used to uniquely identify a particular Sapling full viewing key. + +A "Sapling full viewing key tag" is the first 4 bytes of the corresponding Sapling full viewing key +fingerprint. It is intended for optimizing performance of key lookups, and MUST NOT be assumed to +uniquely identify a particular key. + +Sprout Address Fingerprints and Tags +------------------------------------ + +A "Sprout address fingerprint" of a Sprout payment address with raw encoding *ADDR* (as specified in +[#sapling-spec]_ section 5.6.3, including the lead bytes) is given by:: + + BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*) + +It MAY be used to uniquely identify a particular Sprout payment address. + +A "Sprout address tag" is the first 4 bytes of the corresponding Sprout address fingerprint. It is +intended for optimizing performance of address lookups, and MUST NOT be assumed to uniquely identify +a particular address. + + +Specification: Key Encodings +============================ + +The following encodings are analogous to the ``xprv`` and ``xpub`` encodings defined +in BIP 32 for transparent keys and addresses. Each key type has a raw representation +and a Bech32 [#bip-0173]_ encoding. + + +Sapling extended spending keys +------------------------------ + +A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *depth*, +with parent full viewing key tag *parent_fvk_tag* and child number *i*, is +represented as a byte sequence:: + + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* + +When encoded as Bech32, the Human-Readable Part is "secret-extended-key-main" +for the production network, or "secret-extended-key-main" for the test network. + +Sapling extended full viewing keys +---------------------------------- + +A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *depth*, +with parent full viewing key tag *parent_fvk_tag* and child number *i*, is +represented as a byte sequence:: + + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* + +When encoded as Bech32, the Human-Readable Part is "zxviews" for the production +network, or "zxviewtestsapling" for the test network. + +Sprout extended spending keys +----------------------------- + +A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with +parent address tag *parent_addr_tag* and child number *i*, is represented as a +byte sequence:: + + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* + +where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in +[#sapling-spec]_ section 5.6.8, including the lead bytes. + +When encoded as Bech32, the Human-Readable Part is "zxsprout" for the production +network, or "zxtestsprout" for the test network. Sprout extended spending keys +are encoded using Bech32 even though other Sprout keys and addresses are encoded +using Base58Check. + + Test Vectors ============ @@ -328,6 +413,7 @@ References .. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets `_ .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ +.. [#bip-0173] `BIP 173: Base32 address format for native v0-16 witness outputs `_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From 52eac8c2c1fd7908cdf8389aa6bcc9fc66f7a3b3 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 17:00:52 +0100 Subject: [PATCH 20/52] Put human-readable parts in monospace. Signed-off-by: Daira Hopwood --- zip-0032.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index b575ccbf..eb6e7976 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -359,8 +359,8 @@ represented as a byte sequence:: I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* -When encoded as Bech32, the Human-Readable Part is "secret-extended-key-main" -for the production network, or "secret-extended-key-main" for the test network. +When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main`` +for the production network, or ``secret-extended-key-main`` for the test network. Sapling extended full viewing keys ---------------------------------- @@ -371,8 +371,8 @@ represented as a byte sequence:: I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* -When encoded as Bech32, the Human-Readable Part is "zxviews" for the production -network, or "zxviewtestsapling" for the test network. +When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production +network, or ``zxviewtestsapling`` for the test network. Sprout extended spending keys ----------------------------- @@ -386,8 +386,8 @@ byte sequence:: where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in [#sapling-spec]_ section 5.6.8, including the lead bytes. -When encoded as Bech32, the Human-Readable Part is "zxsprout" for the production -network, or "zxtestsprout" for the test network. Sprout extended spending keys +When encoded as Bech32, the Human-Readable Part is ``zxsprout`` for the production +network, or ``zxtestsprout`` for the test network. Sprout extended spending keys are encoded using Bech32 even though other Sprout keys and addresses are encoded using Base58Check. @@ -414,6 +414,7 @@ References .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ .. [#bip-0173] `BIP 173: Base32 address format for native v0-16 witness outputs `_ +.. [#zip-0173] `ZIP 173: Bech32 Format `_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From 3e884f957995fde1ae34829f0de0955009c1149f Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 17:02:54 +0100 Subject: [PATCH 21/52] Fix formatting. Signed-off-by: Daira Hopwood --- zip-0032.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index eb6e7976..7ddb240a 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -317,9 +317,9 @@ Sapling Full Viewing Key Fingerprints and Tags ---------------------------------------------- A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding *FVK* (as specified -in [#sapling-spec]_ section 5.6.7) is given by:: +in [#sapling-spec]_ section 5.6.7) is given by: - BLAKE2b-256("ZcashSaplingFVFP", *FVK*) + * BLAKE2b-256("ZcashSaplingFVFP", *FVK*) It MAY be used to uniquely identify a particular Sapling full viewing key. @@ -331,9 +331,9 @@ Sprout Address Fingerprints and Tags ------------------------------------ A "Sprout address fingerprint" of a Sprout payment address with raw encoding *ADDR* (as specified in -[#sapling-spec]_ section 5.6.3, including the lead bytes) is given by:: +[#sapling-spec]_ section 5.6.3, including the lead bytes) is given by: - BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*) + * BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*) It MAY be used to uniquely identify a particular Sprout payment address. @@ -355,9 +355,9 @@ Sapling extended spending keys A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *depth*, with parent full viewing key tag *parent_fvk_tag* and child number *i*, is -represented as a byte sequence:: +represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* + * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main`` for the production network, or ``secret-extended-key-main`` for the test network. @@ -367,9 +367,9 @@ Sapling extended full viewing keys A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *depth*, with parent full viewing key tag *parent_fvk_tag* and child number *i*, is -represented as a byte sequence:: +represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* + * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production network, or ``zxviewtestsapling`` for the test network. @@ -379,9 +379,9 @@ Sprout extended spending keys A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with parent address tag *parent_addr_tag* and child number *i*, is represented as a -byte sequence:: +byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* + * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in [#sapling-spec]_ section 5.6.8, including the lead bytes. From b9e6ed7e1a2f0f41887ceb34751bf08b6282ba5b Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 17:10:13 +0100 Subject: [PATCH 22/52] Another formatting improvement. Signed-off-by: Daira Hopwood --- zip-0032.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 7ddb240a..5db64af7 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -319,7 +319,7 @@ Sapling Full Viewing Key Fingerprints and Tags A "Sapling full viewing key fingerprint" of a full viewing key with raw encoding *FVK* (as specified in [#sapling-spec]_ section 5.6.7) is given by: - * BLAKE2b-256("ZcashSaplingFVFP", *FVK*) + BLAKE2b-256("ZcashSaplingFVFP", *FVK*) It MAY be used to uniquely identify a particular Sapling full viewing key. @@ -333,7 +333,7 @@ Sprout Address Fingerprints and Tags A "Sprout address fingerprint" of a Sprout payment address with raw encoding *ADDR* (as specified in [#sapling-spec]_ section 5.6.3, including the lead bytes) is given by: - * BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*) + BLAKE2b-256("Zcash_Sprout_AFP", *ADDR*) It MAY be used to uniquely identify a particular Sprout payment address. @@ -357,7 +357,7 @@ A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *dept with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main`` for the production network, or ``secret-extended-key-main`` for the test network. @@ -369,7 +369,7 @@ A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *de with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production network, or ``zxviewtestsapling`` for the test network. @@ -381,7 +381,7 @@ A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with parent address tag *parent_addr_tag* and child number *i*, is represented as a byte sequence: - * I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in [#sapling-spec]_ section 5.6.8, including the lead bytes. From 918ea38834d95ebca2c2551336954b6e5880464e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 5 Jul 2018 17:11:59 +0100 Subject: [PATCH 23/52] Fix a cut-and-paste error. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 5db64af7..af5d0997 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -360,7 +360,7 @@ represented as a byte sequence: I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main`` -for the production network, or ``secret-extended-key-main`` for the test network. +for the production network, or ``secret-extended-key-test`` for the test network. Sapling extended full viewing keys ---------------------------------- From 0034331888e5aac0b9e028d20c306cf3daa56c9b Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:21:31 +0100 Subject: [PATCH 24/52] Add MUST NOT to Terminology. Signed-off-by: Daira Hopwood --- zip-0032.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index af5d0997..10a8c842 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -15,7 +15,8 @@ Terminology =========== -The key words "MUST" and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ +The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. +[#RFC2119]_ Abstract From d65629f7a1b8d15fe822e5629ed0ef586e2f408e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:22:23 +0100 Subject: [PATCH 25/52] Clarify the relation to existing use of BIPs 32 & 44. Signed-off-by: Daira Hopwood --- zip-0032.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 10a8c842..f5de5bab 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -30,8 +30,9 @@ components from a single seed. The second part defines an equivalent, but indepe components (which have a different internal construction). The third part shows how to use these trees in the context of existing BIP 44 [#bip-0044]_ wallets. -This specification is not intended to supplant the existing use by some Zcash wallets of BIP 32 and BIP 44 -for transparent Zcash addresses. +This specification complements the existing use by some Zcash wallets of BIP 32 and BIP 44 for transparent +Zcash addresses, and is not intended to deprecate that usage (privacy risks of using transparent addresses +notwithstanding). Motivation From 633436cff6544a7f9f986a806ef486c18b977c99 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:22:55 +0100 Subject: [PATCH 26/52] Specify that the seed MUST be at least 32 bytes. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index f5de5bab..1cdb14f3 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -134,7 +134,7 @@ is the normal Sapling full viewing key, *dk* is the same diversifier key as abov Master key generation --------------------- -Let *S* be a seed byte sequence of a chosen length. +Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 bytes. - Calculate *I* = BLAKE2b-512("ZcashIP32Sapling", *S*). - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . From 5788c120e7dd02dbcd7e189d90ed81c760ffee0d Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:23:23 +0100 Subject: [PATCH 27/52] Rename s_m to sk_m. Signed-off-by: Daira Hopwood --- zip-0032.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1cdb14f3..579dad67 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -138,16 +138,16 @@ Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 by - Calculate *I* = BLAKE2b-512("ZcashIP32Sapling", *S*). - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Use *I*\ :sub:`L` as the master spending key *s*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code +- Use *I*\ :sub:`L` as the master spending key *sk*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . - Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , *ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation [#sapling-key-components]_: - - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x00])) - - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x01])) - - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x02])) - - *dk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*s*\ :sub:`m`\ , [0x10])) + - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x00])) + - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x01])) + - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x02])) + - *dk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x10])) Child key derivation -------------------- From ba56f26b4d7774b01a385811ee15206ad1cd3299 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:24:14 +0100 Subject: [PATCH 28/52] Explain that some diversifiers are invalid, and correct the definition of default diversifier. Signed-off-by: Daira Hopwood --- zip-0032.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 579dad67..30768822 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -205,9 +205,13 @@ In order to reach the maximum possible diversifier range without running into th FF1-AES256 as a Pseudo-Random Permutation as follows: - Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1. -- *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*)) +- *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*)). -The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,0`\ . +A valid diversifier *d*\ :sub:`i,j` is one for which DiversifyHash(*d*\ :sub:`i,j`) ≠ ⊥. +For a given *dk*\ :sub:`i`\ , approximately half of the possible values of *j* yield valid diversifiers. + +The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,j`\ , where *j* is the +least nonnegative integer yielding a valid diversifier. Specification: Sprout key derivation From 7002be59fac0e5868428d3d21d2ea2353bdb0c2d Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:26:03 +0100 Subject: [PATCH 29/52] Clarify the interpretation of I_L in Sprout key derivation. This also fixes a cut-and-paste error (a child chain code is c_i, not c_m). Signed-off-by: Daira Hopwood --- zip-0032.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 30768822..7d88e47f 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -237,8 +237,11 @@ Let *S* be a seed byte sequence of a chosen length. - Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*). - Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ . -- Use *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m`\ , and *I*\ :sub:`R` as the master chain code - *c*\ :sub:`m`\ . +- Interpret *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m`\ by clearing the 4 most + significant bits of the first byte, and decoding the 32-byte result in the same way as for + *a*\ :sub:`sk`\ in the raw encoding of a Sprout spending key (excluding lead bytes) in + [#sapling-spec]_ section 5.6.8. +- Use *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . Child key derivation -------------------- @@ -251,8 +254,11 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Use *I*\ :sub:`L` as the child spending key *a*\ :sub:`sk,i`\ , and *I*\ :sub:`R` as the child chain code - *c*\ :sub:`m`\ . +- Interpret *I*\ :sub:`L` as the child spending key a\ :sub:`sk,i`\ by clearing the 4 most + significant bits of the first byte, and decoding the 32-byte result in the same way as for + *a*\ :sub:`sk`\ in the raw encoding of a Sprout spending key (excluding lead bytes) in + [#sapling-spec]_ section 5.6.8. +- Use *I*\ :sub:`R` as the child chain code *c*\ :sub:`i`\ . Specification: Wallet usage From 5881d3c211a64fa40b24b66f83c81dd6d05999d8 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:27:10 +0100 Subject: [PATCH 30/52] Define depth, parent tag, and i for master keys. Signed-off-by: Daira Hopwood --- zip-0032.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index 7d88e47f..a41c6087 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -371,6 +371,9 @@ represented as a byte sequence: I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* +For the master extended spending key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, +and *i* is 0. + When encoded as Bech32, the Human-Readable Part is ``secret-extended-key-main`` for the production network, or ``secret-extended-key-test`` for the test network. @@ -383,6 +386,9 @@ represented as a byte sequence: I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* +For the master extended full viewing key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, +and *i* is 0. + When encoded as Bech32, the Human-Readable Part is ``zxviews`` for the production network, or ``zxviewtestsapling`` for the test network. @@ -398,6 +404,9 @@ byte sequence: where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in [#sapling-spec]_ section 5.6.8, including the lead bytes. +For the master extended spending key, *depth* is 0, *parent_addr_tag* is 4 zero bytes, +and *i* is 0. + When encoded as Bech32, the Human-Readable Part is ``zxsprout`` for the production network, or ``zxtestsprout`` for the test network. Sprout extended spending keys are encoded using Bech32 even though other Sprout keys and addresses are encoded From ebecd8c1ffbce11fa610e09a1848db154e8318ce Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:28:45 +0100 Subject: [PATCH 31/52] Clarify the encoding of a_sk in a Sprout extended spending key. Also exclude lead bytes, and swap ASK and c for consistency with Sapling formats and BIP 32. Signed-off-by: Daira Hopwood --- zip-0032.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index a41c6087..fb574906 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -399,10 +399,10 @@ A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with parent address tag *parent_addr_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ASK* -where *ASK* is the raw encoding of the spending key *a*\ :sub:`sk` as specified in -[#sapling-spec]_ section 5.6.8, including the lead bytes. +where *ASK* is the 32-byte encoding of *a*\ :sub:`sk` in the raw encoding of a Sprout +spending key (excluding lead bytes) as specified in [#sapling-spec]_ section 5.6.8. For the master extended spending key, *depth* is 0, *parent_addr_tag* is 4 zero bytes, and *i* is 0. From 42506f08bdbbed1da7e209f30a4ba82ded9bec4f Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:36:25 +0100 Subject: [PATCH 32/52] Define DiversifyHash. Signed-off-by: Daira Hopwood --- zip-0032.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index fb574906..1c0093ee 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -84,6 +84,9 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J` \ is the order of the Jubjub large prime subgroup. +- DiversifyHash(*d*) maps a diversifier *d* to a base point on the Jubjub elliptic curve, or to ⊥ if the + diversifier is invalid. It is instantiated in [#sapling-spec]_ section 5.4.1.6. + The following algorithm standardized in [#NIST-SP-800-38G]_ is used: - FF1-AES256.Encrypt(*key*, *tweak*, *x*) refers to the FF1 encryption algorithm using AES with a From 6e9a79604c41accde1dc5943bdceb5a0efdcdd48 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 02:42:36 +0100 Subject: [PATCH 33/52] Cosmetics. Signed-off-by: Daira Hopwood --- zip-0032.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1c0093ee..61f2b876 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -240,9 +240,9 @@ Let *S* be a seed byte sequence of a chosen length. - Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*). - Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ . -- Interpret *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m`\ by clearing the 4 most +- Interpret *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m` \ by clearing the 4 most significant bits of the first byte, and decoding the 32-byte result in the same way as for - *a*\ :sub:`sk`\ in the raw encoding of a Sprout spending key (excluding lead bytes) in + *a*\ :sub:`sk` \ in the raw encoding of a Sprout spending key (excluding lead bytes) in [#sapling-spec]_ section 5.6.8. - Use *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . @@ -257,9 +257,9 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Interpret *I*\ :sub:`L` as the child spending key a\ :sub:`sk,i`\ by clearing the 4 most +- Interpret *I*\ :sub:`L` as the child spending key a\ :sub:`sk,i` \ by clearing the 4 most significant bits of the first byte, and decoding the 32-byte result in the same way as for - *a*\ :sub:`sk`\ in the raw encoding of a Sprout spending key (excluding lead bytes) in + *a*\ :sub:`sk` \ in the raw encoding of a Sprout spending key (excluding lead bytes) in [#sapling-spec]_ section 5.6.8. - Use *I*\ :sub:`R` as the child chain code *c*\ :sub:`i`\ . From 1b04d74cdef099427d9a0d0efc2ff9c04cf1c8b0 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 13:35:22 +0100 Subject: [PATCH 34/52] Remove unintended addition of a reference to the non-existant (yet) ZIP 173. Signed-off-by: Daira Hopwood --- zip-0032.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 61f2b876..6332b2ce 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -438,7 +438,6 @@ References .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ .. [#bip-0173] `BIP 173: Base32 address format for native v0-16 witness outputs `_ -.. [#zip-0173] `ZIP 173: Bech32 Format `_ .. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From 6f966489b87ac2960193517157e0a876081f4006 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 6 Jul 2018 13:49:24 +0100 Subject: [PATCH 35/52] Correct the derivation of a Sapling child full viewing key's nk, and define the bases G and H. Signed-off-by: Daira Hopwood --- zip-0032.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 6332b2ce..1c663108 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -181,6 +181,8 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub Deriving a child extended full viewing key `````````````````````````````````````````` +Let 𝓖 be as defined in [#sapling-spec]_ section 5.4.6.1 and let 𝓗 be as defined in [#sapling-key-components]_. + CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ , *c*\ :sub:`par`\ ), *i*) → (*ak*\ :sub:`i`\ , *nk*\ :sub:`i`\ , *ovk*\ :sub:`i`\ , *dk*\ :sub:`i`\ , *c*\ :sub:`i`\ ) @@ -194,8 +196,8 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - Let *I*\ :sub:`nsk` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x14])) - Return: - - *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] *G* + *ak*\ :sub:`par` - - *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] *G* + *nk*\ :sub:`par` + - *ak*\ :sub:`i` = [*I*\ :sub:`ask`\ ] 𝓖 + *ak*\ :sub:`par` + - *nk*\ :sub:`i` = [*I*\ :sub:`nsk`\ ] 𝓗 + *nk*\ :sub:`par` - *ovk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x15] || *ovk*\ :sub:`par`\ )) - *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ )) - *c*\ :sub:`i` = *I*\ :sub:`R` From 777d82a26f0cf1d1fce71c31d07ea0490b2f2edd Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 13 Jul 2018 03:13:06 +0100 Subject: [PATCH 36/52] Factor out the encoding of extended {spending key, full viewing key} parts and make it more precise. Signed-off-by: Daira Hopwood --- zip-0032.rst | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1c663108..7951f8c4 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -18,6 +18,8 @@ Terminology The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ +"Jubjub" refers to the elliptic curve defined in [#sapling-spec] section 5.4.8.3. + Abstract ======== @@ -73,6 +75,13 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - I2LEBSP\ :sub:`l`\ (*k*) is the sequence of *l* bits representing *k* in little-endian order. +- LEBS2OSP\ :sub:`l`\ (*B*) is defined as follows when *l* is a multiple of 8: convert each group of 8 bits + in *B* to a byte value with the least significant bit first, and concatenate the resulting bytes in the + same order as the groups. + +- repr\ :sub:`𝕁`\ (*P*) is the representation of the Jubjub elliptic curve point *P* as a bit sequence, + defined in [#sapling-spec]_ section 5.4.8.3. + - BLAKE2b-256(*p*, *x*) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string *p*, and input *x*. @@ -134,6 +143,13 @@ is the normal Sapling expanded spending key, *dk* is a diversifier key, and *c* We represent a Sapling extended full viewing key as (*ak*, *nk*, *ovk*, *dk*, *c*), where (*ak*, *nk*, *ovk*) is the normal Sapling full viewing key, *dk* is the same diversifier key as above, and *c* is the chain code. +Helper functions +---------------- + +Define EncodeXSKParts(*ask*, *nsk*, *ovk*, *dk*) := I2LEOSP\ :sub:`256`\ (*ask*) || I2LEOSP\ :sub:`256`\ (*nsk*) || *ovk* || *dk*. + +Define EncodeFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*. + Master key generation --------------------- @@ -165,8 +181,10 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || *ask*\ :sub:`par` || *nsk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || EncodeXSKParts(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + where (*nk*\ :sub:`par`\ , *ak*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) is the full viewing key derived from + (*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) as described in [#sapling-key-components]_. - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -189,7 +207,7 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || *ak*\ :sub:`par` || *nk*\ :sub:`par` || *ovk*\ :sub:`par` || *dk*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -374,7 +392,7 @@ A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *dept with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ask* || *nsk* || *ovk* || *dk* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeXSKParts(*ask*, *nsk*, *ovk*, *dk*) For the master extended spending key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, and *i* is 0. @@ -389,7 +407,7 @@ A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *de with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ak* || *nk* || *ovk* || *dk* + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeFVKParts(*ak*, *nk*, *ovk*, *dk*) For the master extended full viewing key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, and *i* is 0. From 3018efc0f39f7410216591b228309ec82780282a Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 13 Jul 2018 03:22:32 +0100 Subject: [PATCH 37/52] Correct the encoding of a_sk,par for Sprout child derivation. Signed-off-by: Daira Hopwood --- zip-0032.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 7951f8c4..b90d4350 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -273,7 +273,9 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *a*\ :sub:`sk,par` || I2LEOSP\ :sub:`32`\ (*i*)) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *ASK*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) + where *ASK*\ :sub:`par` is the encoding of *a*\ :sub:`sk,par` excluding lead bytes from + [#sapling-spec]_ section 5.6.8. - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . From 5cdc69196acc85b67d3d56e78099bf7bdb69b52b Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 13 Jul 2018 10:02:09 +0100 Subject: [PATCH 38/52] Factor out Sprout a_sk encoding/decoding into helper functions. Signed-off-by: Daira Hopwood --- zip-0032.rst | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index b90d4350..1d5d61ff 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -253,6 +253,15 @@ We therefore only define and derive Sprout extended spending keys. We represent a Sprout extended spending key as (*a*\ :sub:`sk`\ , *c*), where *a*\ :sub:`sk` is the normal Sprout spending key, and *c* is the chain code. +Helper functions +---------------- + +Let EncodeASK(*a*\ :sub:`sk`) be the 32-byte encoding of *a*\ :sub:`sk` in the raw encoding of a Sprout +spending key (excluding lead bytes) as specified in [#sapling-spec]_ section 5.6.8. + +Let DecodeASK(*ASK*) be the result of clearing the 4 most significant bits of the first byte of *ASK*, +and decoding the 32-byte result according to the inverse of EncodeASK. + Master key generation --------------------- @@ -260,10 +269,7 @@ Let *S* be a seed byte sequence of a chosen length. - Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*). - Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ . -- Interpret *I*\ :sub:`L` as the master spending key a\ :sub:`sk,m` \ by clearing the 4 most - significant bits of the first byte, and decoding the 32-byte result in the same way as for - *a*\ :sub:`sk` \ in the raw encoding of a Sprout spending key (excluding lead bytes) in - [#sapling-spec]_ section 5.6.8. +- Use DecodeASK(*I*\ :sub:`L`\ ) as the master spending key a\ :sub:`sk,m`\ . - Use *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . Child key derivation @@ -273,16 +279,11 @@ CDKsk((*a*\ :sub:`sk,par`\ , *c*\ :sub:`par`\ ), *i*) → (*a*\ :sub:`sk,i`\ , * - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || *ASK*\ :sub:`par` || I2LEOSP\ :sub:`32`\ (*i*)) - where *ASK*\ :sub:`par` is the encoding of *a*\ :sub:`sk,par` excluding lead bytes from - [#sapling-spec]_ section 5.6.8. + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x80] || EncodeASK(*a*\ :sub:`sk,par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - If not (normal child): return failure - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . -- Interpret *I*\ :sub:`L` as the child spending key a\ :sub:`sk,i` \ by clearing the 4 most - significant bits of the first byte, and decoding the 32-byte result in the same way as for - *a*\ :sub:`sk` \ in the raw encoding of a Sprout spending key (excluding lead bytes) in - [#sapling-spec]_ section 5.6.8. +- Use DecodeASK(*I*\ :sub:`L`\ ) as the child spending key a\ :sub:`sk,i`\ . - Use *I*\ :sub:`R` as the child chain code *c*\ :sub:`i`\ . @@ -424,10 +425,7 @@ A Sprout extended spending key (*a*\ :sub:`sk`\ , *c*), at depth *depth*, with parent address tag *parent_addr_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || *ASK* - -where *ASK* is the 32-byte encoding of *a*\ :sub:`sk` in the raw encoding of a Sprout -spending key (excluding lead bytes) as specified in [#sapling-spec]_ section 5.6.8. + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeASK(*a*\ :sub:`sk`\ ) For the master extended spending key, *depth* is 0, *parent_addr_tag* is 4 zero bytes, and *i* is 0. From eb60b41f20057a1918d6be909593c67610b6b01b Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Fri, 13 Jul 2018 10:21:50 +0100 Subject: [PATCH 39/52] Seeds for Sprout master keys must also be at least 32 bytes. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1d5d61ff..96e5f04a 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -265,7 +265,7 @@ and decoding the 32-byte result according to the inverse of EncodeASK. Master key generation --------------------- -Let *S* be a seed byte sequence of a chosen length. +Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 bytes. - Calculate *I* = BLAKE2b-512("ZcashIP32_Sprout", *S*). - Split *I* into two 32-byte sequences, I\ :sub:`L` and I\ :sub:`R`\ . From 511c2eb1e09393655e218012c3fefff1311a6fef Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 19 Jul 2018 16:01:04 +0100 Subject: [PATCH 40/52] Fix a link. Signed-off-by: Daira Hopwood --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 96e5f04a..1f89e36f 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -18,7 +18,7 @@ Terminology The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ -"Jubjub" refers to the elliptic curve defined in [#sapling-spec] section 5.4.8.3. +"Jubjub" refers to the elliptic curve defined in [#sapling-spec]_ section 5.4.8.3. Abstract From 813a8891d1374099d592bd5e2c3d29037460f4a7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Wed, 25 Jul 2018 14:48:33 +0100 Subject: [PATCH 41/52] Rename EncodeFVKParts to EncodeXFVKParts, since its input includes dk which is only part of an extended full viewing key. Signed-off-by: Daira Hopwood --- zip-0032.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1f89e36f..2c4bee24 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -148,7 +148,7 @@ Helper functions Define EncodeXSKParts(*ask*, *nsk*, *ovk*, *dk*) := I2LEOSP\ :sub:`256`\ (*ask*) || I2LEOSP\ :sub:`256`\ (*nsk*) || *ovk* || *dk*. -Define EncodeFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*. +Define EncodeXFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*. Master key generation --------------------- @@ -182,7 +182,7 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || EncodeXSKParts(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeXFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) where (*nk*\ :sub:`par`\ , *ak*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) is the full viewing key derived from (*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) as described in [#sapling-key-components]_. @@ -207,7 +207,7 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeXFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -410,7 +410,7 @@ A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *de with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeFVKParts(*ak*, *nk*, *ovk*, *dk*) + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeXFVKParts(*ak*, *nk*, *ovk*, *dk*) For the master extended full viewing key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, and *i* is 0. From 2aee30ca100c4a55d4dcaf7236214cbf650a8e7e Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sat, 1 Sep 2018 18:36:39 +0100 Subject: [PATCH 42/52] Use the same notation for r_J as the spec. --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 2c4bee24..5776360b 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -90,7 +90,7 @@ Most of the notation and functions used in this ZIP are defined in the Sapling p - PRF\ :sup:`expand`\ (*sk*, *t*) := BLAKE2b-512("Zcash_ExpandSeed", *sk* || *t*) -- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J` \ is the order +- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`𝕁`\ ), where *r*\ :sub:`𝕁` \ is the order of the Jubjub large prime subgroup. - DiversifyHash(*d*) maps a diversifier *d* to a base point on the Jubjub elliptic curve, or to ⊥ if the From 08b8427e9109b1e342cd05b5a65a2c6eab667367 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sat, 1 Sep 2018 18:39:08 +0100 Subject: [PATCH 43/52] Don't use 'X' to abbreviate 'extended', since it is ambiguous with 'expanded'. --- zip-0032.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 5776360b..1c9dc5e3 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -146,9 +146,9 @@ is the normal Sapling full viewing key, *dk* is the same diversifier key as abov Helper functions ---------------- -Define EncodeXSKParts(*ask*, *nsk*, *ovk*, *dk*) := I2LEOSP\ :sub:`256`\ (*ask*) || I2LEOSP\ :sub:`256`\ (*nsk*) || *ovk* || *dk*. +Define EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*) := I2LEOSP\ :sub:`256`\ (*ask*) || I2LEOSP\ :sub:`256`\ (*nsk*) || *ovk* || *dk*. -Define EncodeXFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*. +Define EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*) := LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*ak*)) || LEBS2OSP\ :sub:`256`\ (repr\ :sub:`𝕁`\ (*nk*)) || *ovk* || *dk*. Master key generation --------------------- @@ -181,8 +181,8 @@ CDKsk((*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || EncodeXSKParts(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeXFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If so (hardened child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x11] || EncodeExtSKParts(*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeExtFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) where (*nk*\ :sub:`par`\ , *ak*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) is the full viewing key derived from (*ask*\ :sub:`par`\ , *nsk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ ) as described in [#sapling-key-components]_. @@ -207,7 +207,7 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: - Check whether *i* ≥ 2\ :sup:`31` (whether the child is a hardened key). - If so (hardened child): return failure - - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeXFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) + - If not (normal child): let *I* = PRF\ :sup:`expand`\ (*c*\ :sub:`par`\ , [0x12] || EncodeExtFVKParts(*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub:`par`\ ) || I2LEOSP\ :sub:`32`\ (*i*)) - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Let *I*\ :sub:`ask` = ToScalar(PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x13])) @@ -395,7 +395,7 @@ A Sapling extended spending key (*ask*, *nsk*, *ovk*, *dk*, *c*), at depth *dept with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeXSKParts(*ask*, *nsk*, *ovk*, *dk*) + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeExtSKParts(*ask*, *nsk*, *ovk*, *dk*) For the master extended spending key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, and *i* is 0. @@ -410,7 +410,7 @@ A Sapling extended full viewing key (*ak*, *nk*, *ovk*, *dk*, *c*), at depth *de with parent full viewing key tag *parent_fvk_tag* and child number *i*, is represented as a byte sequence: - I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeXFVKParts(*ak*, *nk*, *ovk*, *dk*) + I2LEOSP\ :sub:`8`\ (*depth*) || *parent_fvk_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *c* || EncodeExtFVKParts(*ak*, *nk*, *ovk*, *dk*) For the master extended full viewing key, *depth* is 0, *parent_fvk_tag* is 4 zero bytes, and *i* is 0. From 2eec56d9367aafb95df4eb0298b668728f7728c7 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sat, 1 Sep 2018 18:39:41 +0100 Subject: [PATCH 44/52] Add specification for seed fingerprints. --- zip-0032.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/zip-0032.rst b/zip-0032.rst index 1c9dc5e3..10ffa734 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -379,6 +379,17 @@ A "Sprout address tag" is the first 4 bytes of the corresponding Sprout address intended for optimizing performance of address lookups, and MUST NOT be assumed to uniquely identify a particular address. +Seed Fingerprints +----------------- + +A "seed fingerprint" for the master seed *S* of a hierarchical deterministic wallet is given by: + + BLAKE2b-256("Zcash_HD_Seed_FP", *S*) + +It MAY be used to uniquely identify a particular hierarchical deterministic wallet. + +No corresponding short tag is defined. + Specification: Key Encodings ============================ From 55e3cd177eb0f81699075e29fc263a88c07ee850 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:25:12 +0100 Subject: [PATCH 45/52] Clarify wording about default payment addresses --- zip-0032.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 10ffa734..2a542fd7 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -328,9 +328,10 @@ ZIP 32 derivation MUST support the following path:: m_Sapling / purpose' / coin_type' / account' -Wallets MUST support generating the default payment address (corresponding to the default diversifier). They -MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the -user experience of giving a unique address to each recipient. +Furthermore, wallets MUST support generating the default payment address (corresponding to the default +diversifier as defined above) for any account they support. They MAY also support generating a stream of +payment addresses for a given account, if they wish to maintain the user experience of giving a unique +address to each recipient. Note that a given account can have a maximum of approximately 2\ :sup:`87` payment addresses, because each diversifier has around a 50% chance of being invalid. From a414e4e7d3cd3611de09fc980dc56b11503f47ee Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:37:55 +0100 Subject: [PATCH 46/52] Pull in definition of hardened notation --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index 2a542fd7..e35140b6 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -111,7 +111,7 @@ Implementors should note that this ZIP is consistently little-endian (in keeping specification), which is the opposite of BIP 32. We adapt the path notation of BIP 32 [#bip-0032]_ to describe shielded HD paths, using apostrophes to -indicate hardened derivation as in BIP 44 [#bip-0044]_: +indicate hardened derivation (i' = i + 2\ :sup:`31`\ ) as in BIP 44 [#bip-0044]_: - CDKsk(CDKsk(CDKsk(m\ :sub:`Sprout`\ , a'), b), c) is written as m\ :sub:`Sprout` / a' / b / c - CDKfvk(CDKfvk(CDKfvk(M\ :sub:`Sapling`\ , a), b), c) is written as M\ :sub:`Sapling` / a / b / c From 1f7b5120f1a514def37d079a4a77c7bcee801b11 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:38:54 +0100 Subject: [PATCH 47/52] Clarify that dk is not part of the standard Sapling derivation --- zip-0032.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index e35140b6..03e6f075 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -159,15 +159,20 @@ Let *S* be a seed byte sequence of a chosen length, which MUST be at least 32 by - Split *I* into two 32-byte sequences, *I*\ :sub:`L` and *I*\ :sub:`R`\ . - Use *I*\ :sub:`L` as the master spending key *sk*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code *c*\ :sub:`m`\ . -- Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , - *ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation +- Calculate *ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , and *ovk*\ :sub:`m` via the standard Sapling derivation [#sapling-key-components]_: - *ask*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x00])) - *nsk*\ :sub:`m` = ToScalar(PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x01])) - *ovk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x02])) + +- Calculate *dk*\ :sub:`m` similarly: + - *dk*\ :sub:`m` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*sk*\ :sub:`m`\ , [0x10])) +- Return (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ , *ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) as the + master extended spending key *m*\ :sub:`Sapling`\ . + Child key derivation -------------------- From 44e9c03d45183544c87a0c90349e807a9545a913 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:39:52 +0100 Subject: [PATCH 48/52] dk_i -> dk in "Diversifier derivation" section --- zip-0032.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 03e6f075..b848bf52 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -228,17 +228,17 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: Diversifier derivation ---------------------- -The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*\ :sub:`i`\ . +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. In order to reach the maximum possible diversifier range without running into the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows: - Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1. -- *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*)). +- *d*\ :sub:`j` = FF1-AES256.Encrypt(*dk*, "", I2LEBSP\ :sub:`88`\ (*j*)). -A valid diversifier *d*\ :sub:`i,j` is one for which DiversifyHash(*d*\ :sub:`i,j`) ≠ ⊥. -For a given *dk*\ :sub:`i`\ , approximately half of the possible values of *j* yield valid diversifiers. +A valid diversifier *d*\ :sub:`j` is one for which DiversifyHash(*d*\ :sub:`j`) ≠ ⊥. +For a given *dk*, approximately half of the possible values of *j* yield valid diversifiers. -The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,j`\ , where *j* is the +The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`j`\ , where *j* is the least nonnegative integer yielding a valid diversifier. From 606abd14e2b10ac5b1b1aa4ae8d1aefc0fdb8715 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:40:19 +0100 Subject: [PATCH 49/52] Be explicit about supported range for the Sapling key path --- zip-0032.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zip-0032.rst b/zip-0032.rst index b848bf52..47fa2011 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -329,7 +329,7 @@ relevant transactions. The above key path levels include an account identifier, which in all user interfaces is represented as a "bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling -ZIP 32 derivation MUST support the following path:: +ZIP 32 derivation MUST support the following path for any account in range {0..2\ :sup:`31`\ -1}:: m_Sapling / purpose' / coin_type' / account' From 888681c0b03ae89720fcaa85d5727998918509d1 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 18 Sep 2018 11:42:29 +0100 Subject: [PATCH 50/52] Update references to Sapling protocol spec --- zip-0032.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 47fa2011..1c860ceb 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -475,7 +475,7 @@ References .. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets `_ .. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 `_ .. [#bip-0173] `BIP 173: Base32 address format for native v0-16 witness outputs `_ -.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ -.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] `_ +.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling] `_ +.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-25 or later [Overwinter+Sapling] `_ .. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption `_ From cb1e6638362c464f6ad8c202cc9ab26db9976ad1 Mon Sep 17 00:00:00 2001 From: Ariel Date: Thu, 20 Sep 2018 12:11:13 +0300 Subject: [PATCH 51/52] Improve explanation of diversifier sequence choice --- zip-0032.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 1c860ceb..272742f0 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -228,8 +228,8 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: Diversifier derivation ---------------------- -The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. -In order to reach the maximum possible diversifier range without running into the birthday bound, we use +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. To prevent the diversifier leaking how many diversified addresses have already been generated for an account; we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. +In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows: - Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1. From 975a2aaa64780991ee51dfa16dff2c45fbdaf569 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 20 Sep 2018 11:03:24 +0100 Subject: [PATCH 52/52] Formatting --- zip-0032.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zip-0032.rst b/zip-0032.rst index 272742f0..b6f4e534 100644 --- a/zip-0032.rst +++ b/zip-0032.rst @@ -228,8 +228,10 @@ CDKfvk((*ak*\ :sub:`par`\ , *nk*\ :sub:`par`\ , *ovk*\ :sub:`par`\ , *dk*\ :sub: Diversifier derivation ---------------------- -The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. To prevent the diversifier leaking how many diversified addresses have already been generated for an account; we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. -In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use +The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*. To prevent the +diversifier leaking how many diversified addresses have already been generated for an account, we make the +sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the +maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows: - Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1.