Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ZIP 32] Shielded Hierarchical Deterministic Wallets #157

Merged
merged 52 commits into from Oct 5, 2018

Conversation

str4d
Copy link
Contributor

@str4d str4d commented May 30, 2018

No description provided.

zip-0032.rst Outdated

- *a* || *b* means the concatenation of sequences *a* then *b*.

- [*k*] *P* means scalar multiplication in the group *P*.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scalar multiplication of the (elliptic curve) group element P by the scalar k.

zip-0032.rst Outdated
- 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*)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: *sk*, *t* (the comma should not be in italic :-) )

- 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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With hindsight, it would have been useful to support an "address derivation key" which allows creating (and linking) diversified addresses but without being able to decrypt notes sent to them. I don't see a way to do this with Sapling's current key derivation structure, though. We should consider this issue for the next circuit upgrade — at which time we'll have more experience with diversified addresses.

(Aside: Sapling payment addresses were intentionally made not to be "rediversifiable" –i.e. it is not possible to create one diversified address directly from another– as part of preventing Brian Warner's attack in which a note for one address is encrypted to a different address in order to attempt to link them. But that attack does not preclude support for an address derivation key, because we would not be trying to prevent linking of addresses given this key.)

zip-0032.rst Outdated
Specification: Sprout key derivation
====================================

For completeness, we define a system for deriving a tree of Sprout keys components. It is unlikely that this
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/key/keys/

zip-0032.rst Outdated

- ``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]_.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note that all testnets share coin_type index 1.

zip-0032.rst Outdated

Unlike BIP 44, neither Sprout nor Sapling have a `change` path level. This is because shielded addresses are
never publicly visible in transactions, which means that sending change back to the originating address is
indistinguishable from using a change address.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only makes sense if you already know that the motivation for using separate change addresses in Bitcoin was to attempt to improve privacy.

zip-0032.rst Outdated
Wallets MUST support generating the default payment address (corresponding to the default diversifier). They
MAY also support generating a stream of payment addresses for a given account, if they wish to maintain the
user experience of giving a unique address to each recipient. Note that a given account can have a maximum of
2\ :sup:`88` payment addresses.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need some discussion of diversifier collisions here. If wallet implementors attempt to do this in the most obvious way, they will start to hit collisions after ~244 (or fewer, with lower probability) addresses. Should we define a PRP-based derivation method?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: ~243.5 (because half of diversifiers are invalid). And the maximum number is 287.

@str4d str4d force-pushed the zip-0032 branch 4 times, most recently from 18b1bc6 to 96a829b Compare June 8, 2018 02:53
@daira daira changed the title ZIP 32: Shielded Hierarchical Deterministic Wallets [ZIP 32] Shielded Hierarchical Deterministic Wallets Jun 10, 2018
@str4d
Copy link
Contributor Author

str4d commented Jun 20, 2018

@daira and I had a pairing to figure out how to derive pseudo-random diversifiers without hitting the 244 birthday bound on collisions, by using a PRP. We've decided to use FFX-A2 (as being considered by NIST), with 88-bit messages and the zero-length byte string as tweak. The one additional change we are making is to use 256-bit AES keys (matching the rest of the key material); as the key size is not technically a tunable parameter within the A2 parameter set, we will refer to this as FFX-AES256-A2. EDIT: NIST standardised this in SP 800-38G as FF1-AES256.

@daira daira force-pushed the zip-0032 branch 2 times, most recently from a69ef8c to 30493b3 Compare July 5, 2018 16:11
zip-0032.rst Outdated
@@ -199,7 +199,7 @@ The 88-bit diversifiers for a Sapling extended key are derived from its diversif
In order to reach the maximum possible diversifier range without running into the birthday bound, we use
FF1-AES256 as a Pseudo-Random Permutation as follows:

- Let *j* be the index of the desired diversifier.
- Let *j* be the index of the desired diversifier, in the range 0 .. 2\ :sup:`88`\ -1.
- *d*\ :sub:`i,j` = FF1-AES256.Encrypt(*dk*\ :sub:`i`\ , "", I2LEBSP\ :sub:`88`\ (*j*))

