ZIP: 32
Title: Shielded Hierarchical Deterministic Wallets
Owners: Jack Grigg <str4d@electriccoin.co>
Daira-Emma Hopwood <daira-emma@electriccoin.co>
Credits: Sean Bowe
Kris Nuttycombe
Ying Tong Lai
Pieter Wuille
Marek Palatinus
Pavol Rusnak
Status: Final
Category: Standards / Wallet
Created: 2018-05-22
License: MIT
Terminology
The key words "MUST", "MUST NOT", "SHOULD", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 14 1 when, and only when, they appear in all capitals.
"Jubjub" refers to the elliptic curve defined in 14.
A "cryptovalue" is a high-entropy value used in a cryptographic protocol that is not necessarily a key.
A "chain code" is a cryptovalue that is needed, in addition to a spending key, in order to derive descendant keys and addresses of that key.
The terms "Testnet" and "Mainnet" are to be interpreted as described in section 3.12 of the Zcash Protocol Specification 9.
Abstract
This proposal defines a mechanism for extending hierarchical deterministic wallets, as described in BIP 32 2, to support Zcash's shielded addresses.
The initial parts of the specification define (mostly) equivalent, but independent, systems for deriving a tree of key components from a single seed, for the following shielded pools (which have different internal key structures):
Sapling
Orchard
Previous versions of this document also defined a similar derivation system for the Sprout shielded pool. This has been removed since it was never used, and is unlikely to be used given that zcashd no longer generates Sprout addresses (and neither Zebra nor the mobile SDKs have ever done so).
The last part shows how to use these trees in the context of existing BIP 44 5 wallets.
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
BIP 32 2 is the standard mechanism by which wallets for Bitcoin and its derivatives (including Zcash's transparent addresses 6) 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 3) 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.
Viewing authority or spending 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 Zcash protocol specification 8. They are reproduced here for convenience:
truncatek(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ℓ(S)
is the integer in range
{0..2ℓ−1}
represented in little-endian order by the byte sequence
S
of length
ℓ/8
.
I2LEBSPℓ(k)
is the sequence of
ℓ
bits representing
k
in little-endian order.
LEBS2OSPℓ(B)
is defined as follows when
ℓ
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.
reprJ(P)
is the representation of the Jubjub elliptic curve point
P
as a bit sequence, defined in 14.
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
.
rJ
is the order of the Jubjub large prime subgroup.
rP
is the order of the Pallas curve.
ToScalarSapling(x):=LEOS2IP512(x)(modrJ)
.
ToScalarOrchard(x):=LEOS2IP512(x)(modrP)
.
DiversifyHashSapling(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 12.
The following algorithm standardized in 21 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ℓ(k)
is the byte sequence
S
of length
ℓ/8
representing in little-endian order the integer
k
in range
{0..2ℓ−1}
. It is the reverse operation of
LEOS2IPℓ(S)
.
Implementors should note that this ZIP is consistently little-endian (in keeping with the Sapling and Orchard specifications), which is the opposite of BIP 32.
We adapt the path notation of BIP 32 2 to describe shielded HD paths, using prime marks (
′
) to indicate hardened derivation (
i′=i+231
) as in BIP 44 5:
CKDfvk(CKDfvk(CKDfvk(mSapling,a),b),c)
is written as
mSapling/a/b/c
.
Note: no corresponding notation is currently defined for the result of Hardened-only child key derivation with non-zero
lead
and/or non-empty
tag
.
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.
Let
S
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.
Calculate
I=BLAKE2b-512(“ZcashIP32Sapling”,S)
.
Split
I
into two 32-byte sequences,
IL
and
IR
.
Use
IL
as the master spending key
skm
, and
IR
as the master chain code
cm
.
Calculate
askm
,
nskm
, and
ovkm
via the standard Sapling derivation 10:
askm=ToScalarSapling(PRFexpand(skm,[0x00]))
nskm=ToScalarSapling(PRFexpand(skm,[0x01]))
ovkm=truncate32(PRFexpand(skm,[0x02]))
.
Calculate
dkm
similarly:
dkm=truncate32(PRFexpand(skm,[0x10]))
.
Return
(askm,nskm,ovkm,dkm,cm)
as the master extended spending key
mSapling
.
Note that the master extended key is invalid if
askm
is
0
, or if the corresponding
ivk
derived as specified in 10 is
0
.
Sapling 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.
Check whether
i≥231
(whether the child is a hardened key).
If so (hardened child): let
I=PRFexpand(cpar,[0x11]∣∣EncodeExtSKParts(askpar,nskpar,ovkpar,dkpar)∣∣I2LEOSP32(i))
.
If not (normal child): let
I=PRFexpand(cpar,[0x12]∣∣EncodeExtFVKParts(akpar,nkpar,ovkpar,dkpar)∣∣I2LEOSP32(i))
where
(nkpar,akpar,ovkpar)
is the full viewing key derived from
(askpar,nskpar,ovkpar)
as described in 10.
Split
I
into two 32-byte sequences,
IL
and
IR
.
Let
Iask=ToScalarSapling(PRFexpand(IL,[0x13]))
.
Let
Insk=ToScalarSapling(PRFexpand(IL,[0x14]))
.
Return:
aski=(Iask+askpar)(modrJ)
nski=(Insk+nskpar)(modrJ)
ovki=truncate32(PRFexpand(IL,[0x15]∣∣ovkpar))
dki=truncate32(PRFexpand(IL,[0x16]∣∣dkpar))
ci=IR
.
Note that the child extended key is invalid if
aski
is
0
, or if the corresponding
ivk
derived as specified in 10 is
0
.
Deriving a child extended full viewing key
Let
GSapling
be as defined in 13 and let
HSapling
be as defined in 10.
Check whether
i≥231
(whether the child is a hardened key).
If so (hardened child): return failure.
If not (normal child): let
I=PRFexpand(cpar,[0x12]∣∣EncodeExtFVKParts(akpar,nkpar,ovkpar,dkpar)∣∣I2LEOSP32(i))
.
Split
I
into two 32-byte sequences,
IL
and
IR
.
Let
Iask=ToScalarSapling(PRFexpand(IL,[0x13]))
.
Let
Insk=ToScalarSapling(PRFexpand(IL,[0x14]))
.
Return:
aki=[Iask]GSapling+akpar
nki=[Insk]HSapling+nkpar
ovki=truncate32(PRFexpand(IL,[0x15]∣∣ovkpar))
dki=truncate32(PRFexpand(IL,[0x16]∣∣dkpar))
ci=IR
.
Note that the child extended key is invalid if
aki
is the zero point of Jubjub, or if the corresponding
ivk
derived as specified in 10 is
0
.
Sapling internal key derivation
The above derivation mechanisms produce external addresses suitable for giving out to senders. We also want to be able to produce another address derived from a given external address, for use by wallets for internal operations such as change and auto-shielding. Unlike BIP 44 that allows deriving a stream of external and internal addresses in the same hierarchical derivation tree 5, for any external full viewing key we only need to be able to derive a single internal full viewing key that has viewing authority for just internal transfers. We also need to be able to derive the corresponding internal spending key if we have the external spending key.
Deriving a Sapling internal spending key
Let
(ask,nsk,ovk,dk)
be the external spending key.
Derive the corresponding
ak
and
nk
as specified in 10.
Let
I=BLAKE2b-256(“Zcash_SaplingInt”,EncodeExtFVKParts(ak,nk,ovk,dk))
.
Let
Insk=ToScalarSapling(PRFexpand(I,[0x17]))
.
Let
R=PRFexpand(I,[0x18])
.
Let
nskinternal=(Insk+nsk)(modrJ)
.
Split
R
into two 32-byte sequences,
dkinternal
and
ovkinternal
.
Return the internal spending key as
(ask,nskinternal,ovkinternal,dkinternal)
.
Note that the child extended key is invalid if
ak
is the zero point of Jubjub, or if the corresponding
ivk
derived as specified in 10 is
0
.
Let
(ak,nk,ovk,dk)
be the external full viewing key.
Let
I=BLAKE2b-256(“Zcash_SaplingInt”,EncodeExtFVKParts(ak,nk,ovk,dk))
.
Let
Insk=ToScalarSapling(PRFexpand(I,[0x17]))
.
Let
R=PRFexpand(I,[0x18])
.
Let
nkinternal=[Insk]HSapling+nk
.
Split
R
into two 32-byte sequences,
dkinternal
and
ovkinternal
.
Return the internal full viewing key as
(ak,nkinternal,ovkinternal,dkinternal)
.
This design uses the same technique as non-hardened derivation to obtain a full viewing key with the same spend authority (the private key corresponding to
ak
) as the original, but viewing authority only for internal transfers.
The values of
I
,
Insk
, and
R
are the same between deriving a full viewing key, and deriving the corresponding spending key. Both of these derivations are shown in the following diagram:
Diagram of Sapling internal key derivation
(For simplicity, the proof authorizing key is not shown.)
This method of deriving internal keys is applied to external keys that are children of the Account level. It was implemented in zcashd as part of support for ZIP 316 23.
Note that the internal extended key is invalid if
ak
is the zero point of Jubjub, or if the corresponding
ivkinternal
derived from the internal full viewing key as specified in 10 is
0
.
Sapling 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 FF1-AES256 as a Pseudo-Random Permutation as follows:
Let
j
be the index of the desired diversifier, in the range
0..288−1
.
dj=FF1-AES256.Encrypt(dk,“”,I2LEBSP88(j))
.
A valid diversifier
dj
is one for which
DiversifyHashSapling(dj)=⊥
. 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
dj
, where
j
is the least nonnegative integer yielding a valid diversifier.
Specification: Hardened-only key derivation
The derivation mechanism for Sapling addresses specified above incurs significant complexity to support non-hardened derivation. In the several years since Sapling was deployed, we have seen no use cases for non-hardened derivation appear. With that in mind, we now have a general hardened-only derivation process that retains compatibility with existing derivation path semantics (to enable deriving the same path across multiple contexts).
The functions defined in this section are intended for internal use by context-specific mechanisms in subsequent sections, rather than for direct use.
Instantiation
Let
Context
be the context in which the hardened-only key derivation process is instantiated (e.g. a shielded protocol). We define two context-specific constants:
Context.MKGDomain
is a sequence of 16 bytes, used as a domain separator during master key generation. It SHOULD be disjoint from other domain separators used with BLAKE2b in Zcash protocols.
Context.CKDDomain
is a byte value, used as a domain separator during child key derivation. This should be tracked as part of the global set of domains defined for
PRFexpand
.
Hardened-only master key generation
Let
IKM
be an input key material byte sequence, which MUST use an unambiguous encoding within the given context, and SHOULD contain at least 256 bits of entropy. It is RECOMMENDED to use a prefix-free encoding, which may require the use of length fields if multiple fields need to be encoded.
MKGhContext(IKM)→(skm,cm)
:
Calculate
I=BLAKE2b-512(Context.MKGDomain,IKM)
.
Split
I
into two 32-byte sequences,
IL
and
IR
.
Use
IL
as the master secret key
skm
.
Use
IR
as the master chain code
cm
.
Return
(skm,cm)
.
Hardened-only child key derivation
As well as the integer child index
i
, the child key derivation function defined here supports a lead byte
lead
(used for domain separation) and byte sequence
tag
. Each triple
(i,lead,tag)
produces an independent output.
If
i<231
(non-hardened child index): return failure.
Let
lead_enc={[],[lead],if lead=0 and tag=[]otherwise.
Let
I=PRFexpand(cpar,[Context.CKDDomain]∣∣skpar∣∣I2LEOSP32(i)∣∣lead_enc∣∣tag)
.
Split
I
into two 32-byte sequences,
IL
and
IR
.
Return
(IL,IR)
.
Note that in the input to
PRFexpand
, the case
lead=0
and
tag=[]
is encoded in a way compatible with the definition of
CKDh
in previous versions of this specification (before
lead
and
tag
were added).
Specification: Orchard key derivation
We only support hardened key derivation for Orchard. We instantiate the hardened key generation process with the following constants:
Orchard.MKGDomain=“ZcashIP32Orchard”
Orchard.CKDDomain=0x81
Orchard extended keys
We represent an Orchard extended spending key as
(sk,c),
where
sk
is the normal Orchard spending key (opaque 32 bytes), and
c
is the chain code.
Orchard master key generation
Let
S
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.
Return
MKGhOrchard(S)
as the master extended spending key
mOrchard
.
Orchard child key derivation
CKDsk((skpar,cpar),i)→(ski,ci)
:
Return
CKDhOrchard((skpar,cpar),i,0,[])
Note that the resulting child spending key may produce an invalid external FVK, as specified in 11, with small probability. The corresponding internal FVK derived as specified in the next section may also be invalid with small probability.
Orchard internal key derivation
As in the case of Sapling, for a given external address, we want to produce another address for use by wallets for internal operations such as change and auto-shielding. That is, for any external full viewing key we need to be able to derive a single internal full viewing key that has viewing authority for just internal transfers. We also need to be able to derive the corresponding internal spending key if we have the external spending key.
Let
ask
be the spend authorizing key if available, and let
(ak,nk,rivk)
be the corresponding external full viewing key, obtained as specified in 11.
Define
DeriveInternalFVKOrchard(ak,nk,rivk)
as follows:
Let
K=I2LEBSP256(rivk)
.
Let
rivkinternal=ToScalarOrchard(PRFexpand(K,[0x83]∣∣I2LEOSP256(ak)∣∣I2LEOSP256(nk)))
.
Return
(ak,nk,rivkinternal)
.
The result of applying
DeriveInternalFVKOrchard
to the external full viewing key is the internal full viewing key. The corresponding expanded internal spending key is
(ask,nk,rivkinternal)
.
Unlike Sapling internal key derivation, we do not base this internal key derivation procedure on non-hardened derivation, which is not defined for Orchard. We can obtain the desired separation of viewing authority by modifying only the
rivkinternal
field relative to the external full viewing key, which results in different
dkinternal
,
ivkinternal
and
ovkinternal
fields being derived, as specified in 11 and shown in the following diagram:
Diagram of Orchard internal key derivation, also showing derivation from the parent extended spending key
This method of deriving internal keys is applied to external keys that are children of the Account level. It was implemented in zcashd as part of support for ZIP 316 23.
Note that the resulting FVK may be invalid, as specified in 11.
Orchard diversifier derivation
As with Sapling, we define a mechanism for deterministically deriving a sequence of diversifiers, without leaking how many diversified addresses have already been generated for an account. Unlike Sapling, we do so by deriving a diversifier key directly from the full viewing key, instead of as part of the extended spending key. This means that the full viewing key provides the capability to determine the position of a diversifier within the sequence, which matches the capabilities of a Sapling extended full viewing key but simplifies the key structure.
Given an Orchard extended spending key
(ski,ci)
:
Let
(ak,nk,rivk)
be the Orchard full viewing key for
ski
.
Let
j
be the index of the desired diversifier, in the range
0..288−1
.
di,j=FF1-AES256.Encrypt(dki,“”,I2LEBSP88(j))
.
Note that unlike Sapling, all Orchard diversifiers are valid, and thus all possible values of
j
yield valid diversifiers.
The default diversifier for
(ski,ci)
is defined to be
di,0.
Specification: Registered key derivation
In the context of a particular application protocol defined by a ZIP, there is sometimes a need to define an HD subtree that will not collide with keys derived for other protocols, as far as that is possible to assure by following the ZIP process 22.
Within this subtree, the application protocol may use derivation paths related to those used for existing key material — for example, to derive an account-level key. The following instantiation of the hardened key generation process may be used for this purpose.
It is strongly RECOMMENDED that implementors ensure that documentation of the context string(s), and the usage and derivation paths of the application protocol's key tree in the corresponding ZIP are substantially complete, before public deployment of software or hardware using this mechanism. The ZIP process allows for subsequent updates and corrections.
Let
ContextString
be a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
We instantiate the hardened key generation process with the following constants:
Registered.MKGDomain=“ZIPRegistered_KD”
Registered.CKDDomain=0xAC
Registered subtree root key generation
Let
S
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.
Note: The intermediate key
(skm,cm)
would grant the ability to derive the subtree root for application protocols defined in any ZIP using the same
ContextString
and seed. This is a potentially dangerous scope of grant since it cannot be known what future protocols will use this mechanism; therefore,
(skm,cm)
SHOULD NOT be used or stored directly without careful consideration of security consequences.
Registered child key derivation
As well as the integer child index
i
, the child key derivation function defined here supports a byte sequence
tag
; each pair
(i,tag)
produces a different child key. If an explicit tag is not required,
tag
is set to the empty byte sequence.
Note: The tag MUST use an unambiguous encoding within the given context. It is RECOMMENDED to use a prefix-free encoding, which may require the use of length fields if multiple fields need to be encoded.
CKDreg((skpar,cpar),i,tag)→(skchild,cchild)
:
Return
CKDhRegistered((skpar,cpar),i,0,tag)
.
Full-width child cryptovalue derivation
If the application protocol requires a 64-byte cryptovalue (for example, to avoid an entropy bottleneck in its subsequent operations), then a similar process to Registered child key derivation above can be used to obtain such a cryptovalue at a given child index; again with optional tag. The same considerations about encoding of the
tag
apply as above.
Let
(IL,IR)=CKDhRegistered((skpar,cpar),i,1,tag)
.
Return
IL∣∣IR
.
For the avoidance of doubt, the output of
derive_child_cryptovalue
MUST NOT be provided as input to any key derivation function defined in ZIP 32. In particular, it MUST NOT be reinterpreted directly or indirectly as an input to
CKDh
.
Specification: Ad-hoc key derivation (deprecated)
For compatibility with existing deployments, we also define a mechanism to derive ad-hoc key trees for private use by applications, without ecosystem coordination. This was called "arbitrary key derivation" in previous iterations of this ZIP, but that term caused confusion as to the applicability of the mechanism.
Since there is no guarantee of non-collision between different application protocols, and no way to tie these key trees to well-defined specification or documentation processes, use of this mechanism is NOT RECOMMENDED for new protocols.
Let
ContextString
be a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.
We instantiate the hardened key derivation process with the following constants:
Adhoc.MKGDomain=“ZcashArbitraryKD”
Adhoc.CKDDomain=0xAB
Ad-hoc master key generation (deprecated)
Let
S
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.
Note: a previous iteration of this ZIP suggested that, if
i
is the last element of an HD path (i.e. no extension of this path is used), then the concatenation
ski∣∣ci
could be used as a 64-bit key. This is NOT RECOMMENDED, because it is difficult to define safe APIs that enforce the restriction that a given node in the key tree must not be used both in this way and to derive further child keys. Full-width child cryptovalue derivation provides a safe way to obtain the same functionality for new application protocols.
Specification: Wallet usage
Existing Zcash-supporting HD wallets all use BIP 44 5 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
Sapling and Orchard 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 cryptocurrency 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 6. Note that in keeping with that document, all cryptocurrency testnets share
coin_type
index
1
.
account
: numbered from index
0
in sequentially increasing manner. Defined as in BIP 44 5.
Unlike BIP 44, none of the shielded key paths 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 for any account in range
{0..231−1}
:
mSapling/purpose′/coin_type′/account′
.
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
287
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 5:
zcashd version 4.6.0 and later uses this to derive "legacy" Sapling addresses from a mnemonic seed phrase under account
0x7FFFFFFF
, using hardened derivation for
address_index
.
Orchard key path
Orchard supports diversified addresses with the same spending authority (like Sapling). 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 Orchard ZIP 32 derivation MUST support the following path for any account in range
{0..231−1}
:
mOrchard/purpose′/coin_type′/account′
.
Furthermore, wallets MUST support generating the default payment address (corresponding to the default diversifier for Orchard) for any account they support. They MAY also support generating a stream of diversified payment addresses for a given account, if they wish to enable users to give a unique address to each recipient.
Note that a given account can have a maximum of
288
payment addresses (unlike Sapling, all Orchard diversifiers are valid).
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 17) 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.
Orchard Full Viewing Key Fingerprints and Tags
An "Orchard full viewing key fingerprint" of a full viewing key with raw encoding
FVK
(as specified in 19) is given by:
BLAKE2b-256(“ZcashOrchardFVFP”,FVK)
.
It MAY be used to uniquely identify a particular Orchard full viewing key.
An "Orchard full viewing key tag" is the first 4 bytes of the corresponding Orchard full viewing key fingerprint. It is intended for optimizing performance of key lookups, and MUST NOT be assumed to uniquely identify a particular key.
Seed Fingerprints
A "seed fingerprint" for the master seed
S
of a hierarchical deterministic wallet is given by:
BLAKE2b-256(“Zcash_HD_Seed_FP”,[length(S)]∣∣S)
.
It MAY be used to uniquely identify a particular hierarchical deterministic wallet.
No corresponding short tag is defined.
Note: a previous version of this specification did not have the length byte prefixing the seed. The current specification reflects the implementation in zcashd.
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 7 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:
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.
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:
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.
Orchard extended spending keys
An Orchard extended spending key
(sk,c)
, at depth
depth
, with parent full viewing key tag
parent_fvk_tag
and child number
i
, is represented as a byte sequence:
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-orchard-extsk-main for Mainnet, or secret-orchard-extsk-test for Testnet.
We define this encoding for completeness, however given that it includes the capability to derive child spending keys, we expect that most wallets will only expose the regular Orchard spending key encoding to users 20.
Values reserved due to previous specification for Sprout
The following values were previously used in the specification of hierarchical derivation for Sprout, and therefore SHOULD NOT be used in future Zcash-related specifications:
the
BLAKE2b-512
personalization
“ZcashIP32_Sprout”
, formerly specified for derivation of the master key of the Sprout tree;
the
BLAKE2b-256
personalization
“Zcash_Sprout_AFP”
, formerly specified for generation of Sprout address fingerprints;
the
PRFexpand
prefix
0x80
, formerly specified for Sprout child key derivation;
the Bech32 Human-Readable Parts zxsprout and zxtestsprout, formerly specified for Sprout extended spending keys on Mainnet and Testnet respectively.
Test Vectors
Test vectors are available at <https://github.com/zcash/zcash-test-vectors> in the sapling_zip32, sapling_zip32_hard, orchard_zip32, zip_0032_registered, and zip_0032_arbitrary files for each format.