Skip to content
ZIPs.tools

ZIP 32

Shielded Hierarchical Deterministic Wallets

  • Final
Proposal metadata
ID
32
Status
Final
Category
Standards / Wallet
Owners
  • Jack Grigg
  • Daira-Emma Hopwood
Created
2018-05-22
License
MIT
Contents
  1. Terminology
  2. Abstract
  3. Motivation
  4. Conventions
  5. Specification: Wallet seeds
  6. Rationale for the 256-bit entropy requirement
  7. Specification: Sapling key derivation
  8. Sapling extended keys
  9. Sapling helper functions
  10. Sapling master key generation
  11. Sapling child key derivation
  12. Sapling internal key derivation
  13. Sapling diversifier derivation
  14. Specification: Hardened-only key derivation
  15. Instantiation
  16. Hardened-only master key generation
  17. Hardened-only child key derivation
  18. Specification: Orchard key derivation
  19. Orchard extended keys
  20. Orchard master key generation
  21. Orchard child key derivation
  22. Orchard internal key derivation
  23. Orchard diversifier and OVK derivation
  24. Specification: Registered key derivation
  25. Registered subtree root key generation
  26. Registered child key derivation
  27. Full-width child cryptovalue derivation
  28. Specification: Ad-hoc key derivation (deprecated)
Preamble
ZIP
32
Title
Shielded Hierarchical Deterministic Wallets
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 141 when, and only when, they appear in all capitals.

"Jubjub" refers to the elliptic curve defined in2.

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 Specification3.

Abstract

This proposal defines a mechanism for extending hierarchical deterministic wallets, as described in BIP 32 4, 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 445 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 326 is the standard mechanism by which wallets for Bitcoin and its derivatives (including Zcash's transparent addresses7) 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 BIP 39 mnemonic8 or SLIP 39 shares 9) 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 10. They are reproduced here for convenience:

  • truncatek(S)\mathsf{truncate}_k(S) means the sequence formed from the first kk elements of SS.
  • a ∣∣ ba\,||\,b means the concatenation of sequences aa then bb.
  • [k]P[k] P means scalar multiplication of the elliptic curve point PP by the scalar kk.
  • LEOS2IPℓ(S)\mathsf{LEOS2IP}_\ell(S) is the integer in range {0 .. 2ℓ−1}\{ 0\,..\, 2^\ell - 1 \} represented in little-endian order by the byte sequence SS of length ℓ/8\ell/8.
  • I2LEBSPℓ(k)\mathsf{I2LEBSP}_\ell(k) is the sequence of ℓ\ell bits representing kk in little-endian order.
  • LEBS2OSPℓ(B)\mathsf{LEBS2OSP}_\ell(B) is defined as follows when ℓ\ell is a multiple of 88: convert each group of 8 bits in BB to a byte value with the least significant bit first, and concatenate the resulting bytes in the same order as the groups.
  • reprJ(P)\mathsf{repr}_\mathbb{J}(P) is the representation of the Jubjub elliptic curve point PP as a bit sequence, defined in11.
  • BLAKE2b-256(p,x)\mathsf{BLAKE2b}\textsf{-}\mathsf{256}(p, x) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string pp, and input xx.
  • BLAKE2b-512(p,x)\mathsf{BLAKE2b}\textsf{-}\mathsf{512}(p, x) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string pp, and input xx.
  • PRFexpand(sk,t):=\mathsf{PRF^{expand}}(\mathsf{sk}, t) := BLAKE2b-512(“Zcash_ExpandSeed”,\mathsf{BLAKE2b}\textsf{-}\mathsf{512}(\texttt{“Zcash\_ExpandSeed”}, sk ∣∣ t)\mathsf{sk}\,||\,t).
  • rJr_\mathbb{J} is the order of the Jubjub large prime subgroup.
  • rPr_\mathbb{P} is the order of the Pallas curve.
  • ToScalarSapling(x):=\mathsf{ToScalar^{Sapling}}(x) := LEOS2IP512(x)(modrJ)\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{J}}.
  • ToScalarOrchard(x):=\mathsf{ToScalar^{Orchard}}(x) := LEOS2IP512(x)(modrP)\mathsf{LEOS2IP}_{512}(x) \pmod{r_\mathbb{P}}.
  • DiversifyHashSapling(d)\mathsf{DiversifyHash^{Sapling}}(d) maps a diversifier dd to a base point on the Jubjub elliptic curve, or to ⊥\bot if the diversifier is invalid. It is instantiated in12.

