Skip to content

Commit

Permalink
Render manually, while the CI-based rendering is broken
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Oct 1, 2024
1 parent f14fc99 commit b4682c1
Showing 1 changed file with 125 additions and 24 deletions.
149 changes: 125 additions & 24 deletions rendered/zip-0032.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<span class="math">\(% This ZIP makes heavy use of mathematical markup. If you can see this, you may want to instead view the rendered version at https://zips.z.cash/zip-0032 .\)</span>
</p>
<section id="terminology"><h2><span class="section-heading">Terminology</span><span class="section-anchor"> <a rel="bookmark" href="#terminology"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in BCP 14 <a id="footnote-reference-1" class="footnote_reference" href="#bcp14">1</a> when, and only when, they appear in all capitals.</p>
<p>The key words "MUST", "MUST NOT", "SHOULD", "RECOMMENDED", and "MAY" in this document are to be interpreted as described in BCP 14 <a id="footnote-reference-1" class="footnote_reference" href="#bcp14">1</a> when, and only when, they appear in all capitals.</p>
<p>"Jubjub" refers to the elliptic curve defined in <a id="footnote-reference-2" class="footnote_reference" href="#protocol-jubjub">15</a>.</p>
<p>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.</p>
<p>The terms "Testnet" and "Mainnet" are to be interpreted as described in section 3.12 of the Zcash Protocol Specification <a id="footnote-reference-3" class="footnote_reference" href="#protocol-networks">10</a>.</p>
Expand Down Expand Up @@ -578,24 +578,33 @@
is the least nonnegative integer yielding a valid diversifier.</p>
</section>
</section>
<section id="specification-orchard-key-derivation"><h2><span class="section-heading">Specification: Orchard key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#specification-orchard-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>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 only support hardened key derivation for Orchard.</p>
<section id="orchard-extended-keys"><h3><span class="section-heading">Orchard extended keys</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-extended-keys"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>We represent an Orchard extended spending key as
<span class="math">\((\mathsf{sk, c}),\)</span>
where
<span class="math">\(\mathsf{sk}\)</span>
is the normal Orchard spending key (opaque 32 bytes), and
<span class="math">\(\mathsf{c}\)</span>
is the chain code.</p>
<section id="specification-hardened-only-key-derivation"><h2><span class="section-heading">Specification: Hardened-only key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#specification-hardened-only-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>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).</p>
<section id="instantiation"><h3><span class="section-heading">Instantiation</span><span class="section-anchor"> <a rel="bookmark" href="#instantiation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let
<span class="math">\(\mathsf{Context}\)</span>
be the context in which the hardened-only key derivation process is instantiated (e.g. a shielded protocol). We define two context-specific constants:</p>
<ul>
<li>
<span class="math">\(\mathsf{Context.MKGDomain}\)</span>
is a 16-byte domain separator used during master key generation. It SHOULD be disjoint from other domain separators used with BLAKE2b in Zcash protocols.</li>
<li>
<span class="math">\(\mathsf{Context.CKDDomain}\)</span>
is a 1-byte domain separator used during child key derivation. This should be tracked as part of the global set of domains defined for
<span class="math">\(\mathsf{PRF^{expand}}\)</span>
.</li>
</ul>
</section>
<section id="orchard-master-key-generation"><h3><span class="section-heading">Orchard master key generation</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-master-key-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<section id="hardened-only-master-key-generation"><h3><span class="section-heading">Hardened-only master key generation</span><span class="section-anchor"> <a rel="bookmark" href="#hardened-only-master-key-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let
<span class="math">\(S\)</span>
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.</p>
<span class="math">\(\mathsf{IKM}\)</span>
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.</p>
<p>
<span class="math">\(\mathsf{MKGh}^\mathsf{Context}(\mathsf{IKM}) \rightarrow (\mathsf{sk}_m, \mathsf{c}_m)\)</span>
</p>
<ul>
<li>Calculate
<span class="math">\(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{“ZcashIP32Orchard”}, S)\)</span>
<span class="math">\(I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\mathsf{Context.MKGDomain}, \mathsf{IKM})\)</span>
.</li>
<li>Split
<span class="math">\(I\)</span>
Expand All @@ -606,7 +615,7 @@
.</li>
<li>Use
<span class="math">\(I_L\)</span>
as the master spending key
as the master secret key
<span class="math">\(\mathsf{sk}_m\)</span>
.</li>
<li>Use
Expand All @@ -616,23 +625,21 @@
.</li>
<li>Return
<span class="math">\((\mathsf{sk}_m, \mathsf{c}_m)\)</span>
as the master extended spending key
<span class="math">\(m_\mathsf{Orchard}\)</span>
.</li>
</ul>
</section>
<section id="orchard-child-key-derivation"><h3><span class="section-heading">Orchard child key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-child-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<section id="hardened-only-child-key-derivation"><h3><span class="section-heading">Hardened-only child key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#hardened-only-child-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>
<span class="math">\(\mathsf{CDKsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
<span class="math">\(\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)\)</span>
<span class="math">\(\mathsf{CKDh}^\mathsf{Context}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
<span class="math">\(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\)</span>
</p>
<ul>
<li>Check whether
<span class="math">\(i \geq 2^{31}\)</span>
(whether the child is a hardened key).
<ul>
<li>If so (hardened child): let
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, [\texttt{0x81}]\,||\,\mathsf{sk}_{par}\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
<span class="math">\(I = \mathsf{PRF^{expand}}(\mathsf{c}_{par}, \mathsf{Context.CKDDomain}\,||\,\mathsf{sk}_{par}\,||\,\mathsf{I2LEOSP}_{32}(i))\)</span>
.</li>
<li>If not (normal child): return failure.</li>
</ul>
Expand All @@ -646,14 +653,60 @@
.</li>
<li>Use
<span class="math">\(I_L\)</span>
as the child spending key
<span class="math">\(\mathsf{sk}_{i}\)</span>
as the child secret key
<span class="math">\(\mathsf{sk}_i\)</span>
.</li>
<li>Use
<span class="math">\(I_R\)</span>
as the child chain code
<span class="math">\(\mathsf{c}_i\)</span>
.</li>
<li>Return
<span class="math">\((\mathsf{sk}_i, \mathsf{c}_i)\)</span>
.</li>
</ul>
</section>
</section>
<section id="specification-orchard-key-derivation"><h2><span class="section-heading">Specification: Orchard key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#specification-orchard-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>We only support hardened key derivation for Orchard. We instantiate the hardened key generation process with the following constants:</p>
<ul>
<li>
<span class="math">\(\mathsf{Orchard.MKGDomain} = \texttt{“ZcashIP32Orchard”}\)</span>
</li>
<li>
<span class="math">\(\mathsf{Orchard.CKDDomain} = [\texttt{0x81}]\)</span>
</li>
</ul>
<section id="orchard-extended-keys"><h3><span class="section-heading">Orchard extended keys</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-extended-keys"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>We represent an Orchard extended spending key as
<span class="math">\((\mathsf{sk, c}),\)</span>
where
<span class="math">\(\mathsf{sk}\)</span>
is the normal Orchard spending key (opaque 32 bytes), and
<span class="math">\(\mathsf{c}\)</span>
is the chain code.</p>
</section>
<section id="orchard-master-key-generation"><h3><span class="section-heading">Orchard master key generation</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-master-key-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let
<span class="math">\(S\)</span>
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.</p>
<ul>
<li>Return
<span class="math">\(\mathsf{MKGh}^\mathsf{Orchard}(S)\)</span>
as the master extended spending key
<span class="math">\(m_\mathsf{Orchard}\)</span>
.</li>
</ul>
</section>
<section id="orchard-child-key-derivation"><h3><span class="section-heading">Orchard child key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#orchard-child-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>
<span class="math">\(\mathsf{CDKsk}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
<span class="math">\(\rightarrow (\mathsf{sk}_{i}, \mathsf{c}_i)\)</span>
</p>
<ul>
<li>Return
<span class="math">\(\mathsf{CKDh}^\mathsf{Orchard}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
</li>
</ul>
<p>Note that the resulting child spending key may produce an invalid external FVK, as specified in <a id="footnote-reference-28" class="footnote_reference" href="#protocol-orchardkeycomponents">12</a>, with small probability. The corresponding internal FVK derived as specified in the next section may also be invalid with small probability.</p>
</section>
Expand Down Expand Up @@ -735,6 +788,54 @@
</p>
</section>
</section>
<section id="specification-arbitrary-key-derivation"><h2><span class="section-heading">Specification: Arbitrary key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#specification-arbitrary-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>In some contexts there is a need for deriving arbitrary keys with the same derivation path as existing key material (for example, deriving an arbitrary account-level key), without the need for ecosystem-wide coordination. The following instantiation of the hardened key generation process may be used for this purpose.</p>
<p>Let
<span class="math">\(\mathsf{ContextString}\)</span>
be a globally-unique non-empty sequence of at most 65535 bytes that identifies the desired context.</p>
<p>We instantiate the hardened key generation process with the following constants:</p>
<ul>
<li>
<span class="math">\(\mathsf{Arbitrary.MKGDomain} = \texttt{“ZcashArbitraryKD”}\)</span>
</li>
<li>
<span class="math">\(\mathsf{Arbitrary.CKDDomain} = [\texttt{0xAB}]\)</span>
</li>
</ul>
<section id="arbitrary-master-key-generation"><h3><span class="section-heading">Arbitrary master key generation</span><span class="section-anchor"> <a rel="bookmark" href="#arbitrary-master-key-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>Let
<span class="math">\(S\)</span>
be a seed byte sequence of a chosen length, which MUST be at least 32 and at most 252 bytes.</p>
<p>The master extended arbitrary key is:</p>
<p>
<span class="math">\(m_\mathsf{Arbitrary} = \mathsf{MKGh}^\mathsf{Arbitrary}(\)</span>
<span class="math">\(\hspace{2em} \mathsf{I2LEOSP}_{16}(\mathsf{length}(\mathsf{ContextString}))\,||\,\mathsf{ContextString}\,||\,\)</span>
<span class="math">\(\hspace{2em} [\mathsf{length}(S)]\,||\,S)\)</span>
.</p>
</section>
<section id="arbitrary-child-key-derivation"><h3><span class="section-heading">Arbitrary child key derivation</span><span class="section-anchor"> <a rel="bookmark" href="#arbitrary-child-key-derivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
<p>
<span class="math">\(\mathsf{CKDarb}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
<span class="math">\(\rightarrow (\mathsf{sk}_i, \mathsf{c}_i)\)</span>
</p>
<ul>
<li>Return
<span class="math">\(\mathsf{CKDh}^\mathsf{Arbitrary}((\mathsf{sk}_{par}, \mathsf{c}_{par}), i)\)</span>
</li>
</ul>
<p>If the context requires a 64-byte key (for example, to avoid an entropy bottleneck in its particular subsequent operations), and
<span class="math">\(i\)</span>
is the last element of an HD path, the concatenation
<span class="math">\(\mathsf{sk}_i\,||\,\mathsf{c}_i\)</span>
MAY be used as a key. In this case,
<span class="math">\((\mathsf{sk}_i, \mathsf{c}_i)\)</span>
MUST NOT be given as input to
<span class="math">\(\mathsf{CKDarb}\)</span>
(this is a restatement of the requirement that
<span class="math">\(i\)</span>
is the last element of an HD path).</p>
</section>
</section>
<section id="specification-wallet-usage"><h2><span class="section-heading">Specification: Wallet usage</span><span class="section-anchor"> <a rel="bookmark" href="#specification-wallet-usage"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
<p>Existing Zcash-supporting HD wallets all use BIP 44 <a id="footnote-reference-33" class="footnote_reference" href="#bip-0044">5</a> 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.</p>
<section id="key-path-levels"><h3><span class="section-heading">Key path levels</span><span class="section-anchor"> <a rel="bookmark" href="#key-path-levels"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
Expand Down

0 comments on commit b4682c1

Please sign in to comment.