QED-it / zips

Working copy of the Zcash Improvement Proposals with ZSA updates
https://qed-it.github.io/zips/
MIT License
0 stars 1 forks source link

Convention for domain separators #24

Open AntoineRondelet opened 1 year ago

AntoineRondelet commented 1 year ago

I'd like to discuss conventions for domain separators. I can see that the Zcash contribs have been using different format for their domain separators in their ZIPs.

Here’s what I get when I pattern match "ZIP and "ZcashIP in the ZIPs repo:

~/D/zips ❯❯❯ find "." -type f -exec grep -Hn 'ZcashIP' {} \;
./zip-0032.rst:187:- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{"ZcashIP32Sapling"}, S)`.
./zip-0032.rst:377:- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{"ZcashIP32Orchard"}, S)`.
./zip-0032.rst:662:* the :math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}` personalization :math:`\texttt{"ZcashIP32_Sprout"}`,

~/D/zips ❯❯❯ find "." -type f -exec grep -Hn '"ZIP' {} \;
./zip-0227.html:115:                        <span class="math">\(m_{\mathsf{Issuance}} := \mathsf{MasterKeyGen}(\texttt{"ZIP32ZSAIssue_V1"}, S)\)</span>
./zip-0227.rst:118:We define the master extended issuance key :math:`m_{\mathsf{Issuance}} := \mathsf{MasterKeyGen}(\texttt{"ZIP32ZSAIssue_V1"}, S)`.

./zip-0304.rst:171:- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`.
./zip-0304.rst:192:- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`.

So, in ZIP32 (which is used as reference for the key derivation in ZIP 227) they use "ZcashIP32<suffix> as a message structure for their domain separator, while in ZIP 304 they use ZIP304<suffix> and in ZIP227 we use ZIP32ZSAIssue_V1 . None of these are consistent. Ideally there should be a convention for the domain separators (maybe there is one, but I miss it?). Looking at the 2 types of separators used by Zcash we should probably try to align there as well and switch ZIP32ZSAIssue_V1 for either ZIP227Issue_V1 or ZcashIP227Issue_V1 (the latter is probably better since we use ZIP32 as reference for the key derivation, so it’d be better to use the same syntax in the MasterKeyGen in ZIP227). TL;DR we should probably stick to either ZIP[zip_number]<suffix> or ZcashIP[zip_number]<suffix> for the MasterKeygen in ZIP227.

Thoughts? Do I miss something obvious?


@PaulLaux mentioned that:


Is it really necessary to use ZIP32 as prefix to ZIP32ZSAIssue_V1 though? The spec of ZIP227 is pretty clear about the fact that the MasterKeyGen is taken from ZIP32. The ZSA specs seem to be designed to support different protocol versions of Zcash (as per the use of the Protocol superscript in the ZIPs for the AssetBase). While this may appear to be a detail, I really believe that we should make things as standardized and “systematic” as possible, even the definition of these “domain separators”. So we can strive to make things more consistent here by using the same domain separator prefix as used in ZIP32's KeyGen, i.e. ZcashIP instead of ZIP to use the following syntax ZcashIP32<suffix> where suffix is 7-character long, e.g. ZSA<4 first characters of the Protocol> etc.

Also, I'm not sure how ZIP32 will be extended to support ZSA insurance, but I guess it'll be done via another ZIP, won't it? (in which case the ZIP32 prefix may not make sense anymore?)

Using some Protocol-related characters in the suffix would also be consistent with the first input of the GroupHash used to derive the ZSAValuebase (which contains OrchardZSA as suffix) in ZIP-227. I mean, no big deal, happy to take things as they are, but the domain separators don’t seem to follow any conventions (even the one used for AssetDigest doesn’t have any prefix referring to the ZIP. It’s currently ZSA-Asset-Digest which isn’t really consistent with any other seeds/domain separators because it uses - while other ZIPs seem to use snake case (_) or PascalCase for domain separators, see:

(env) ~/D/zips ❯❯❯ find "." -type f -exec grep -Hn '\mathsf{BLAKE2b}' {} \;
./protocol/protocol.tex:1355:\newcommand{\BlakeTwobGeneric}{\mathsf{BLAKE2b}}
./zip-0032.rst:105:- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)` refers to unkeyed BLAKE2b-256 in sequential mode,
./zip-0032.rst:108:- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}(p, x)` refers to unkeyed BLAKE2b-512 in sequential mode,
./zip-0032.rst:111:- :math:`\mathsf{PRF^{expand}}(\mathsf{sk}, t) :=`:math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{"Zcash_ExpandSeed"},`:math:`\mathsf{sk}\,||\,t)`
./zip-0032.rst:187:- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{"ZcashIP32Sapling"}, S)`.
./zip-0032.rst:377:- Calculate :math:`I = \mathsf{BLAKE2b}\text{-}\mathsf{512}(\texttt{"ZcashIP32Orchard"}, S)`.
./zip-0032.rst:562:* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZcashSaplingFVFP"}, \mathit{FVK})`.
./zip-0032.rst:576:* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZcashOrchardFVFP"}, \mathit{FVK})`.
./zip-0032.rst:589:* :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"Zcash_HD_Seed_FP"},`:math:`[\mathsf{length}(S)]\,||\,S)`.
./zip-0032.rst:662:* the :math:`\mathsf{BLAKE2b}\text{-}\mathsf{512}` personalization :math:`\texttt{"ZcashIP32_Sprout"}`,
./zip-0032.rst:664:* the :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}` personalization :math:`\texttt{"Zcash_Sprout_AFP"}`,
./zip-0304.rst:90:- :math:`\mathsf{BLAKE2b}\text{-}\mathsf{256}(p, x)` refers to unkeyed BLAKE2b-256 in
./zip-0304.rst:171:- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`.
./zip-0304.rst:192:- Let :math:`digest = \mathsf{BLAKE2b}\text{-}\mathsf{256}(\texttt{"ZIP304Signed"}\,||\,coinType, zkproof\,||\,msg)`.
AntoineRondelet commented 1 year ago

So, the suggestion is:

AntoineRondelet commented 1 year ago

Having a consistent scheme for domain separators makes things easier to review and makes possible mistakes easier to spot but should also benefit the implementation, we can have util functions like (Python):

def get_zip227_blake2b512_separator(suffix: str):
    assert len(suffix) == 10
    return f"ZIP227{suffix}"

Same for other separators (GroupHash etc)

daira commented 3 weeks ago

So, in ZIP32 (which is used as reference for the key derivation in ZIP 227) they use "ZcashIP32 as a message structure for their domain separator, while in ZIP 304 they use ZIP304 and in ZIP227 we use ZIP32ZSAIssue_V1 . None of these are consistent.

ZIP 32 is the only one of those that is a final spec, and the only one we can't easily change. I just checked: all of the BLAKE2b domain separators in final consensus specs (either ZIPs or the protocol spec) start with either "Zcash" or "ZTx". (ZIP 316 also uses "UAF4Jumble" for Unified Addresses. FROST uses "FROST_" but only for non-Zcash curves.)

It's not technically required to follow the same convention, but there is method behind it. If all the domain separators start with a small number of prefixes, then another coin that forks the design could just pick different values for those prefixes.

It isn't necessary to include the ZIP number for things that are going to be included in the main protocol spec, like Sapling, Orchard, and OrchardZSA shielded protocols. It also isn't necessary to repeat the Z for Zcash in an acronym. So "ZcashSA" (for "Zcash Shielded Assets") plus a 9-byte suffix would work. For example here I suggested "ZcashSA_Issue_V1" for ZSA issuance key derivation.

  • Be consistent with casing in domain separators/seeds: stick to PascalCase and use snake case _ if necessary.
  • Use z.cash:<suffix> for GroupHash [...], where suffix is <protocol>ZSA (e.g. OrchardZSA).

Yes these are correct.