The default diversifier for a Sapling extended key is defined to be *d*\ :sub:`i,0`\ .
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we need to be clearer here: it's not simply j = 0, but the first j that results in a valid diversifier.

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*.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, does unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes (and likewise for BLAKE2b-256) convey the correct meaning? We want to indicate that the only difference between the two is the digest length (so maybe unkeyed BLAKE2b in [...], but that it is not the same thing as truncating (so maybe we need more than output digest length).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same wording as in the protocol spec, and I believe it's unambiguous.

zip-0032.rst Show resolved Hide resolved
zip-0032.rst Outdated
parent address tag *parent_addr_tag* and child number *i*, is represented as a
byte sequence::

I2LEOSP\ :sub:`8`\ (*depth*) || *parent_addr_tag* || I2LEOSP\ :sub:`32`\ (*i*) || *ASK* || *c*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put ASK after c to match the Sapling encodings.

str4d and others added 17 commits July 25, 2018 00:32
Note that this means they are encoded in little-endian order, which is the
opposite of BIP 32.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Hardened derivation is undefined for an extended FVK
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
…rent addresses.

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
zip-0032.rst Outdated
.. [#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>`_
.. [#bip-0173] `BIP 173: Base32 address format for native v0-16 witness outputs <https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki>`_
.. [#sapling-spec] `Zcash Protocol Specification, Version 2018.0-beta-21 or later [Overwinter+Sapling] <https://github.com/zcash/zips/blob/master/protocol/sapling.pdf>`_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update these links to protocol.pdf

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filename changes weren't made until 2018.0-beta-25. But it's correct to update it to protocol.pdf if the version is changed to be later than that.

- *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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to "Deriving a normal child extended full viewing key from a parent extended full viewing key"?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this implied? The subheading above it doesn't say "Deriving a child extended spending key from a parent extended spending key".

- *dk*\ :sub:`i` = truncate\ :sub:`32`\ (PRF\ :sup:`expand`\ (*I*\ :sub:`L`\ , [0x16] || *dk*\ :sub:`par`\ ))
- *c*\ :sub:`i` = *I*\ :sub:`R`

Diversifier derivation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dk seems better than dki in this section

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if di,j is also changed to dj.

zip-0032.rst Outdated

m_Sapling / purpose' / coin_type' / account'

Wallets MUST support generating the default payment address (corresponding to the default diversifier). They
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps add 'as defined above' after 'default diversifier'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In summary to discussions, would change sentence to
"Furthermore, Wallets MUST support generating the default payment address (corresponding to the default diversifier as defined above) for any account they support".

zip-0032.rst Outdated
- ToScalar(*x*) := LEOS2IP\ :sub:`512`\ (*x*) (mod *r*\ :sub:`J`\ ), where *r*\ :sub:`J` \ is the order
of the Jubjub large prime subgroup.

- DiversifyHash(*d*) maps a diversifier *d* to a base point on the Jubjub elliptic curve, or to ⊥ if the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps add 'prime order subgroup' after 'elliptic curve'

zip-0032.rst Outdated

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::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add 'for any account' in {0,..,2^31-1}' ?

zip-0032.rst Outdated
- Use *I*\ :sub:`L` as the master spending key *sk*\ :sub:`m`\ , and *I*\ :sub:`R` as the master chain code
*c*\ :sub:`m`\ .
- Calculate the master extended spending key *m*\ :sub:`Sapling` = (*ask*\ :sub:`m`\ , *nsk*\ :sub:`m`\ ,
*ovk*\ :sub:`m`\ , *dk*\ :sub:`m`\ , *c*\ :sub:`m`\ ) via the standard Sapling derivation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

via -> similarly - cause dk isn't in the Sapling derivation

zip-0032.rst Outdated
----------------------

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate about what you mean 'running into the birthday problem'? I think you mean also you want to get some independence of diversifier sequences of different base keys. If I just want no collisions, I could define d_{i,j} = j.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, diversifiers should follow an independent random sequence for each ivk. Otherwise, the diversifier leaks information about how many previous diversifiers were obtained from that ivk.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, this should be explained though.. added two new comments with suggested phrasings.

@ebfull
Copy link
Contributor

ebfull commented Sep 10, 2018

My ACK is to indicate that I approve of the design -- though I would personally have advocated against specifying a Sprout key derivation model. Also, I think it may be worth mentioning the security properties like BIP32 does. (We should indicate that using the same seed byte sequence for master key derivation in BIP32 and ZIP32 is fine, even though it may be obvious to some.)

I'm confused about how this document progresses through the ZIP process, and whether we're supposed to label this as a draft or not. Do we not merge until we have test vectors and the spec is complete?

zip-0032.rst Outdated
@@ -329,7 +329,7 @@ relevant transactions.

The above key path levels include an account identifier, which in all user interfaces is represented as a
"bucket of funds" under the control of a single spending authority. Therefore, wallets implementing Sapling
ZIP 32 derivation MUST support the following path::
ZIP 32 derivation MUST support the following path for any account in range {0..2\ :sup:`31`\ -1}::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

account -> account'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Account is already defined earlier up as hardened, so the meaning here is clear enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and account is in range 0..2^31-1, while account' is technically in range 2^31..2^32-1 which doesn't read as easily)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right.

zip-0032.rst Outdated
----------------------

The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*.
In order to reach the maximum possible diversifier range without running into the birthday bound, we use
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"without running into the birthday bound," --> "without running into repetitions due to the birthday bound,".

zip-0032.rst Outdated
Diversifier derivation
----------------------

The 88-bit diversifiers for a Sapling extended key are derived from its diversifier key *dk*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add after sentence "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."

@daira daira merged commit f6f47a0 into zcash:master Oct 5, 2018
@str4d str4d deleted the zip-0032 branch November 3, 2022 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants