mirror of https://github.com/zcash/zips.git
332 lines
16 KiB
ReStructuredText
332 lines
16 KiB
ReStructuredText
::
|
|
|
|
ZIP: 32
|
|
Title: Shielded Hierarchical Deterministic Wallets
|
|
Author: Jack Grigg <jack@z.cash>
|
|
Daira Hopwood <daira@z.cash>
|
|
Credits: Pieter Wuille <pieter.wuille@gmail.com>
|
|
Marek Palatinus <slush@satoshilabs.com>
|
|
Pavol Rusnak <stick@satoshilabs.com>
|
|
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 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.
|
|
|
|
- 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*.
|
|
|
|
- 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
|
|
of the Jubjub large prime subgroup.
|
|
|
|
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.
|
|
|
|
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]_:
|
|
|
|
- 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*, *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*, *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
|
|
---------------------
|
|
|
|
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`\ , *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]))
|
|
|
|
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`\ , *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`\ , [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]))
|
|
- 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`\ , [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`
|
|
|
|
Deriving a child extended full viewing key
|
|
``````````````````````````````````````````
|
|
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`\ , [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]))
|
|
- 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`\ , [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`
|
|
|
|
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
|
|
FF1-AES256 as a Pseudo-Random Permutation as follows:
|
|
|
|
- Let *j* be the index of the desired diversifier.
|
|
- *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`\ .
|
|
|
|
|
|
Specification: Sprout key derivation
|
|
====================================
|
|
|
|
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
|
|
--------------------
|
|
|
|
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` || I2LEOSP\ :sub:`32`\ (*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]_. 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. 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
|
|
----------------
|
|
|
|
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 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::
|
|
|
|
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 <https://tools.ietf.org/html/rfc2119>`_
|
|
.. [#bip-0032] `BIP 32: Hierarchical Deterministic Wallets <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki>`_
|
|
.. [#bip-0039] `BIP 39: Mnemonic code for generating deterministic keys <https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki>`_
|
|
.. [#bip-0043] `BIP 43: Purpose Field for Deterministic Wallets <https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki>`_
|
|
.. [#bip-0044] `BIP 44: Multi-Account Hierarchy for Deterministic Wallets <https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki>`_
|
|
.. [#slip-0044] `SLIP 44: Registered coin types for BIP-0044 <https://github.com/satoshilabs/slips/blob/master/slip-0044.md>`_
|
|
.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] <https://github.com/zcash/zips/blob/master/protocol/sapling.pdf>`_
|
|
.. [#sapling-key-components] `Section 4.2.2: Sapling Key Components. Zcash Protocol Specification, Version 2018.0-beta-20 [Overwinter+Sapling] <https://github.com/zcash/zips/blob/master/protocol/sapling.pdf>`_
|
|
.. [#NIST-SP-800-38G] `NIST Special Publication 800-38G -- Recommendation for Block Cipher Modes of Operation: Methods for Format-Preserving Encryption <https://dx.doi.org/10.6028/NIST.SP.800-38G>`_
|
|
|