The following algorithm standardized in13 is used:

  • FF1-AES256.Encrypt(key,tweak,x)\mathsf{FF1}\textsf{-}\mathsf{AES256.Encrypt}(key, tweak, x) refers to the FF1 encryption algorithm using AES with a 256-bit keykey, and parameters radix=2radix = 2, minlen=88minlen = 88, maxlen=88maxlen = 88. It will be used only with the empty string “”\texttt{“”} as the tweaktweak. xx is a sequence of 88 bits, as is the output.

We also define the following conversion function:

  • I2LEOSPℓ(k)\mathsf{I2LEOSP}_\ell(k) is the byte sequence SS of length ℓ/8\ell/8 representing in little-endian order the integer kk in range {0 .. 2ℓ−1}\{ 0\,..\, 2^\ell - 1 \}. It is the reverse operation of LEOS2IPℓ(S)\mathsf{LEOS2IP}_\ell(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 3214 to describe shielded HD paths, using prime marks (′)\textsf{(}\kern0.1em{}'\textsf{)} to indicate hardened derivation ( ⁣i′=i+231\!i' = i + 2^{31}) as in BIP 4415:

  • CKDfvk(CKDfvk(CKDfvk(mSapling,a),b),c)\mathsf{CKDfvk}(\mathsf{CKDfvk}(\mathsf{CKDfvk}(m_\mathsf{Sapling}, a), b), c) is written as mSapling/a/b/cm_\mathsf{Sapling} / a / b / c.

Note: no corresponding notation is currently defined for the result of Hardened-only child key derivation with non-zero lead\mathsf{lead} and/or non-empty tag\mathsf{tag}.

Specification: Wallet seeds

Several of the key derivation algorithms specified in this ZIP derive a master key from a seed byte sequence. Any such seed byte sequence MUST be at least 32 and at most 252 bytes.

The method of generating such a seed byte sequence for Zcash purposes MUST ensure that it has at least 256 bits of entropy. This requirement also applies to any mnemonic or input randomness used to obtain the seed byte sequence. See ZIP 31516 for further guidance.

Rationale for the 256-bit entropy requirement

Click to show/hide

Zcash consistently uses cryptovalues of length at or close to 256 bits, throughout its cryptographic design. Although the target security level for the protocol against classical cryptanalytic attacks is 21252^{125} (i.e. any such attack should take at least 21252^{125} operations, as explained in17), this does not imply that 128-bit keys or seeds are sufficient. The apparent gap between the security target and the key length is well motivated: it provides better resistance to attacks using parallel hardware 18 in the multi-user setting19; it takes into account small entropy losses in the key derivation process; and it simplifies the analysis of the protocol against quantum attacks for unknown addresses20, or in the context of a future post-quantum recovery protocol21.

In particular, for the hierarchical key derivation method described in this ZIP, if the seed or mnemonic has entropy less than 256 bits, it will be a weak link in the derivation of all keys belonging to that wallet.

It should be noted that an adversary can search for uses of lower-entropy mnemonics across multiple wallets simultaneously. They can collect a large set of (transparent or shielded) target addresses and/or viewing keys, and then perform a brute-force search over mnemonics in a lower-entropy subspace, efficiently checking whether the first few addresses or viewing keys that would be generated from each mnemonic match any of the targets.

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)(\mathsf{ask, nsk, ovk, dk, c}), where (ask,nsk,ovk)(\mathsf{ask, nsk, ovk}) is the normal Sapling expanded spending key, dk\mathsf{dk} is a diversifier key, and c\mathsf{c} is the chain code.

We represent a Sapling extended full viewing key as (ak,nk,ovk,dk,c)(\mathsf{ak, nk, ovk, dk, c}), where (ak,nk,ovk)(\mathsf{ak, nk, ovk}) is the normal Sapling full viewing key, dk\mathsf{dk} is the same diversifier key as above, and c\mathsf{c} is the chain code.

Sapling helper functions

Define

  • EncodeExtSKParts(ask,nsk,ovk,dk):=\mathsf{EncodeExtSKParts}(\mathsf{ask, nsk, ovk, dk}) := I2LEOSP256(ask)\mathsf{I2LEOSP}_{256}(\mathsf{ask}) ∣∣ I2LEOSP256(nsk)||\,\mathsf{I2LEOSP}_{256}(\mathsf{nsk}) ∣∣ ovk||\,\mathsf{ovk} ∣∣ dk||\,\mathsf{dk}
  • EncodeExtFVKParts(ak,nk,ovk,dk):=\mathsf{EncodeExtFVKParts}(\mathsf{ak, nk, ovk, dk}) := LEBS2OSP256(reprJ(ak))\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{ak})) ∣∣ LEBS2OSP256(reprJ(nk))||\,\mathsf{LEBS2OSP}_{256}(\mathsf{repr}_\mathbb{J}(\mathsf{nk})) ∣∣ ovk||\,\mathsf{ovk} ∣∣ dk||\,\mathsf{dk}

Sapling master key generation

Let SS be a seed byte sequence meeting the requirements in Specification: Wallet seeds.

  • Calculate I=BLAKE2b-512(“ZcashIP32Sapling”,S)I = \mathsf{BLAKE2b}\textsf{-}\mathsf{512}(\texttt{“ZcashIP32Sapling”}, S).
  • Split II into two 32-byte sequences, ILI_L and IRI_R.
  • Use ILI_L as the master spending key skm\mathsf{sk}_m, and IRI_R as the master chain code cm\mathsf{c}_m.
  • Calculate askm\mathsf{ask}_m, nskm\mathsf{nsk}_m, and ovkm\mathsf{ovk}_m via the standard Sapling derivation22:
    • askm=ToScalarSapling(PRFexpand(skm,[0x00]))\mathsf{ask}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x00}]))
    • nskm=ToScalarSapling(PRFexpand(skm,[0x01]))\mathsf{nsk}_m = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x01}]))
    • ovkm=truncate32(PRFexpand(skm,[0x02]))\mathsf{ovk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x02}])).
  • Calculate dkm\mathsf{dk}_m similarly:
    • dkm=truncate32(PRFexpand(skm,[0x10]))\mathsf{dk}_m = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(\mathsf{sk}_m, [\mathtt{0x10}])).
  • Return (askm,nskm,ovkm,dkm,cm)(\mathsf{ask}_m, \mathsf{nsk}_m, \mathsf{ovk}_m, \mathsf{dk}_m, \mathsf{c}_m) as the master extended spending key mSaplingm_\mathsf{Sapling}.

Note that the master extended key is invalid if askm\mathsf{ask}_m is 00, or if the corresponding ivk\mathsf{ivk} derived as specified in23 is 00.

Sapling child key derivation

As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index ii, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.

Deriving a child extended spending key

CKDsk((askpar,nskpar,ovkpar,dkpar,cpar),i)\mathsf{CKDsk}((\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) →(aski,nski,ovki,dki,ci)\rightarrow (\mathsf{ask}_i, \mathsf{nsk}_i, \mathsf{ovk}_i, \mathsf{dk}_i, \mathsf{c}_i) :

  • Check whether i≥231i \geq 2^{31} (whether the child is a hardened key).
    • If so (hardened child): let I=PRFexpand(cpar,[0x11]I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{0x11}] ∣∣ EncodeExtSKParts(askpar,nskpar,ovkpar,dkpar)||\,\mathsf{EncodeExtSKParts}(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}) ∣∣ I2LEOSP32(i))||\,\mathsf{I2LEOSP}_{32}(i)).
    • If not (normal child): let I=PRFexpand(cpar,[0x12]I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{0x12}] ∣∣ EncodeExtFVKParts(akpar,nkpar,ovkpar,dkpar)||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}) ∣∣ I2LEOSP32(i))||\,\mathsf{I2LEOSP}_{32}(i)) where (nkpar,akpar,ovkpar)(\mathsf{nk}_{par}, \mathsf{ak}_{par}, \mathsf{ovk}_{par}) is the full viewing key derived from (askpar,nskpar,ovkpar)(\mathsf{ask}_{par}, \mathsf{nsk}_{par}, \mathsf{ovk}_{par}) as described in24.
  • Split II into two 32-byte sequences, ILI_L and IRI_R.
  • Let Iask=ToScalarSapling(PRFexpand(IL,[0x13]))I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x13}])).
  • Let Insk=ToScalarSapling(PRFexpand(IL,[0x14]))I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}])).
  • Return:
    • aski=(Iask+askpar)(modrJ)\mathsf{ask}_i = (I_\mathsf{ask} + \mathsf{ask}_{par}) \pmod{r_\mathbb{J}}
    • nski=(Insk+nskpar)(modrJ)\mathsf{nsk}_i = (I_\mathsf{nsk} + \mathsf{nsk}_{par}) \pmod{r_\mathbb{J}}
    • ovki=truncate32(PRFexpand(IL,[0x15]\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x15}] ∣∣ ovkpar))||\,\mathsf{ovk}_{par}))
    • dki=truncate32(PRFexpand(IL,[0x16]\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}] ∣∣ dkpar))||\,\mathsf{dk}_{par}))
    • ci=IR\mathsf{c}_i = I_R.

