mirror of https://github.com/zcash/zips.git
hash signing package in randomizer generator; overall adjustments
This commit is contained in:
parent
c0c16432a4
commit
b441df0745
134
zip-0312.html
134
zip-0312.html
|
@ -31,13 +31,13 @@ Pull-Request: <<a href="https://github.com/zcash/zips/pull/662">https://githu
|
|||
</section>
|
||||
<section id="motivation"><h2><span class="section-heading">Motivation</span><span class="section-anchor"> <a rel="bookmark" href="#motivation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<p>In the Zcash protocol, Spend Authorization Signatures are employed to authorize a transaction. The ability to generate these signatures with the user's private key is what effectively allows the user to spend funds.</p>
|
||||
<p>This is a security-critical step, since anyone who obtains access to the private key will be able to spend the user's funds. For this reason, one interesting possibility is to require multiple parties to allow the transaction to go through. This can be accomplished with threshold signatures, where the private key is split between parties in a way that a threshold (e.g. 2 out of 3) of them must sign the transaction in order to create the final signature. This enables scenarios such as users and exchanges sharing custody of a wallet, for example.</p>
|
||||
<p>This is a security-critical step, since anyone who obtains access to the private key will be able to spend the user's funds. For this reason, one interesting possibility is to require multiple parties to allow the transaction to go through. This can be accomplished with threshold signatures, where the private key is split between parties (or generated already split using a distributed protocol) in a way that a threshold (e.g. 2 out of 3) of them must sign the transaction in order to create the final signature. This enables scenarios such as users and third-party services sharing custody of a wallet, or a group of people managing shared funds, for example.</p>
|
||||
<p>FROST is one of such threshold signature protocols. However, it can't be used as-is since the Zcash protocol also requires re-randomizing public and private keys to ensure unlinkability between transactions. This ZIP specifies a variant of FROST with re-randomization support.</p>
|
||||
</section>
|
||||
<section id="requirements"><h2><span class="section-heading">Requirements</span><span class="section-anchor"> <a rel="bookmark" href="#requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<ul>
|
||||
<li>All signatures generated by following this ZIP must be verified successfully as Sapling or Orchard spend authorization signatures using the appropriate validating key.</li>
|
||||
<li>The signatures generated by following this ZIP should meet the security criteria for Signature with Re-Randomizable Keys as specified in the Zcash protocol <a id="id3" class="footnote_reference" href="#protocol-concretereddsa">10</a>.</li>
|
||||
<li>The signatures generated by following this ZIP should meet the security criteria for Signature with Re-Randomizable Keys as specified in the Zcash protocol <a id="id3" class="footnote_reference" href="#protocol-concretereddsa">11</a>.</li>
|
||||
<li>The threat model described below must be taken into account.</li>
|
||||
</ul>
|
||||
<section id="threat-model"><h3><span class="section-heading">Threat Model</span><span class="section-anchor"> <a rel="bookmark" href="#threat-model"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
|
||||
|
@ -60,51 +60,59 @@ Pull-Request: <<a href="https://github.com/zcash/zips/pull/662">https://githu
|
|||
</section>
|
||||
<section id="non-requirements"><h2><span class="section-heading">Non-requirements</span><span class="section-anchor"> <a rel="bookmark" href="#non-requirements"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<ul>
|
||||
<li>This ZIP does not support removing the Coordinator role, as described in #[frost-removingcoordinator]_.</li>
|
||||
<li>This ZIP does not support removing the Coordinator role, as described in <a id="id5" class="footnote_reference" href="#frost-removingcoordinator">5</a>.</li>
|
||||
<li>This ZIP does not prevent key share holders from linking the signing operation to a transaction in the blockchain.</li>
|
||||
<li>Like the FROST specification <a id="id5" class="footnote_reference" href="#frost">3</a>, this ZIP does not specify a key generation procedure; but refer to that specification for guidelines.</li>
|
||||
<li>Like the FROST specification <a id="id6" class="footnote_reference" href="#frost">3</a>, this ZIP does not specify a key generation procedure; but refer to that specification for guidelines.</li>
|
||||
<li>Network privacy is not in scope for this ZIP, and must be obtained with other tools if desired.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="specification"><h2><span class="section-heading">Specification</span><span class="section-anchor"> <a rel="bookmark" href="#specification"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<p>Algorithms in this section are specified using Python pseudo-code, in the same fashion as the FROST specification <a id="id6" class="footnote_reference" href="#frost">3</a>.</p>
|
||||
<p>The types Scalar, Element, and G are defined in #[frost-primeordergroup]_, as well as the notation for elliptic-curve arithmetic, which uses the additive notation. Note that this notation differs from that used in the Zcash Protocol Specification. For example, <code>G.ScalarMult(P, k)</code> is used for scalar multiplication, where the protocol spec would use
|
||||
<p>Algorithms in this section are specified using Python pseudo-code, in the same fashion as the FROST specification <a id="id7" class="footnote_reference" href="#frost">3</a>.</p>
|
||||
<p>The types Scalar, Element, and G are defined in <a id="id8" class="footnote_reference" href="#frost-primeordergroup">6</a>, as well as the notation for elliptic-curve arithmetic, which uses the additive notation. Note that this notation differs from that used in the Zcash Protocol Specification. For example, <code>G.ScalarMult(P, k)</code> is used for scalar multiplication, where the protocol spec would use
|
||||
<span class="math">\([k] P\)</span>
|
||||
with the group implied by
|
||||
<span class="math">\(P\)</span>
|
||||
.</p>
|
||||
<p>An additional per-ciphersuite hash function is used, denote <code>HR(m)</code>, which receives an arbitrary-sized byte string and returns a Scalar. It is defined concretely in the Ciphersuites section.</p>
|
||||
<section id="re-randomizable-frost"><h3><span class="section-heading">Re-randomizable FROST</span><span class="section-anchor"> <a rel="bookmark" href="#re-randomizable-frost"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
|
||||
<p>To add re-randomization to FROST, follow the specification <a id="id7" class="footnote_reference" href="#frost">3</a> with the following modifications.</p>
|
||||
<p>To add re-randomization to FROST, follow the specification <a id="id9" class="footnote_reference" href="#frost">3</a> with the following modifications.</p>
|
||||
<section id="key-generation"><h4><span class="section-heading">Key Generation</span><span class="section-anchor"> <a rel="bookmark" href="#key-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>While key generation is out of scope for this ZIP and the FROST spec <a id="id8" class="footnote_reference" href="#frost">3</a>, it needs to be consistent with FROST, see <a id="id9" class="footnote_reference" href="#frost-tdkg">8</a> for guidance. The spend authorization private key
|
||||
<p>While key generation is out of scope for this ZIP and the FROST spec <a id="id10" class="footnote_reference" href="#frost">3</a>, it needs to be consistent with FROST, see <a id="id11" class="footnote_reference" href="#frost-tdkg">8</a> for guidance. The spend authorization private key
|
||||
<span class="math">\(\mathsf{ask}\)</span>
|
||||
<a id="id10" class="footnote_reference" href="#protocol-spendauthsig">12</a> is the particular key that must be used in the context of this ZIP. Note that the
|
||||
<a id="id12" class="footnote_reference" href="#protocol-spendauthsig">13</a> is the particular key that must be used in the context of this ZIP. Note that the
|
||||
<span class="math">\(\mathsf{ask}\)</span>
|
||||
is usually derived from the spending key
|
||||
<span class="math">\(\mathsf{sk}\)</span>
|
||||
, though that is not required. This allows using distributed key generation, since the key it generates is unpredictable. Note however that note deriving
|
||||
, though that is not required. Not doing so allows using distributed key generation, since the key it generates is unpredictable. Note however that not deriving
|
||||
<span class="math">\(\mathsf{ask}\)</span>
|
||||
from
|
||||
<span class="math">\(\mathsf{sk}\)</span>
|
||||
prevents using seed phrases to recover the original secret (which may be something desirable in the context of FROST).</p>
|
||||
</section>
|
||||
<section id="randomizer-generation"><h4><span class="section-heading">Randomizer Generation</span><span class="section-anchor"> <a rel="bookmark" href="#randomizer-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>A new helper function is defined, which computes
|
||||
<span class="math">\(\mathsf{RedDSA.GenRandom}\)</span>
|
||||
:</p>
|
||||
<p>A new helper function is defined, which generates a randomizer. The <cite>encode_signing_package</cite> is defined as the byte serialization of the <cite>msg</cite>, <cite>commitment_list</cite> values as described in <a id="id13" class="footnote_reference" href="#frost-serialization">10</a>. Implementations MAY choose another encoding as long as all values (the message, and the identifier, binding nonce and hiding nonce for each participant) are encoded.</p>
|
||||
<pre>randomizer_generate():
|
||||
|
||||
Inputs:
|
||||
- None
|
||||
- msg, the message being signed in the current FROST signing run
|
||||
- commitment_list = [(i, hiding_nonce_commitment_i,
|
||||
binding_nonce_commitment_i), ...], a list of commitments issued by
|
||||
each participant, where each element in the list indicates a
|
||||
NonZeroScalar identifier i and two commitment Element values
|
||||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list
|
||||
MUST be sorted in ascending order by identifier.
|
||||
|
||||
Outputs: randomizer, a Scalar
|
||||
|
||||
def randomizer_generate():
|
||||
randomizer_input = random_bytes(64)
|
||||
return H3(randomizer_input)</pre>
|
||||
def randomizer_generate(msg, commitment_list):
|
||||
rng_randomizer = G.RandomScalar()
|
||||
rng_randomizer_enc = G.SerializeScalar(rng_randomizer)
|
||||
signing_package_enc = encode_signing_package(commitment_list, msg)
|
||||
randomizer_input = random_bytes(rng_randomizer_enc || signing_package_enc)
|
||||
return HR(randomizer_input)</pre>
|
||||
</section>
|
||||
<section id="round-one-commitment"><h4><span class="section-heading">Round One - Commitment</span><span class="section-anchor"> <a rel="bookmark" href="#round-one-commitment"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>Roune One is exactly the same as specified <a id="id11" class="footnote_reference" href="#frost">3</a>. But for context, it involves these steps:</p>
|
||||
<p>Roune One is exactly the same as specified <a id="id14" class="footnote_reference" href="#frost">3</a>. But for context, it involves these steps:</p>
|
||||
<ul>
|
||||
<li>Each signer generates nonces and their corresponding public commitments. A nonce is a pair of Scalar values, and a commitment is a pair of Element values.</li>
|
||||
<li>The nonces are stored locally by the signer and kept private for use in the second round.</li>
|
||||
|
@ -113,19 +121,19 @@ def randomizer_generate():
|
|||
</section>
|
||||
<section id="round-two-signature-share-generation"><h4><span class="section-heading">Round Two - Signature Share Generation</span><span class="section-anchor"> <a rel="bookmark" href="#round-two-signature-share-generation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>In Round Two, the Coordinator generates a random scalar <code>randomizer</code> by calling <code>randomizer_generate</code> and sends it to each signer, over a confidential and authenticated channel, along with the message and the set of signing commitments. (Note that this differs from regular FROST which just requires an authenticated channel.)</p>
|
||||
<p>In Zcash, the message that needs to be signed is actually the SIGHASH transaction hash, which does not convey enough information for the signers to decide if they want to authorize the transaction or not. Therefore, in practice, more data is needed to be sent (over the same encrypted, authenticated channel) from the Coordinator to the signers, possibly the transaction itself, openings of value commitments, decryption of note ciphertexts, etc.; and the signers must check that the given SIGHASH matches the data sent from the Coordinator, or compute the SIGHASH themselves from that data. However, the specific mechanism for that process is outside the scope of this ZIP.</p>
|
||||
<p>The <code>sign</code> function remains unchanged, but its inputs must be modified relative to the <code>randomizer</code> as following:</p>
|
||||
<p>In Zcash, the message that needs to be signed is actually the SIGHASH transaction hash, which does not convey enough information for the signers to decide if they want to authorize the transaction or not. Therefore, in practice, more data is needed to be sent (over the same encrypted, authenticated channel) from the Coordinator to the signers, possibly the transaction itself, openings of value commitments, decryption of note ciphertexts, etc.; and the signers MUST check that the given SIGHASH matches the data sent from the Coordinator, or compute the SIGHASH themselves from that data. However, the specific mechanism for that process is outside the scope of this ZIP.</p>
|
||||
<p>The randomized <code>sign</code> function is defined as the regular FROST <code>sign</code> function, but with its inputs modified relative to the <code>randomizer</code> as following:</p>
|
||||
<ul>
|
||||
<li><code>sk_i = sk_i + randomizer</code></li>
|
||||
<li><code>group_public_key = group_public_key + G.ScalarBaseMult(randomizer)</code></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="signature-share-verification-and-aggregation"><h4><span class="section-heading">Signature Share Verification and Aggregation</span><span class="section-anchor"> <a rel="bookmark" href="#signature-share-verification-and-aggregation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>The <code>aggregate</code> function remains unchanged, but its inputs must be modified relative to the <code>randomizer</code> as following:</p>
|
||||
<p>The randomized <code>aggregate</code> function is defined as the regular FROST <code>aggregate</code> function, but with its inputs modified relative to the <code>randomizer</code> as following:</p>
|
||||
<ul>
|
||||
<li><code>group_public_key = group_public_key + G.ScalarBaseMult(randomizer)</code></li>
|
||||
</ul>
|
||||
<p>The <code>verify_signature_share</code> function remains unchanged, but its inputs must be modified relative to the <code>randomizer</code> as following:</p>
|
||||
<p>The randomized <code>verify_signature_share</code> function is defined as the regular FROST <code>verify_signature_share</code> function, but with its inputs modified relative to the <code>randomizer</code> as following:</p>
|
||||
<ul>
|
||||
<li><code>PK_i = PK_i + G.ScalarBaseMult(randomizer)</code></li>
|
||||
<li><code>group_public_key = group_public_key + G.ScalarBaseMult(randomizer)</code></li>
|
||||
|
@ -134,91 +142,93 @@ def randomizer_generate():
|
|||
</section>
|
||||
<section id="ciphersuites"><h3><span class="section-heading">Ciphersuites</span><span class="section-anchor"> <a rel="bookmark" href="#ciphersuites"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h3>
|
||||
<section id="frost-jubjub-blake2b-512"><h4><span class="section-heading">FROST(Jubjub, BLAKE2b-512)</span><span class="section-anchor"> <a rel="bookmark" href="#frost-jubjub-blake2b-512"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>This ciphersuite uses Jubjub for the Group and BLAKE2b-512 for the Hash function <code>H</code> meant to produce signatures indistinguishable from RedJubjub Sapling Spend Authorization Signatures as specified in <a id="id12" class="footnote_reference" href="#protocol-concretespendauthsig">11</a>.</p>
|
||||
<p>This ciphersuite uses Jubjub for the Group and BLAKE2b-512 for the Hash function <code>H</code> meant to produce signatures indistinguishable from RedJubjub Sapling Spend Authorization Signatures as specified in <a id="id15" class="footnote_reference" href="#protocol-concretespendauthsig">12</a>.</p>
|
||||
<ul>
|
||||
<li>Group: Jubjub <a id="id13" class="footnote_reference" href="#protocol-jubjub">13</a> with base point
|
||||
<li>Group: Jubjub <a id="id16" class="footnote_reference" href="#protocol-jubjub">14</a> with base point
|
||||
<span class="math">\(\mathcal{G}^{\mathsf{Sapling}}\)</span>
|
||||
as defined in <a id="id14" class="footnote_reference" href="#protocol-concretespendauthsig">11</a>.
|
||||
as defined in <a id="id17" class="footnote_reference" href="#protocol-concretespendauthsig">12</a>.
|
||||
<ul>
|
||||
<li>Order:
|
||||
<span class="math">\(r_\mathbb{J}\)</span>
|
||||
as defined in <a id="id15" class="footnote_reference" href="#protocol-jubjub">13</a>.</li>
|
||||
<li>Identity: as defined in <a id="id16" class="footnote_reference" href="#protocol-jubjub">13</a>.</li>
|
||||
as defined in <a id="id18" class="footnote_reference" href="#protocol-jubjub">14</a>.</li>
|
||||
<li>Identity: as defined in <a id="id19" class="footnote_reference" href="#protocol-jubjub">14</a>.</li>
|
||||
<li>RandomScalar(): Implemented by returning a uniformly random Scalar in the range [0, <code>G.Order()</code> - 1]. Refer to {{frost-randomscalar}} for implementation guidance.</li>
|
||||
<li>SerializeElement(P): Implemented as
|
||||
<span class="math">\(\mathsf{repr}_\mathbb{J}(P)\)</span>
|
||||
as defined in <a id="id17" class="footnote_reference" href="#protocol-jubjub">13</a></li>
|
||||
as defined in <a id="id20" class="footnote_reference" href="#protocol-jubjub">14</a></li>
|
||||
<li>DeserializeElement(P): Implemented as
|
||||
<span class="math">\(\mathsf{abst}_\mathbb{J}(P)\)</span>
|
||||
as defined in <a id="id18" class="footnote_reference" href="#protocol-jubjub">13</a>, returning an error if
|
||||
as defined in <a id="id21" class="footnote_reference" href="#protocol-jubjub">14</a>, returning an error if
|
||||
<span class="math">\(\bot\)</span>
|
||||
is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails.</li>
|
||||
<li>SerializeScalar: Implemented by outputting the little-endian 32-byte encoding of the Scalar value.</li>
|
||||
<li>DeserializeScalar: Implemented by attempting to deserialize a Scalar from a little-endian 32-byte string. This function can fail if the input does not represent a Scalar in the range [0, <code>G.Order()</code> - 1].</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Hash (<code>H</code>): BLAKE2b-512 <a id="id19" class="footnote_reference" href="#blake">1</a> (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.
|
||||
<li>Hash (<code>H</code>): BLAKE2b-512 <a id="id22" class="footnote_reference" href="#blake">1</a> (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.
|
||||
<ul>
|
||||
<li>H1(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
<li>H2(m): Implemented by computing BLAKE2b-512("Zcash_RedJubjubH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>. (This is equivalent to
|
||||
<span class="math">\(\mathsf{H}^\circledast(m)\)</span>
|
||||
, as defined by the
|
||||
<span class="math">\(\mathsf{RedJubjub}\)</span>
|
||||
scheme instantiated in <a id="id20" class="footnote_reference" href="#protocol-concretereddsa">10</a>.)</li>
|
||||
scheme instantiated in <a id="id23" class="footnote_reference" href="#protocol-concretereddsa">11</a>.)</li>
|
||||
<li>H3(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
<li>H4(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubM", m).</li>
|
||||
<li>H5(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubC", m).</li>
|
||||
<li>HR(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubA", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Signature verification is as specified in <a id="id21" class="footnote_reference" href="#protocol-concretespendauthsig">11</a> for RedJubjub.</p>
|
||||
<p>Signature verification is as specified in <a id="id24" class="footnote_reference" href="#protocol-concretespendauthsig">12</a> for RedJubjub.</p>
|
||||
</section>
|
||||
<section id="frost-pallas-blake2b-512"><h4><span class="section-heading">FROST(Pallas, BLAKE2b-512)</span><span class="section-anchor"> <a rel="bookmark" href="#frost-pallas-blake2b-512"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h4>
|
||||
<p>This ciphersuite uses Pallas for the Group and BLAKE2b-512 for the Hash function <code>H</code> meant to produce signatures indistinguishable from RedPallas Orchard Spend Authorization Signatures as specified in <a id="id22" class="footnote_reference" href="#protocol-concretespendauthsig">11</a>.</p>
|
||||
<p>This ciphersuite uses Pallas for the Group and BLAKE2b-512 for the Hash function <code>H</code> meant to produce signatures indistinguishable from RedPallas Orchard Spend Authorization Signatures as specified in <a id="id25" class="footnote_reference" href="#protocol-concretespendauthsig">12</a>.</p>
|
||||
<ul>
|
||||
<li>Group: Pallas <a id="id23" class="footnote_reference" href="#protocol-pallasandvesta">14</a> with base point
|
||||
<li>Group: Pallas <a id="id26" class="footnote_reference" href="#protocol-pallasandvesta">15</a> with base point
|
||||
<span class="math">\(\mathcal{G}^{\mathsf{Orchard}}\)</span>
|
||||
as defined in <a id="id24" class="footnote_reference" href="#protocol-concretespendauthsig">11</a>.
|
||||
as defined in <a id="id27" class="footnote_reference" href="#protocol-concretespendauthsig">12</a>.
|
||||
<ul>
|
||||
<li>Order:
|
||||
<span class="math">\(r_\mathbb{P}\)</span>
|
||||
as defined in <a id="id25" class="footnote_reference" href="#protocol-pallasandvesta">14</a>.</li>
|
||||
<li>Identity: as defined in <a id="id26" class="footnote_reference" href="#protocol-pallasandvesta">14</a>.</li>
|
||||
as defined in <a id="id28" class="footnote_reference" href="#protocol-pallasandvesta">15</a>.</li>
|
||||
<li>Identity: as defined in <a id="id29" class="footnote_reference" href="#protocol-pallasandvesta">15</a>.</li>
|
||||
<li>RandomScalar(): Implemented by returning a uniformly random Scalar in the range [0, <code>G.Order()</code> - 1]. Refer to {{frost-randomscalar}} for implementation guidance.</li>
|
||||
<li>SerializeElement(P): Implemented as
|
||||
<span class="math">\(\mathsf{repr}_\mathbb{P}(P)\)</span>
|
||||
as defined in <a id="id27" class="footnote_reference" href="#protocol-pallasandvesta">14</a>.</li>
|
||||
as defined in <a id="id30" class="footnote_reference" href="#protocol-pallasandvesta">15</a>.</li>
|
||||
<li>DeserializeElement(P): Implemented as
|
||||
<span class="math">\(\mathsf{abst}_\mathbb{P}(P)\)</span>
|
||||
as defined in <a id="id28" class="footnote_reference" href="#protocol-pallasandvesta">14</a>, failing if
|
||||
as defined in <a id="id31" class="footnote_reference" href="#protocol-pallasandvesta">15</a>, failing if
|
||||
<span class="math">\(\bot\)</span>
|
||||
is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails.</li>
|
||||
<li>SerializeScalar: Implemented by outputting the little-endian 32-byte encoding of the Scalar value.</li>
|
||||
<li>DeserializeScalar: Implemented by attempting to deserialize a Scalar from a little-endian 32-byte string. This function can fail if the input does not represent a Scalar in the range [0, <code>G.Order()</code> - 1].</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Hash (<code>H</code>): BLAKE2b-512 <a id="id29" class="footnote_reference" href="#blake">1</a> (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.
|
||||
<li>Hash (<code>H</code>): BLAKE2b-512 <a id="id32" class="footnote_reference" href="#blake">1</a> (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.
|
||||
<ul>
|
||||
<li>H1(m): Implemented by computing BLAKE2b-512("FROST_RedPallasR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
<li>H2(m): Implemented by computing BLAKE2b-512("Zcash_RedPallasH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>. (This is equivalent to
|
||||
<span class="math">\(\mathsf{H}^\circledast(m)\)</span>
|
||||
, as defined by the
|
||||
<span class="math">\(\mathsf{RedPallas}\)</span>
|
||||
scheme instantiated in <a id="id30" class="footnote_reference" href="#protocol-concretereddsa">10</a>.)</li>
|
||||
scheme instantiated in <a id="id33" class="footnote_reference" href="#protocol-concretereddsa">11</a>.)</li>
|
||||
<li>H3(m): Implemented by computing BLAKE2b-512("FROST_RedPallasN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
<li>H4(m): Implemented by computing BLAKE2b-512("FROST_RedPallasM", m).</li>
|
||||
<li>H5(m): Implemented by computing BLAKE2b-512("FROST_RedPallasC", m).</li>
|
||||
<li>HR(m): Implemented by computing BLAKE2b-512("FROST_RedPallasA", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo <code>G.Order()</code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Signature verification is as specified in <a id="id31" class="footnote_reference" href="#protocol-concretespendauthsig">11</a> for RedPallas.</p>
|
||||
<p>Signature verification is as specified in <a id="id34" class="footnote_reference" href="#protocol-concretespendauthsig">12</a> for RedPallas.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="rationale"><h2><span class="section-heading">Rationale</span><span class="section-anchor"> <a rel="bookmark" href="#rationale"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<p>FROST is a threshold Schnorr signature scheme, and Zcash Spend Authorization are also Schnorr signatures, which allows the usage of FROST with Zcash. However, since there is no widespread standard for Schnorr signatures, it must be ensured that the signatures generated by the FROST variant specified in this ZIP can be verified successfully by a Zcash implementation following its specification. In practice this entails making sure that the generated signature can be verified by the
|
||||
<span class="math">\(\mathsf{RedDSA.Validate}\)</span>
|
||||
function specified in <a id="id32" class="footnote_reference" href="#protocol-concretereddsa">10</a>:</p>
|
||||
function specified in <a id="id35" class="footnote_reference" href="#protocol-concretereddsa">11</a>:</p>
|
||||
<ul>
|
||||
<li>The FROST signature, when split into R and S in the first step of
|
||||
<span class="math">\(\mathsf{RedDSA.Validate}\)</span>
|
||||
|
@ -229,11 +239,11 @@ def randomizer_generate():
|
|||
<span class="math">\(\mathsf{H}^\circledast(m)\)</span>
|
||||
Zcash function in the ciphersuites, and making sure its input will be the same. Fortunately FROST and Zcash use the same input order (R, public key, message) so we just need to make sure that SerializeElement (used to compute the encoded public key before passing to the hash function) matches what
|
||||
<span class="math">\(\mathsf{RedDSA.Validate}\)</span>
|
||||
expects; which is possible since both <cite>R</cite> and <cite>vk</cite> (the public key) are encoded in the same way in Zcash.</li>
|
||||
expects; which is possible since both <cite>R</cite> and <cite>vk</cite> (the public key) are encoded in the same way as in Zcash.</li>
|
||||
<li>Note that <code>r</code> (and thus <code>R</code>) will not be generated as specified in RedDSA.Sign. This is not an issue however, since with Schnorr signatures it does not matter for the verifier how the <code>r</code> value was chosen, it just needs to be generated uniformly at random, which is true for FROST.</li>
|
||||
<li>The above will ensure that the verification equation in
|
||||
<span class="math">\(\mathsf{RedDSA.Validate}\)</span>
|
||||
will pass, since FROST ensures the exact same equation will be valid as described in <a id="id33" class="footnote_reference" href="#frost-primeorderverify">7</a>.</li>
|
||||
will pass, since FROST ensures the exact same equation will be valid as described in <a id="id36" class="footnote_reference" href="#frost-primeorderverify">7</a>.</li>
|
||||
</ul>
|
||||
<p>The second step is adding the re-randomization functionality so that each FROST signing generates a re-randomized signature:</p>
|
||||
<ul>
|
||||
|
@ -245,8 +255,8 @@ def randomizer_generate():
|
|||
, which refers to the randomizer as
|
||||
<span class="math">\(\alpha\)</span>
|
||||
) and <code>sum(lambda_i * c * (sk_i + randomizer))</code>. The latter can be rewritten as <code>c * (sum(lambda_i * sk_i) + randomizer *
|
||||
sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Shamir secret sharing mechanism used by FROST, and since <code>sum(lambda_i) == 1</code> <a id="id34" class="footnote_reference" href="#sum-lambda-proof">15</a>, we arrive at <code>c * (sk + randomizer)</code> as required.</li>
|
||||
<li>The re-randomization procedure must be exactly the same as in <a id="id35" class="footnote_reference" href="#protocol-concretereddsa">10</a> to ensure that re-randomized keys are uniformly distributed and signatures are unlinkable. This is also true; observe that <code>randomizer_generate</code> is exactly the same as
|
||||
sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Shamir secret sharing mechanism used by FROST, and since <code>sum(lambda_i) == 1</code> <a id="id37" class="footnote_reference" href="#sum-lambda-proof">17</a>, we arrive at <code>c * (sk + randomizer)</code> as required.</li>
|
||||
<li>The re-randomization procedure must be exactly the same as in <a id="id38" class="footnote_reference" href="#protocol-concretereddsa">11</a> to ensure that re-randomized keys are uniformly distributed and signatures are unlinkable. This is also true; observe that <code>randomizer_generate</code> generates randomizer uniformly at random as required by
|
||||
<span class="math">\(\mathsf{RedDSA.GenRandom}\)</span>
|
||||
; and signature generation is compatible with
|
||||
<span class="math">\(\mathsf{RedDSA.RandomizedPrivate}\)</span>
|
||||
|
@ -260,7 +270,7 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
</ul>
|
||||
</section>
|
||||
<section id="reference-implementation"><h2><span class="section-heading">Reference implementation</span><span class="section-anchor"> <a rel="bookmark" href="#reference-implementation"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<p>TODO: add links to implementation</p>
|
||||
<p>The <cite>reddsa</cite> crate <a id="id39" class="footnote_reference" href="#crate-reddsa">16</a> contains a re-randomized FROST implementation of both ciphersuites.</p>
|
||||
</section>
|
||||
<section id="references"><h2><span class="section-heading">References</span><span class="section-anchor"> <a rel="bookmark" href="#references"><img width="24" height="24" class="section-anchor" src="assets/images/section-anchor.png" alt=""></a></span></h2>
|
||||
<table id="blake" class="footnote">
|
||||
|
@ -335,10 +345,18 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="protocol-concretereddsa" class="footnote">
|
||||
<table id="frost-serialization" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>10</th>
|
||||
<td><a href="https://frost.zfnd.org/user/serialization.html">The ZF FROST Book, Serialization Format</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="protocol-concretereddsa" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>11</th>
|
||||
<td><a href="protocol/protocol.pdf#concretereddsa">Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -346,7 +364,7 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
<table id="protocol-concretespendauthsig" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>11</th>
|
||||
<th>12</th>
|
||||
<td><a href="protocol/protocol.pdf#concretespendauthsig">Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -354,7 +372,7 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
<table id="protocol-spendauthsig" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>12</th>
|
||||
<th>13</th>
|
||||
<td><a href="protocol/protocol.pdf#spendauthsig">Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 4.15: Spend Authorization Signature (Sapling and Orchard)</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -362,7 +380,7 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
<table id="protocol-jubjub" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>13</th>
|
||||
<th>14</th>
|
||||
<td><a href="protocol/protocol.pdf#jubjub">Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -370,15 +388,23 @@ sum(lambda_i)</code>. Since <code>sum(lambda_i * sk_i) == sk</code> per the Sham
|
|||
<table id="protocol-pallasandvesta" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>14</th>
|
||||
<th>15</th>
|
||||
<td><a href="protocol/protocol.pdf#pallasandvesta">Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="crate-reddsa" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>16</th>
|
||||
<td><a href="https://github.com/ZcashFoundation/reddsa">reddsa</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table id="sum-lambda-proof" class="footnote">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>15</th>
|
||||
<th>17</th>
|
||||
<td><a href="https://math.stackexchange.com/questions/1325292/prove-that-the-sum-of-the-lagrange-interpolation-coefficients-is-equal-to-1/1325342#1325342">Prove that the sum of the Lagrange (interpolation) coefficients is equal to 1</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
116
zip-0312.rst
116
zip-0312.rst
|
@ -48,16 +48,18 @@ private key is what effectively allows the user to spend funds.
|
|||
|
||||
This is a security-critical step, since anyone who obtains access to the private
|
||||
key will be able to spend the user's funds. For this reason, one interesting
|
||||
possibility is to require multiple parties to allow the transaction to go through.
|
||||
This can be accomplished with threshold signatures, where the private key is
|
||||
split between parties in a way that a threshold (e.g. 2 out of 3) of them must
|
||||
sign the transaction in order to create the final signature. This enables scenarios
|
||||
such as users and exchanges sharing custody of a wallet, for example.
|
||||
possibility is to require multiple parties to allow the transaction to go
|
||||
through. This can be accomplished with threshold signatures, where the private
|
||||
key is split between parties (or generated already split using a distributed
|
||||
protocol) in a way that a threshold (e.g. 2 out of 3) of them must sign the
|
||||
transaction in order to create the final signature. This enables scenarios such
|
||||
as users and third-party services sharing custody of a wallet, or a group of
|
||||
people managing shared funds, for example.
|
||||
|
||||
FROST is one of such threshold signature protocols. However, it can't be used as-is
|
||||
since the Zcash protocol also requires re-randomizing public and private keys
|
||||
to ensure unlinkability between transactions. This ZIP specifies a variant of
|
||||
FROST with re-randomization support.
|
||||
FROST is one of such threshold signature protocols. However, it can't be used
|
||||
as-is since the Zcash protocol also requires re-randomizing public and private
|
||||
keys to ensure unlinkability between transactions. This ZIP specifies a variant
|
||||
of FROST with re-randomization support.
|
||||
|
||||
|
||||
Requirements
|
||||
|
@ -66,8 +68,9 @@ Requirements
|
|||
- All signatures generated by following this ZIP must be verified successfully
|
||||
as Sapling or Orchard spend authorization signatures using the appropriate
|
||||
validating key.
|
||||
- The signatures generated by following this ZIP should meet the security criteria
|
||||
for Signature with Re-Randomizable Keys as specified in the Zcash protocol [#protocol-concretereddsa]_.
|
||||
- The signatures generated by following this ZIP should meet the security
|
||||
criteria for Signature with Re-Randomizable Keys as specified in the Zcash
|
||||
protocol [#protocol-concretereddsa]_.
|
||||
- The threat model described below must be taken into account.
|
||||
|
||||
Threat Model
|
||||
|
@ -89,9 +92,9 @@ by a single participant, likely the one that created the transaction in the firs
|
|||
place. Note that this user already controls the privacy of the transaction since
|
||||
they are responsible for creating the proof.
|
||||
|
||||
This fits well into the "Coordinator" role from the FROST specification [#frost-protocol]_.
|
||||
The Coordinator is responsible for sending the message to be signed to all participants,
|
||||
and to aggregate the signature shares.
|
||||
This fits well into the "Coordinator" role from the FROST specification
|
||||
[#frost-protocol]_. The Coordinator is responsible for sending the message to be
|
||||
signed to all participants, and to aggregate the signature shares.
|
||||
|
||||
With those considerations in mind, the threat model considered in this ZIP is:
|
||||
|
||||
|
@ -107,7 +110,7 @@ Non-requirements
|
|||
================
|
||||
|
||||
- This ZIP does not support removing the Coordinator role, as described in
|
||||
#[frost-removingcoordinator]_.
|
||||
[#frost-removingcoordinator]_.
|
||||
- This ZIP does not prevent key share holders from linking the signing operation to a
|
||||
transaction in the blockchain.
|
||||
- Like the FROST specification [#FROST]_, this ZIP does not specify a key generation
|
||||
|
@ -122,13 +125,17 @@ Specification
|
|||
Algorithms in this section are specified using Python pseudo-code, in the same
|
||||
fashion as the FROST specification [#FROST]_.
|
||||
|
||||
The types Scalar, Element, and G are defined in #[frost-primeordergroup]_, as
|
||||
The types Scalar, Element, and G are defined in [#frost-primeordergroup]_, as
|
||||
well as the notation for elliptic-curve arithmetic, which uses the additive
|
||||
notation. Note that this notation differs from that used in the Zcash Protocol
|
||||
Specification. For example, ``G.ScalarMult(P, k)`` is used for scalar
|
||||
multiplication, where the protocol spec would use :math:`[k] P` with the group
|
||||
implied by :math:`P`.
|
||||
|
||||
An additional per-ciphersuite hash function is used, denote ``HR(m)``, which
|
||||
receives an arbitrary-sized byte string and returns a Scalar. It is defined
|
||||
concretely in the Ciphersuites section.
|
||||
|
||||
|
||||
Re-randomizable FROST
|
||||
---------------------
|
||||
|
@ -141,33 +148,48 @@ Key Generation
|
|||
''''''''''''''
|
||||
|
||||
While key generation is out of scope for this ZIP and the FROST spec [#FROST]_,
|
||||
it needs to be consistent with FROST, see [#frost-tdkg]_ for guidance. The
|
||||
spend authorization private key :math:`\mathsf{ask}` [#protocol-spendauthsig]_
|
||||
is the particular key that must be used in the context of this ZIP. Note that
|
||||
the :math:`\mathsf{ask}` is usually derived from the spending key :math:`\mathsf{sk}`,
|
||||
though that is not required. This allows using distributed key generation, since
|
||||
the key it generates is unpredictable. Note however that note deriving :math:`\mathsf{ask}`
|
||||
from :math:`\mathsf{sk}` prevents using seed phrases to recover the original
|
||||
secret (which may be something desirable in the context of FROST).
|
||||
it needs to be consistent with FROST, see [#frost-tdkg]_ for guidance. The spend
|
||||
authorization private key :math:`\mathsf{ask}` [#protocol-spendauthsig]_ is the
|
||||
particular key that must be used in the context of this ZIP. Note that the
|
||||
:math:`\mathsf{ask}` is usually derived from the spending key
|
||||
:math:`\mathsf{sk}`, though that is not required. Not doing so allows using
|
||||
distributed key generation, since the key it generates is unpredictable. Note
|
||||
however that not deriving :math:`\mathsf{ask}` from :math:`\mathsf{sk}` prevents
|
||||
using seed phrases to recover the original secret (which may be something
|
||||
desirable in the context of FROST).
|
||||
|
||||
|
||||
Randomizer Generation
|
||||
'''''''''''''''''''''
|
||||
|
||||
A new helper function is defined, which computes :math:`\mathsf{RedDSA.GenRandom}`:
|
||||
A new helper function is defined, which generates a randomizer. The
|
||||
`encode_signing_package` is defined as the byte serialization of the `msg`,
|
||||
`commitment_list` values as described in [#frost-serialization]_.
|
||||
Implementations MAY choose another encoding as long as all values (the message,
|
||||
and the identifier, binding nonce and hiding nonce for each participant) are
|
||||
encoded.
|
||||
|
||||
::
|
||||
|
||||
randomizer_generate():
|
||||
|
||||
Inputs:
|
||||
- None
|
||||
- msg, the message being signed in the current FROST signing run
|
||||
- commitment_list = [(i, hiding_nonce_commitment_i,
|
||||
binding_nonce_commitment_i), ...], a list of commitments issued by
|
||||
each participant, where each element in the list indicates a
|
||||
NonZeroScalar identifier i and two commitment Element values
|
||||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list
|
||||
MUST be sorted in ascending order by identifier.
|
||||
|
||||
Outputs: randomizer, a Scalar
|
||||
|
||||
def randomizer_generate():
|
||||
randomizer_input = random_bytes(64)
|
||||
return H3(randomizer_input)
|
||||
def randomizer_generate(msg, commitment_list):
|
||||
rng_randomizer = G.RandomScalar()
|
||||
rng_randomizer_enc = G.SerializeScalar(rng_randomizer)
|
||||
signing_package_enc = encode_signing_package(commitment_list, msg)
|
||||
randomizer_input = random_bytes(rng_randomizer_enc || signing_package_enc)
|
||||
return HR(randomizer_input)
|
||||
|
||||
|
||||
Round One - Commitment
|
||||
|
@ -196,13 +218,14 @@ transaction hash, which does not convey enough information for the signers to
|
|||
decide if they want to authorize the transaction or not. Therefore, in practice,
|
||||
more data is needed to be sent (over the same encrypted, authenticated channel)
|
||||
from the Coordinator to the signers, possibly the transaction itself, openings of
|
||||
value commitments, decryption of note ciphertexts, etc.; and the signers must check
|
||||
value commitments, decryption of note ciphertexts, etc.; and the signers MUST check
|
||||
that the given SIGHASH matches the data sent from the Coordinator, or compute the
|
||||
SIGHASH themselves from that data. However, the specific mechanism for that process
|
||||
is outside the scope of this ZIP.
|
||||
|
||||
The ``sign`` function remains unchanged, but its inputs must be modified relative
|
||||
to the ``randomizer`` as following:
|
||||
The randomized ``sign`` function is defined as the regular FROST ``sign``
|
||||
function, but with its inputs modified relative to the ``randomizer`` as
|
||||
following:
|
||||
|
||||
- ``sk_i = sk_i + randomizer``
|
||||
- ``group_public_key = group_public_key + G.ScalarBaseMult(randomizer)``
|
||||
|
@ -211,13 +234,15 @@ to the ``randomizer`` as following:
|
|||
Signature Share Verification and Aggregation
|
||||
''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The ``aggregate`` function remains unchanged, but its inputs must be modified
|
||||
relative to the ``randomizer`` as following:
|
||||
The randomized ``aggregate`` function is defined as the regular FROST
|
||||
``aggregate`` function, but with its inputs modified relative to the
|
||||
``randomizer`` as following:
|
||||
|
||||
- ``group_public_key = group_public_key + G.ScalarBaseMult(randomizer)``
|
||||
|
||||
The ``verify_signature_share`` function remains unchanged, but its inputs must be modified
|
||||
relative to the ``randomizer`` as following:
|
||||
The randomized ``verify_signature_share`` function is defined as the regular
|
||||
FROST ``verify_signature_share`` function, but with its inputs modified relative
|
||||
to the ``randomizer`` as following:
|
||||
|
||||
- ``PK_i = PK_i + G.ScalarBaseMult(randomizer)``
|
||||
- ``group_public_key = group_public_key + G.ScalarBaseMult(randomizer)``
|
||||
|
@ -270,6 +295,9 @@ Authorization Signatures as specified in [#protocol-concretespendauthsig]_.
|
|||
modulo ``G.Order()``.
|
||||
- H4(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubM", m).
|
||||
- H5(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubC", m).
|
||||
- HR(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubA", m), interpreting
|
||||
the 64 bytes as a little-endian integer, and reducing the resulting integer
|
||||
modulo ``G.Order()``.
|
||||
|
||||
Signature verification is as specified in [#protocol-concretespendauthsig]_
|
||||
for RedJubjub.
|
||||
|
@ -315,6 +343,9 @@ Authorization Signatures as specified in [#protocol-concretespendauthsig]_.
|
|||
modulo ``G.Order()``.
|
||||
- H4(m): Implemented by computing BLAKE2b-512("FROST_RedPallasM", m).
|
||||
- H5(m): Implemented by computing BLAKE2b-512("FROST_RedPallasC", m).
|
||||
- HR(m): Implemented by computing BLAKE2b-512("FROST_RedPallasA", m), interpreting
|
||||
the 64 bytes as a little-endian integer, and reducing the resulting integer
|
||||
modulo ``G.Order()``.
|
||||
|
||||
Signature verification is as specified in [#protocol-concretespendauthsig]_
|
||||
for RedPallas.
|
||||
|
@ -344,7 +375,7 @@ by the :math:`\mathsf{RedDSA.Validate}` function specified in
|
|||
so we just need to make sure that SerializeElement (used to compute the
|
||||
encoded public key before passing to the hash function) matches what
|
||||
:math:`\mathsf{RedDSA.Validate}` expects; which is possible since both `R` and
|
||||
`vk` (the public key) are encoded in the same way in Zcash.
|
||||
`vk` (the public key) are encoded in the same way as in Zcash.
|
||||
|
||||
- Note that ``r`` (and thus ``R``) will not be generated as specified in RedDSA.Sign.
|
||||
This is not an issue however, since with Schnorr signatures it does not matter
|
||||
|
@ -380,9 +411,9 @@ signing generates a re-randomized signature:
|
|||
- The re-randomization procedure must be exactly the same as in
|
||||
[#protocol-concretereddsa]_ to ensure that re-randomized keys are uniformly
|
||||
distributed and signatures are unlinkable. This is also true; observe that
|
||||
``randomizer_generate`` is exactly the same as
|
||||
:math:`\mathsf{RedDSA.GenRandom}`; and signature generation is compatible with
|
||||
:math:`\mathsf{RedDSA.RandomizedPrivate}`,
|
||||
``randomizer_generate`` generates randomizer uniformly at random as required
|
||||
by :math:`\mathsf{RedDSA.GenRandom}`; and signature generation is compatible
|
||||
with :math:`\mathsf{RedDSA.RandomizedPrivate}`,
|
||||
:math:`\mathsf{RedDSA.RandomizedPublic}`, :math:`\mathsf{RedDSA.Sign}` and
|
||||
:math:`\mathsf{RedDSA.Validate}` as explained in the previous item.
|
||||
|
||||
|
@ -390,7 +421,8 @@ signing generates a re-randomized signature:
|
|||
Reference implementation
|
||||
========================
|
||||
|
||||
TODO: add links to implementation
|
||||
The `reddsa` crate [#crate-reddsa]_ contains a re-randomized FROST implementation of
|
||||
both ciphersuites.
|
||||
|
||||
|
||||
References
|
||||
|
@ -405,9 +437,11 @@ References
|
|||
.. [#frost-primeorderverify] `Draft RFC: Two-Round Threshold Schnorr Signatures with FROST. Appendix B: Schnorr Signature Generation and Verification for Prime-Order Groups <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#name-schnorr-signature-generatio>`_
|
||||
.. [#frost-tdkg] `Draft RFC: Two-Round Threshold Schnorr Signatures with FROST. Appendix B: Trusted Dealer Key Generation <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#name-trusted-dealer-key-generati>`_
|
||||
.. [#frost-randomscalar] `Draft RFC: Two-Round Threshold Schnorr Signatures with FROST. Appendix C: Random Scalar Generation <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#name-random-scalar-generation>`_
|
||||
.. [#frost-serialization] `The ZF FROST Book, Serialization Format <https://frost.zfnd.org/user/serialization.html>`_
|
||||
.. [#protocol-concretereddsa] `Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas <protocol/protocol.pdf#concretereddsa>`_
|
||||
.. [#protocol-concretespendauthsig] `Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard) <protocol/protocol.pdf#concretespendauthsig>`_
|
||||
.. [#protocol-spendauthsig] `Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 4.15: Spend Authorization Signature (Sapling and Orchard) <protocol/protocol.pdf#spendauthsig>`_
|
||||
.. [#protocol-jubjub] `Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub <protocol/protocol.pdf#jubjub>`_
|
||||
.. [#protocol-pallasandvesta] `Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta <protocol/protocol.pdf#pallasandvesta>`_
|
||||
.. [#crate-reddsa] `reddsa <https://github.com/ZcashFoundation/reddsa>`_
|
||||
.. [#sum-lambda-proof] `Prove that the sum of the Lagrange (interpolation) coefficients is equal to 1 <https://math.stackexchange.com/questions/1325292/prove-that-the-sum-of-the-lagrange-interpolation-coefficients-is-equal-to-1/1325342#1325342>`_
|
||||
|
|
Loading…
Reference in New Issue