Note that the child extended key is invalid if aski\mathsf{ask}_i is 00, or if the corresponding ivk\mathsf{ivk} derived as specified in25 is 00.

Deriving a child extended full viewing key

Let GSapling\mathcal{G}^\mathsf{Sapling} be as defined in26 and let HSapling\mathcal{H}^\mathsf{Sapling} be as defined in27.

CKDfvk((akpar,nkpar,ovkpar,dkpar,cpar),i)\mathsf{CKDfvk}((\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}, \mathsf{c}_{par}), i) →(aki,nki,ovki,dki,ci)\rightarrow (\mathsf{ak}_{i}, \mathsf{nk}_{i}, \mathsf{ovk}_{i}, \mathsf{dk}_{i}, \mathsf{c}_{i}) :

  • Check whether i≥231i \geq 2^{31} (whether the child is a hardened key).
    • If so (hardened child): return failure.
    • If not (normal child): let I=PRFexpand(cpar,[0x12]I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathtt{0x12}] ∣∣ EncodeExtFVKParts(akpar,nkpar,ovkpar,dkpar)||\,\mathsf{EncodeExtFVKParts}(\mathsf{ak}_{par}, \mathsf{nk}_{par}, \mathsf{ovk}_{par}, \mathsf{dk}_{par}) ∣∣ I2LEOSP32(i))||\,\mathsf{I2LEOSP}_{32}(i)).
  • Split II into two 32-byte sequences, ILI_L and IRI_R.
  • Let Iask=ToScalarSapling(PRFexpand(IL,[0x13]))I_\mathsf{ask} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x13}])).
  • Let Insk=ToScalarSapling(PRFexpand(IL,[0x14]))I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x14}])).
  • Return:
    • aki=[Iask] GSapling+akpar\mathsf{ak}_i = [I_\mathsf{ask}]\,\mathcal{G}^\mathsf{Sapling} + \mathsf{ak}_{par}
    • nki=[Insk] HSapling+nkpar\mathsf{nk}_i = [I_\mathsf{nsk}]\,\mathcal{H}^\mathsf{Sapling} + \mathsf{nk}_{par}
    • ovki=truncate32(PRFexpand(IL,[0x15]\mathsf{ovk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x15}] ∣∣ ovkpar))||\,\mathsf{ovk}_{par}))
    • dki=truncate32(PRFexpand(IL,[0x16]\mathsf{dk}_i = \mathsf{truncate}_{32}(\mathsf{PRF^{expand}}(I_L, [\mathtt{0x16}] ∣∣ dkpar))||\,\mathsf{dk}_{par}))
    • ci=IR\mathsf{c}_i = I_R.

Note that the child extended key is invalid if aki\mathsf{ak}_i is the zero point of Jubjub, or if the corresponding ivk\mathsf{ivk} derived as specified in28 is 00.

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 tree29, 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)(\mathsf{ask}, \mathsf{nsk}, \mathsf{ovk}, \mathsf{dk}) be the external spending key.

  • Derive the corresponding ak\mathsf{ak} and nk\mathsf{nk} as specified in30.
  • Let I=BLAKE2b-256(“Zcash_SaplingInt”,EncodeExtFVKParts(ak,nk,ovk,dk))I = \textsf{BLAKE2b-256}(\texttt{“Zcash\_SaplingInt”}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})).
  • Let Insk=ToScalarSapling(PRFexpand(I,[0x17]))I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}])).
  • Let R=PRFexpand(I,[0x18])R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}]).
  • Let nskinternal=(Insk+nsk)(modrJ)\mathsf{nsk_{internal}} = (I_\mathsf{nsk} + \mathsf{nsk}) \pmod{r_\mathbb{J}}.
  • Split RR into two 32-byte sequences, dkinternal\mathsf{dk_{internal}} and ovkinternal\mathsf{ovk_{internal}}.
  • Return the internal spending key as (ask,nskinternal,ovkinternal,dkinternal)(\mathsf{ask}, \mathsf{nsk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}}).

Note that the child extended key is invalid if ak\mathsf{ak} is the zero point of Jubjub, or if the corresponding ivk\mathsf{ivk} derived as specified in31 is 00.

Deriving a Sapling internal full viewing key

Let HSapling\mathcal{H}^\mathsf{Sapling} be as defined in32.

Let (ak,nk,ovk,dk)(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk}) be the external full viewing key.

  • Let I=BLAKE2b-256(“Zcash_SaplingInt”,EncodeExtFVKParts(ak,nk,ovk,dk))I = \textsf{BLAKE2b-256}(\texttt{“Zcash\_SaplingInt”}, \mathsf{EncodeExtFVKParts}(\mathsf{ak}, \mathsf{nk}, \mathsf{ovk}, \mathsf{dk})).
  • Let Insk=ToScalarSapling(PRFexpand(I,[0x17]))I_\mathsf{nsk} = \mathsf{ToScalar^{Sapling}}(\mathsf{PRF^{expand}}(I, [\mathtt{0x17}])).
  • Let R=PRFexpand(I,[0x18])R = \mathsf{PRF^{expand}}(I, [\mathtt{0x18}]).
  • Let nkinternal=[Insk]HSapling+nk\mathsf{nk_{internal}} = [I_\mathsf{nsk}] \mathcal{H}^\mathsf{Sapling} + \mathsf{nk}.
  • Split RR into two 32-byte sequences, dkinternal\mathsf{dk_{internal}} and ovkinternal\mathsf{ovk_{internal}}.
  • Return the internal full viewing key as (ak,nkinternal,ovkinternal,dkinternal)(\mathsf{ak}, \mathsf{nk_{internal}}, \mathsf{ovk_{internal}}, \mathsf{dk_{internal}}).

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\mathsf{ak}) as the original, but viewing authority only for internal transfers.

The values of II, InskI_\mathsf{nsk}, and RR 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 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 31633.

Note that the internal extended key is invalid if ak\mathsf{ak} is the zero point of Jubjub, or if the corresponding ivkinternal\mathsf{ivk_{internal}} derived from the internal full viewing key as specified in34 is 00.

Sapling diversifier derivation

The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key dk\mathsf{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 jj be the index of the desired diversifier, in the range 0 .. 288−10\,..\, 2^{88} - 1.
  • dj=FF1-AES256.Encrypt(dk,“”,I2LEBSP88(j))d_j = \mathsf{FF1}\textsf{-}\mathsf{AES256.Encrypt}(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j)).

A valid diversifier djd_j is one for which DiversifyHashSapling(dj)≠⊥\mathsf{DiversifyHash^{Sapling}}(d_j) \neq \bot. For a given dk\mathsf{dk}, approximately half of the possible values of jj yield valid diversifiers.

The default diversifier for a Sapling extended key is defined to be djd_j, where jj 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\mathsf{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\mathsf{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\mathsf{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\mathsf{PRF^{expand}}.

Hardened-only master key generation

Let IKM\mathsf{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)\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m) :

  • Calculate I=BLAKE2b-512(Context.MKGDomain,IKM)I = \mathsf{BLAKE2b}\textsf{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM}).
  • Split II into two 32-byte sequences, ILI_L and IRI_R.
  • Use ILI_L as the master secret key skm\mathsf{sk}_m.
  • Use IRI_R as the master chain code cm\mathsf{c}_m.
  • Return (skm,cm)(\mathsf{sk}_m, \mathsf{c}_m).

Hardened-only child key derivation

As well as the integer child index ii, the child key derivation function defined here supports a lead byte lead\mathsf{lead} (used for domain separation) and byte sequence tag\mathsf{tag}. Each triple (i,lead,tag)(i, \mathsf{lead}, \mathsf{tag}) produces an independent output.

CKDhContext((skpar,cpar),i,lead,tag)\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, \mathsf{lead}, \mathsf{tag}) →(skchild,cchild)\rightarrow (\mathsf{sk}_{child}, \mathsf{c}_{child}) :

  • If i<231i < 2^{31} (non-hardened child index): return failure.
  • Let lead_enc={ [ ], ⁣ ⁣if lead=0 and tag=[ ] [lead], ⁣ ⁣otherwise.\mathsf{lead\_enc} = \begin{cases} \,[\,],&\!\!\textsf{if } \mathsf{lead} = 0 \textsf{ and } \mathsf{tag} = [\,] \\ \,[\mathsf{lead}],&\!\!\textsf{otherwise.}\end{cases}
  • Let I=PRFexpand(cpar,[Context.CKDDomain] ∣∣ skpar ∣∣ I2LEOSP32(i) ∣∣ lead_enc ∣∣ tag)I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\mathsf{Context.CKDDomain}]\,||\,\mathsf{sk}_{par}\,||\,\mathsf{I2LEOSP}_{32}(i)\,||\,\mathsf{lead\_enc}\,||\,\mathsf{tag}).
  • Split II into two 32-byte sequences, ILI_L and IRI_R.
  • Return (IL,IR)(I_L, I_R).

Note that in the input to PRFexpand\mathsf{PRF^{expand}}, the case lead=0\mathsf{lead} = 0 and tag=[ ]\mathsf{tag} = [\,] is encoded in a way compatible with the definition of CKDh\mathsf{CKDh} in previous versions of this specification (before lead\mathsf{lead} and tag\mathsf{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”\mathsf{Orchard.MKGDomain} = \texttt{“ZcashIP32Orchard”}
  • Orchard.CKDDomain=0x81\mathsf{Orchard.CKDDomain} = \mathtt{0x81}

Orchard extended keys

We represent an Orchard extended spending key as (sk,c)(\mathsf{sk, c}), where sk\mathsf{sk} is the normal Orchard spending key (opaque 32 bytes), and c\mathsf{c} is the chain code.

Orchard master key generation

Let SS be a seed byte sequence meeting the requirements in Specification: Wallet seeds.

  • Return MKGhOrchard(S)\mathsf{MKGh}^\mathsf{Orchard}(S) as the master extended spending key mOrchardm_\mathsf{Orchard}.

Orchard child key derivation

CKDsk((skpar,cpar),i)\mathsf{CKDsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i) →(ski,ci)\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i) :

  • Return CKDhOrchard((skpar,cpar),i,0,[ ])\mathsf{CKDh}^\mathsf{Orchard}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, 0, [\,])

Note that the resulting child spending key may produce an invalid external FVK, as specified in35, 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\mathsf{ask} be the spend authorizing key if available, and let (ak,nk,rivk)(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk}) be the corresponding external full viewing key, obtained as specified in36.

Define DeriveInternalFVKOrchard(ak,nk,rivk)\mathsf{DeriveInternalFVK^{Orchard}}(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk}) as follows:

  • Let K=I2LEBSP256(rivk)K = \mathsf{I2LEBSP}_{256}(\mathsf{rivk}).
  • Let rivkinternal=ToScalarOrchard(PRFKexpand([0x83] ∣∣ I2LEOSP256(ak) ∣∣ I2LEOSP256(nk)))\mathsf{rivk_{internal}} = \mathsf{ToScalar^{Orchard}}\big(\mathsf{PRF}^{\mathsf{expand}}_{K}\big([\mathtt{0x83}] \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{ak}) \,||\, \mathsf{I2LEOSP_{256}}(\mathsf{nk})\kern-0.1em\big)\kern-0.15em\big).
  • Return (ak,nk,rivkinternal)(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk_{internal}}).

The result of applying DeriveInternalFVKOrchard\mathsf{DeriveInternalFVK^{Orchard}} to the external full viewing key is the internal full viewing key. The corresponding expanded internal spending key is (ask,nk,rivkinternal)(\mathsf{ask}, \mathsf{nk}, \mathsf{rivk_{internal}}).

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\mathsf{rivk_{internal}} field relative to the external full viewing key, which results in different dkinternal\mathsf{dk_{internal}}, ivkinternal\mathsf{ivk_{internal}} and ovkinternal\mathsf{ovk_{internal}} fields being derived, as specified in37 and shown in the following diagram:

Diagram of Orchard internal key derivation, also showing derivation from the parent extended spending key 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 31638.

Note that the resulting FVK may be invalid, as specified in39.

Orchard diversifier and OVK 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.

Let DeriveDkAndOvkOrchard\mathsf{DeriveDkAndOvk^{Orchard}} be as defined in40.

Given an Orchard full viewing key (ak,nk,rivk)(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk}) (which may be either external or internal):

  • (dk,ovk)=DeriveDkAndOvkOrchard(rivk,ak,nk)(\mathsf{dk}, \mathsf{ovk}) = \mathsf{DeriveDkAndOvk^{Orchard}}(\mathsf{rivk}, \mathsf{ak}, \mathsf{nk}).
  • Let jj be the index of the desired diversifier, in the range 0 .. 288−10\,..\, 2^{88} - 1.
  • dj=FF1-AES256.Encrypt(dk,“”,I2LEBSP88(j))\mathsf{d}_j = \mathsf{FF1}\textsf{-}\mathsf{AES256.Encrypt}\big(\mathsf{dk}, \texttt{“”}, \mathsf{I2LEBSP}_{88}(j)\kern-0.1em\big).

Note that unlike Sapling, all Orchard diversifiers are valid, and thus all possible values of jj yield valid diversifiers.

The default diversifier for (ak,nk,rivk)(\mathsf{ak}, \mathsf{nk}, \mathsf{rivk}) is defined to be d0\mathsf{d}_0.

No mechanism is provided to derive distinct Outgoing Viewing Keys ( ⁣ovk\!\mathsf{ovk}) for each diversified address. This is because payments are sent from accounts (with external or internal scope), not from specific diversified addresses41.

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 process42.

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\mathsf{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”\mathsf{Registered.MKGDomain} = \texttt{“ZIPRegistered\_KD”}
  • Registered.CKDDomain=0xAC\mathsf{Registered.CKDDomain} = \mathtt{0xAC}

Registered subtree root key generation

Let SS be a seed byte sequence meeting the requirements in Specification: Wallet seeds.

The registered subtree root is obtained as:

RegKD(ContextString,S,ZipNumber)\mathsf{RegKD}(\mathsf{ContextString}, \mathsf{S}, \mathsf{ZipNumber}) →(sksubtree,csubtree)\rightarrow (\mathsf{sk}_{subtree}, \mathsf{c}_{subtree}) :

  • Let (skm,cm)=MKGhRegistered([length(ContextString)] ∣∣ ContextString ∣∣ [length(S)] ∣∣ S)(\mathsf{sk}_{m}, \mathsf{c}_{m}) = \mathsf{MKGh}^\mathsf{Registered}([\mathsf{length}(\mathsf{ContextString})]\,||\,\mathsf{ContextString}\,||\,[\mathsf{length}(S)]\,||\,S).
  • Return CKDhRegistered((skm,cm),ZipNumber+231,0,[ ])\mathsf{CKDh}^\mathsf{Registered}((\mathsf{sk}_{m}, \mathsf{c}_{m}), \mathsf{ZipNumber} + 2^{31}, 0, [\,]).

Note: The intermediate key (skm,cm)(\mathsf{sk}_{m}, \mathsf{c}_{m}) would grant the ability to derive the subtree root for application protocols defined in any ZIP using the same ContextString\mathsf{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)(\mathsf{sk}_{m}, \mathsf{c}_{m}) SHOULD NOT be used or stored directly without careful consideration of security consequences.

Registered child key derivation

As well as the integer child index ii, the child key derivation function defined here supports a byte sequence tag\mathsf{tag}; each pair (i,tag)(i, \mathsf{tag}) produces a different child key. If an explicit tag is not required, tag\mathsf{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)\mathsf{CKDreg}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, \mathsf{tag}) →(skchild,cchild)\rightarrow (\mathsf{sk}_{child}, \mathsf{c}_{child}) :

  • Return CKDhRegistered((skpar,cpar),i,0,tag)\mathsf{CKDh}^\mathsf{Registered}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, 0, \mathsf{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\mathsf{tag} apply as above.

derive_child_cryptovalue((skpar,cpar),i,tag)\mathsf{derive\_child\_cryptovalue}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, \mathsf{tag}) →Kchild\rightarrow \mathsf{K}_{child} :

  • Let (IL,IR)=CKDhRegistered((skpar,cpar),i,1,tag)(I_L, I_R) = \mathsf{CKDh}^\mathsf{Registered}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i, 1, \mathsf{tag}).
  • Return IL ∣∣ IRI_L\,||\,I_R.

For the avoidance of doubt, the output of derive_child_cryptovalue\mathsf{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\mathsf{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\mathsf{ContextString} be a globally-unique non-empty sequence of at most 252 bytes that identifies the desired context.

Citation graph

Hover or tap a node to see its title and citations.
Loading citation graph…