rfc9591.original.xml | rfc9591.xml | |||
---|---|---|---|---|
<?xml version='1.0' encoding='utf-8'?> | <?xml version='1.0' encoding='UTF-8'?> | |||
<!-- 4/3/2024: SG updated the draft with the update described in | ||||
https://github.com/cfrg/draft-irtf-cfrg-frost/pull/470 | ||||
See related mail with subject: | ||||
Re: Editorial Change to FROST draft | ||||
--> | ||||
<!DOCTYPE rfc [ | <!DOCTYPE rfc [ | |||
<!ENTITY nbsp " "> | <!ENTITY nbsp " "> | |||
<!ENTITY zwsp "​"> | <!ENTITY zwsp "​"> | |||
<!ENTITY nbhy "‑"> | <!ENTITY nbhy "‑"> | |||
<!ENTITY wj "⁠"> | <!ENTITY wj "⁠"> | |||
]> | ]> | |||
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> | ||||
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.6.39 (Ruby 3.2. | <rfc xmlns:xi="http://www.w3.org/2001/XInclude" | |||
2) --> | ipr="trust200902" | |||
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft | docName="draft-irtf-cfrg-frost-15" | |||
-irtf-cfrg-frost-15" category="info" submissionType="IRTF" tocInclude="true" sor | number="9591" | |||
tRefs="true" symRefs="true" version="3"> | category="info" | |||
<!-- xml2rfc v2v3 conversion 3.18.0 --> | submissionType="IRTF" | |||
tocInclude="true" | ||||
sortRefs="true" | ||||
symRefs="true" | ||||
consensus="true" | ||||
xml:lang="en" | ||||
updates="" | ||||
obsoletes="" | ||||
version="3"> | ||||
<front> | <front> | |||
<title abbrev="FROST">Two-Round Threshold Schnorr Signatures with FROST</tit | <title abbrev="The FROST Protocol">The Flexible Round-Optimized Schnorr Thre | |||
le> | shold (FROST) Protocol for Two-Round Schnorr Signatures</title> | |||
<seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-frost-15"/> | <seriesInfo name="RFC" value="9591"/> | |||
<author initials="D." surname="Connolly" fullname="Deirdre Connolly"> | <author initials="D." surname="Connolly" fullname="Deirdre Connolly"> | |||
<organization>Zcash Foundation</organization> | <organization>Zcash Foundation</organization> | |||
<address> | <address> | |||
<email>durumcrustulum@gmail.com</email> | <email>durumcrustulum@gmail.com</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | <author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | |||
<organization>University of Waterloo, Zcash Foundation</organization> | <organization>University of Waterloo, Zcash Foundation</organization> | |||
<address> | <address> | |||
<email>ckomlo@uwaterloo.ca</email> | <email>ckomlo@uwaterloo.ca</email> | |||
skipping to change at line 39 ¶ | skipping to change at line 59 ¶ | |||
<address> | <address> | |||
<email>iang@uwaterloo.ca</email> | <email>iang@uwaterloo.ca</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<author initials="C. A." surname="Wood" fullname="Christopher A. Wood"> | <author initials="C. A." surname="Wood" fullname="Christopher A. Wood"> | |||
<organization>Cloudflare</organization> | <organization>Cloudflare</organization> | |||
<address> | <address> | |||
<email>caw@heapingbits.net</email> | <email>caw@heapingbits.net</email> | |||
</address> | </address> | |||
</author> | </author> | |||
<date year="2023" month="September" day="19"/> | ||||
<area>General</area> | ||||
<workgroup>CFRG</workgroup> | ||||
<keyword>Internet-Draft</keyword> | ||||
<abstract> | ||||
<?line 94?> | ||||
<t>This document specifies the Flexible Round-Optimized Schnorr Threshold (FROST | <date year="2024" month="June"/> | |||
) signing protocol. | ||||
FROST signatures can be issued after a threshold number of entities cooperate to | <workgroup>Crypto Forum</workgroup> | |||
compute a signature, allowing for improved distribution of trust and | <abstract> | |||
redundancy with respect to a secret key. FROST depends only on a prime-order gro | <t>This document specifies the Flexible Round-Optimized Schnorr Threshold | |||
up and cryptographic | (FROST) signing protocol. FROST signatures can be issued after a threshold | |||
hash function. This document specifies a number of ciphersuites to instantiate F | number of entities cooperate to compute a signature, allowing for improved | |||
ROST using different | distribution of trust and redundancy with respect to a secret key. FROST | |||
prime-order groups and hash functions. One such ciphersuite can be used to produ | depends only on a prime-order group and cryptographic hash function. This | |||
ce signatures | document specifies a number of ciphersuites to instantiate FROST using | |||
that can be verified with an Edwards-Curve Digital Signature Algorithm (EdDSA, a | different prime-order groups and hash functions. This document is a product | |||
s defined in RFC8032) | of the Crypto Forum Research Group (CFRG) in the IRTF.</t> | |||
compliant verifier. However, unlike EdDSA, the signatures produced by FROST are | ||||
not deterministic. | ||||
This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF | ||||
.</t> | ||||
</abstract> | </abstract> | |||
<note removeInRFC="true"> | ||||
<name>Discussion Venues</name> | ||||
<t>Discussion of this document takes place on the | ||||
Crypto Forum Research Group mailing list (cfrg@ietf.org), | ||||
which is archived at <eref target="https://mailarchive.ietf.org/arch/search/ | ||||
?email_list=cfrg"/>.</t> | ||||
<t>Source for this draft and an issue tracker can be found at | ||||
<eref target="https://github.com/cfrg/draft-irtf-cfrg-frost"/>.</t> | ||||
</note> | ||||
</front> | </front> | |||
<middle> | <middle> | |||
<?line 106?> | ||||
<section anchor="introduction"> | <section anchor="introduction"> | |||
<name>Introduction</name> | <name>Introduction</name> | |||
<t>RFC EDITOR: PLEASE REMOVE THE FOLLOWING PARAGRAPH The source for this d | ||||
raft is | ||||
maintained in GitHub. Suggested changes should be submitted as pull requests | ||||
at https://github.com/cfrg/draft-irtf-cfrg-frost. Instructions are on that page | ||||
as | ||||
well.</t> | ||||
<t>Unlike signatures in a single-party setting, threshold signatures | <t>Unlike signatures in a single-party setting, threshold signatures | |||
require cooperation among a threshold number of signing participants each holdin g a share | require cooperation among a threshold number of signing participants, each holdi ng a share | |||
of a common private key. The security of threshold schemes in general assumes | of a common private key. The security of threshold schemes in general assumes | |||
that an adversary can corrupt strictly fewer than a threshold number of signer p articipants.</t> | that an adversary can corrupt strictly fewer than a threshold number of signer p articipants.</t> | |||
<t>This document specifies the Flexible Round-Optimized Schnorr Threshold (FROST) signing protocol | <t>This document specifies the Flexible Round-Optimized Schnorr Threshold (FROST) signing protocol | |||
based on the original work in <xref target="FROST20"/>. FROST reduces network ov erhead during | based on the original work in <xref target="FROST20"/>. FROST reduces network ov erhead during | |||
threshold signing operations while employing a novel technique to protect agains t forgery | threshold signing operations while employing a novel technique to protect agains t forgery | |||
attacks applicable to prior Schnorr-based threshold signature constructions. FRO ST requires | attacks applicable to prior Schnorr-based threshold signature constructions. FRO ST requires | |||
two rounds to compute a signature. Single-round signing variants based on <xref target="FROST20"/> are out of scope.</t> | two rounds to compute a signature. Single-round signing variants based on <xref target="FROST20"/> are out of scope.</t> | |||
<t>FROST depends only on a prime-order group and cryptographic hash functi | <t>FROST depends only on a prime-order group and cryptographic hash | |||
on. This document specifies | function. This document specifies a number of ciphersuites to | |||
a number of ciphersuites to instantiate FROST using different prime-order groups | instantiate FROST using different prime-order groups and hash functions. | |||
and hash functions. | ||||
Two ciphersuites can be used to produce signatures that are compatible with Edwa | Two ciphersuites can be used to produce signatures that are compatible | |||
rds-Curve Digital | with Edwards-Curve Digital Signature Algorithm (EdDSA) variants Ed25519 | |||
Signature Algorithm (EdDSA) variants Ed25519 and Ed448 as specified in <xref tar | and Ed448 as specified in <xref target="RFC8032"/>, i.e., the signatures | |||
get="RFC8032"/>, i.e., the | can be verified with a verifier that is compliant with <xref target="RFC80 | |||
signatures can be verified with an <xref target="RFC8032"/> compliant verifier. | 32"/>. | |||
However, unlike EdDSA, the | However, unlike EdDSA, the signatures produced by FROST are | |||
signatures produced by FROST are not deterministic, since deriving nonces determ | not deterministic, since deriving nonces deterministically allows for a | |||
inistically allows | complete key-recovery attack in multi-party, discrete logarithm-based | |||
for a complete key-recovery attack in multi-party discrete logarithm-based signa | signatures.</t> | |||
tures.</t> | ||||
<t>Key generation for FROST signing is out of scope for this document. How ever, for completeness, | <t>Key generation for FROST signing is out of scope for this document. How ever, for completeness, | |||
key generation with a trusted dealer is specified in <xref target="dep-dealer"/> .</t> | key generation with a trusted dealer is specified in <xref target="dep-dealer"/> .</t> | |||
<t>This document represents the consensus of the Crypto Forum Research | <t>This document represents the consensus of the Crypto Forum Research | |||
Group (CFRG). It is not an IETF product and is not a standard.</t> | Group (CFRG). It is not an IETF product and is not a standard.</t> | |||
<t>RFC EDITOR: PLEASE REMOVE THE FOLLOWING SUB-SECTION</t> | ||||
<section anchor="change-log"> | ||||
<name>Change Log</name> | ||||
<t>draft-13 and draft-14</t> | ||||
<ul spacing="normal"> | ||||
<li>Hash group public key into binding computation (#439)</li> | ||||
<li>Finalize test vectors (#442)</li> | ||||
</ul> | ||||
<t>draft-12</t> | ||||
<ul spacing="normal"> | ||||
<li>Address RGLC feedback (#399, #396, #395, #394, #393, #384, #382, # | ||||
397, #378, #376, #375, #374, #373, #371, #370, #369, #368, #367, #366, #364, #36 | ||||
3, #362, #361, #359, #358, #357, #356, #354, #353, #352, #350, #349, #348, #347, | ||||
#314)</li> | ||||
<li>Fix bug in signature share serialization (#397)</li> | ||||
<li>Fix various editorial issues (#385)</li> | ||||
</ul> | ||||
<t>draft-11</t> | ||||
<ul spacing="normal"> | ||||
<li>Update version string constant (#307)</li> | ||||
<li>Make SerializeElement reject the identity element (#306)</li> | ||||
<li>Make ciphersuite requirements explicit (#302)</li> | ||||
<li>Fix various editorial issues (#303, #301, #299, #297)</li> | ||||
</ul> | ||||
<t>draft-10</t> | ||||
<ul spacing="normal"> | ||||
<li>Update version string constant (#296)</li> | ||||
<li>Fix some editorial issues from Ian Goldberg (#295)</li> | ||||
</ul> | ||||
<t>draft-09</t> | ||||
<ul spacing="normal"> | ||||
<li>Add single-signer signature generation to complement RFC8032 funct | ||||
ions (#293)</li> | ||||
<li>Address Thomas Pornin review comments from https://mailarchive.iet | ||||
f.org/arch/msg/crypto-panel/bPyYzwtHlCj00g8YF1tjj-iYP2c/ (#292, #291, #290, #289 | ||||
, #287, #286, #285, #282, #281, #280, #279, #278, #277, #276, #275, #273, #272, | ||||
#267)</li> | ||||
<li>Correct Ed448 ciphersuite (#246)</li> | ||||
<li>Various editorial changes (#241, #240)</li> | ||||
</ul> | ||||
<t>draft-08</t> | ||||
<ul spacing="normal"> | ||||
<li>Add notation for Scalar multiplication (#237)</li> | ||||
<li>Add secp2561k1 ciphersuite (#223)</li> | ||||
<li>Remove RandomScalar implementation details (#231)</li> | ||||
<li>Add domain separation for message and commitment digests (#228)</l | ||||
i> | ||||
</ul> | ||||
<t>draft-07</t> | ||||
<ul spacing="normal"> | ||||
<li>Fix bug in per-rho signer computation (#222)</li> | ||||
</ul> | ||||
<t>draft-06</t> | ||||
<ul spacing="normal"> | ||||
<li>Make verification a per-ciphersuite functionality (#219)</li> | ||||
<li>Use per-signer values of rho to mitigate protocol malleability (#2 | ||||
17)</li> | ||||
<li>Correct prime-order subgroup checks (#215, #211)</li> | ||||
<li>Fix bug in ed25519 ciphersuite description (#205)</li> | ||||
<li>Various editorial improvements (#208, #209, #210, #218)</li> | ||||
</ul> | ||||
<t>draft-05</t> | ||||
<ul spacing="normal"> | ||||
<li>Update test vectors to include version string (#202, #203)</li> | ||||
<li>Rename THRESHOLD_LIMIT to MIN_PARTICIPANTS (#192)</li> | ||||
<li>Use non-contiguous signers for the test vectors (#187)</li> | ||||
<li>Add more reasoning why the coordinator MUST abort (#183)</li> | ||||
<li>Add a function to generate nonces (#182)</li> | ||||
<li>Add MUST that all participants have the same view of VSS commitmen | ||||
t (#174)</li> | ||||
<li>Use THRESHOLD_LIMIT instead of t and MAX_PARTICIPANTS instead of n | ||||
(#171)</li> | ||||
<li>Specify what the dealer is trusted to do (#166)</li> | ||||
<li>Clarify types of NUM_PARTICIPANTS and THRESHOLD_LIMIT (#165)</li> | ||||
<li>Assert that the network channel used for signing should be authent | ||||
icated (#163)</li> | ||||
<li>Remove wire format section (#156)</li> | ||||
<li>Update group commitment derivation to have a single scalarmul (#15 | ||||
0)</li> | ||||
<li>Use RandomNonzeroScalar for single-party Schnorr example (#148)</l | ||||
i> | ||||
<li>Fix group notation and clarify member functions (#145)</li> | ||||
<li>Update existing implementations table (#136)</li> | ||||
<li>Various editorial improvements (#135, #143, #147, #149, #153, #158 | ||||
, #162, #167, #168, #169, #170, #175, #176, #177, #178, #184, #186, #193, #198, | ||||
#199)</li> | ||||
</ul> | ||||
<t>draft-04</t> | ||||
<ul spacing="normal"> | ||||
<li>Added methods to verify VSS commitments and derive group info (#12 | ||||
6, #132).</li> | ||||
<li>Changed check for participants to consider only nonnegative number | ||||
s (#133).</li> | ||||
<li>Changed sampling for secrets and coefficients to allow the zero el | ||||
ement (#130).</li> | ||||
<li>Split test vectors into separate files (#129)</li> | ||||
<li>Update wire structs to remove commitment shares where not necessar | ||||
y (#128)</li> | ||||
<li>Add failure checks (#127)</li> | ||||
<li>Update group info to include each participant's key and clarify ho | ||||
w public key material is obtained (#120, #121).</li> | ||||
<li>Define cofactor checks for verification (#118)</li> | ||||
<li>Various editorial improvements and add contributors (#124, #123, # | ||||
119, #116, #113, #109)</li> | ||||
</ul> | ||||
<t>draft-03</t> | ||||
<ul spacing="normal"> | ||||
<li>Refactor the second round to use state from the first round (#94). | ||||
</li> | ||||
<li>Ensure that verification of signature shares from the second round | ||||
uses commitments from the first round (#94).</li> | ||||
<li>Clarify RFC8032 interoperability based on PureEdDSA (#86).</li> | ||||
<li>Specify signature serialization based on element and scalar serial | ||||
ization (#85).</li> | ||||
<li>Fix hash function domain separation formatting (#83).</li> | ||||
<li>Make trusted dealer key generation deterministic (#104).</li> | ||||
<li>Add additional constraints on participant indexes and nonce usage | ||||
(#105, #103, #98, #97).</li> | ||||
<li>Apply various editorial improvements.</li> | ||||
</ul> | ||||
<t>draft-02</t> | ||||
<ul spacing="normal"> | ||||
<li>Fully specify both rounds of FROST, as well as trusted dealer key | ||||
generation.</li> | ||||
<li>Add ciphersuites and corresponding test vectors, including suites | ||||
for RFC8032 compatibility.</li> | ||||
<li>Refactor document for editorial clarity.</li> | ||||
</ul> | ||||
<t>draft-01</t> | ||||
<ul spacing="normal"> | ||||
<li>Specify operations, notation and cryptographic dependencies.</li> | ||||
</ul> | ||||
<t>draft-00</t> | ||||
<ul spacing="normal"> | ||||
<li>Outline CFRG draft based on draft-komlo-frost.</li> | ||||
</ul> | ||||
</section> | ||||
</section> | </section> | |||
<section anchor="conventions-and-definitions"> | <section anchor="conventions-and-definitions"> | |||
<name>Conventions and Definitions</name> | <name>Conventions and Definitions</name> | |||
<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL | <t> | |||
NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", | The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQU | |||
"MAY", and "OPTIONAL" in this document are to be interpreted as | IRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL | |||
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and | NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14> | |||
only when, they | RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>", | |||
appear in all capitals, as shown here. | "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to | |||
<?line -6?> | be interpreted as | |||
</t> | described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> | |||
when, and only when, they appear in all capitals, as shown here. | ||||
</t> | ||||
<t>The following notation is used throughout the document.</t> | <t>The following notation is used throughout the document.</t> | |||
<ul spacing="normal"> | <dl spacing="normal"> | |||
<li>byte: A sequence of eight bits.</li> | <dt>byte:</dt><dd>A sequence of eight bits.</dd> | |||
<li> | <dt> | |||
<tt>random_bytes(n)</tt>: Outputs <tt>n</tt> bytes, sampled uniformly | <tt>random_bytes(n)</tt>:</dt><dd>Outputs <tt>n</tt> bytes, sampled un | |||
at random | iformly at random | |||
using a cryptographically secure pseudorandom number generator (CSPRNG).</li> | using a cryptographically secure pseudorandom number generator (CSPRNG).</dd> | |||
<li> | <dt> | |||
<tt>count(i, L)</tt>: Outputs the number of times the element <tt>i</t | <tt>count(i, L)</tt>:</dt><dd>Outputs the number of times the element | |||
t> is represented in the list <tt>L</tt>.</li> | <tt>i</tt> is represented in the list <tt>L</tt>.</dd> | |||
<li> | <dt> | |||
<tt>len(l)</tt>: Outputs the length of list <tt>l</tt>, e.g., <tt>len( | <tt>len(l)</tt>:</dt><dd>Outputs the length of list <tt>l</tt>, e.g., | |||
[1,2,3]) = 3</tt>.</li> | <tt>len([1,2,3]) = 3</tt>.</dd> | |||
<li> | <dt> | |||
<tt>reverse(l)</tt>: Outputs the list <tt>l</tt> in reverse order, e.g | <tt>reverse(l)</tt>:</dt><dd>Outputs the list <tt>l</tt> in reverse or | |||
., <tt>reverse([1,2,3]) = [3,2,1]</tt>.</li> | der, e.g., <tt>reverse([1,2,3]) = [3,2,1]</tt>.</dd> | |||
<li> | <dt> | |||
<tt>range(a, b)</tt>: Outputs a list of integers from <tt>a</tt> to <t | <tt>range(a, b)</tt>:</dt><dd>Outputs a list of integers from | |||
t>b-1</tt> in ascending order, e.g., <tt>range(1, 4) = [1,2,3]</tt>.</li> | <tt>a</tt> to <tt>b-1</tt> in ascending order, e.g., <tt>range(1, 4) | |||
<li> | = [1,2,3]</tt>.</dd> <dt> <tt>pow(a, b)</tt>:</dt><dd>Outputs the | |||
<tt>pow(a, b)</tt>: Outputs the result, a Scalar, of <tt>a</tt> to the | result, a Scalar, of <tt>a</tt> to the power of <tt>b</tt>, e.g., | |||
power of <tt>b</tt>, e.g., <tt>pow(2, 3) = 8</tt> modulo the relevant group ord | <tt>pow(2, 3) = 8</tt> modulo the relevant group order | |||
er <tt>p</tt>.</li> | <tt>p</tt>.</dd> | |||
<li>|| denotes concatenation of byte strings, i.e., <tt>x || y</tt> deno | <dt>||:</dt><dd>Denotes concatenation of byte strings, i.e., <tt>x || y< | |||
tes the byte string <tt>x</tt>, immediately followed by | /tt> denotes the byte string <tt>x</tt>, immediately followed by | |||
the byte string <tt>y</tt>, with no extra separator, yielding <tt>xy</tt>.</li> | the byte string <tt>y</tt>, with no extra separator, yielding <tt>xy</tt>.</dd> | |||
<li>nil denotes an empty byte string.</li> | <dt>nil:</dt><dd>Denotes an empty byte string.</dd> | |||
</ul> | </dl> | |||
<t>Unless otherwise stated, we assume that secrets are sampled uniformly a t random | <t>Unless otherwise stated, we assume that secrets are sampled uniformly a t random | |||
using a cryptographically secure pseudorandom number generator (CSPRNG); see | using a CSPRNG; see <xref target="RFC4086"/> for additional guidance on the gene | |||
<xref target="RFC4086"/> for additional guidance on the generation of random num | ration of random numbers.</t> | |||
bers.</t> | ||||
</section> | </section> | |||
<section anchor="cryptographic-dependencies"> | <section anchor="cryptographic-dependencies"> | |||
<name>Cryptographic Dependencies</name> | <name>Cryptographic Dependencies</name> | |||
<t>FROST signing depends on the following cryptographic constructs:</t> | <t>FROST signing depends on the following cryptographic constructs:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Prime-order Group, <xref target="dep-pog"/>;</li> | <li>Prime-order group (<xref target="dep-pog"/>)</li> | |||
<li>Cryptographic hash function, <xref target="dep-hash"/>;</li> | <li>Cryptographic hash function (<xref target="dep-hash"/>)</li> | |||
</ul> | </ul> | |||
<t>These are described in the following sections.</t> | <t>The following sections describe these constructs in more detail.</t> | |||
<section anchor="dep-pog"> | <section anchor="dep-pog"> | |||
<name>Prime-Order Group</name> | <name>Prime-Order Group</name> | |||
<t>FROST depends on an abelian group of prime order <tt>p</tt>. We repre sent this | <t>FROST depends on an abelian group of prime order <tt>p</tt>. We repre sent this | |||
group as the object <tt>G</tt> that additionally defines helper functions descri bed below. The group operation | group as the object <tt>G</tt> that additionally defines helper functions descri bed below. The group operation | |||
for <tt>G</tt> is addition <tt>+</tt> with identity element <tt>I</tt>. For any elements <tt>A</tt> and <tt>B</tt> of the group <tt>G</tt>, | for <tt>G</tt> is addition <tt>+</tt> with identity element <tt>I</tt>. For any elements <tt>A</tt> and <tt>B</tt> of the group <tt>G</tt>, | |||
<tt>A + B = B + A</tt> is also a member of <tt>G</tt>. Also, for any <tt>A</tt> in <tt>G</tt>, there exists an element | <tt>A + B = B + A</tt> is also a member of <tt>G</tt>. Also, for any <tt>A</tt> in <tt>G</tt>, there exists an element | |||
<tt>-A</tt> such that <tt>A + (-A) = (-A) + A = I</tt>. For convenience, we use <tt>-</tt> to denote | <tt>-A</tt> such that <tt>A + (-A) = (-A) + A = I</tt>. For convenience, we use <tt>-</tt> to denote | |||
subtraction, e.g., <tt>A - B = A + (-B)</tt>. Integers, taken modulo the group o rder <tt>p</tt>, are called | subtraction, e.g., <tt>A - B = A + (-B)</tt>. Integers, taken modulo the group o rder <tt>p</tt>, are called | |||
scalars; arithmetic operations on scalars are implicitly performed modulo <tt>p< | "Scalars"; arithmetic operations on Scalars are implicitly performed modulo <tt> | |||
/tt>. Since <tt>p</tt> is prime, | p</tt>. Since <tt>p</tt> is prime, | |||
scalars form a finite field. Scalar multiplication is equivalent to the repeated | Scalars form a finite field. Scalar multiplication is equivalent to the repeated | |||
application of the group operation on an element <tt>A</tt> with itself <tt>r-1< /tt> times, denoted as | application of the group operation on an element <tt>A</tt> with itself <tt>r-1< /tt> times, denoted as | |||
<tt>ScalarMult(A, r)</tt>. We denote the sum, difference, and product of two sca lars using the <tt>+</tt>, <tt>-</tt>, | <tt>ScalarMult(A, r)</tt>. We denote the sum, difference, and product of two Sca lars using the <tt>+</tt>, <tt>-</tt>, | |||
and <tt>*</tt> operators, respectively. (Note that this means <tt>+</tt> may ref er to group element addition or | and <tt>*</tt> operators, respectively. (Note that this means <tt>+</tt> may ref er to group element addition or | |||
scalar addition, depending on the type of the operands.) For any element <tt>A</ tt>, <tt>ScalarMult(A, p) = I</tt>. | Scalar addition, depending on the type of the operands.) For any element <tt>A</ tt>, <tt>ScalarMult(A, p) = I</tt>. | |||
We denote <tt>B</tt> as a fixed generator of the group. Scalar base multiplicati on is equivalent to the repeated application | We denote <tt>B</tt> as a fixed generator of the group. Scalar base multiplicati on is equivalent to the repeated application | |||
of the group operation on <tt>B</tt> with itself <tt>r-1</tt> times, this is den | of the group operation on <tt>B</tt> with itself <tt>r-1</tt> times, denoted as | |||
oted as <tt>ScalarBaseMult(r)</tt>. The set of | <tt>ScalarBaseMult(r)</tt>. The set of | |||
scalars corresponds to <tt>GF(p)</tt>, which we refer to as the scalar field. It | Scalars corresponds to <tt>GF(p)</tt>, which we refer to as the Scalar field. It | |||
is assumed that | is assumed that | |||
group element addition, negation, and equality comparison can be efficiently com puted for | group element addition, negation, and equality comparison can be efficiently com puted for | |||
arbitrary group elements.</t> | arbitrary group elements.</t> | |||
<t>This document uses types <tt>Element</tt> and <tt>Scalar</tt> to deno te elements of the group <tt>G</tt> and | <t>This document uses types <tt>Element</tt> and <tt>Scalar</tt> to deno te elements of the group <tt>G</tt> and | |||
its set of scalars, respectively. We denote Scalar(x) as the conversion of integ er input <tt>x</tt> | its set of Scalars, respectively. We denote Scalar(x) as the conversion of integ er input <tt>x</tt> | |||
to the corresponding Scalar value with the same numeric value. For example, Scal ar(1) yields | to the corresponding Scalar value with the same numeric value. For example, Scal ar(1) yields | |||
a Scalar representing the value 1. Moreover, we use the type <tt>NonZeroScalar</ tt> to denote a <tt>Scalar</tt> | a Scalar representing the value 1. Moreover, we use the type <tt>NonZeroScalar</ tt> to denote a <tt>Scalar</tt> | |||
value that is not equal to zero, i.e., Scalar(0). We denote equality comparison of these types | value that is not equal to zero, i.e., Scalar(0). We denote equality comparison of these types | |||
as <tt>==</tt> and assignment of values by <tt>=</tt>. When comparing Scalar val ues, e.g., for the purposes | as <tt>==</tt> and assignment of values by <tt>=</tt>. When comparing Scalar val ues, e.g., for the purposes | |||
of sorting lists of Scalar values, the least nonnegative representation mod <tt> p</tt> is used.</t> | of sorting lists of Scalar values, the least nonnegative representation mod <tt> p</tt> is used.</t> | |||
<t>We now detail a number of member functions that can be invoked on <tt >G</tt>.</t> | <t>We now detail a number of member functions that can be invoked on <tt >G</tt>.</t> | |||
<ul spacing="normal"> | <dl spacing="normal"> | |||
<li>Order(): Outputs the order of <tt>G</tt> (i.e., <tt>p</tt>).</li> | <dt>Order():</dt><dd>Outputs the order of <tt>G</tt> (i.e., <tt>p</tt> | |||
<li>Identity(): Outputs the identity <tt>Element</tt> of the group (i. | ).</dd> | |||
e., <tt>I</tt>).</li> | <dt>Identity():</dt><dd>Outputs the identity <tt>Element</tt> of the g | |||
<li>RandomScalar(): Outputs a random <tt>Scalar</tt> element in GF(p), | roup (i.e., <tt>I</tt>).</dd> | |||
i.e., a random scalar in [0, p - 1].</li> | <dt>RandomScalar():</dt><dd>Outputs a random <tt>Scalar</tt> element i | |||
<li>ScalarMult(A, k): Outputs the scalar multiplication between Elemen | n GF(p), i.e., a random Scalar in [0, p - 1].</dd> | |||
t <tt>A</tt> and Scalar <tt>k</tt>.</li> | <dt>ScalarMult(A, k):</dt><dd>Outputs the Scalar multiplication betwee | |||
<li>ScalarBaseMult(k): Outputs the scalar multiplication between Scala | n Element <tt>A</tt> and Scalar <tt>k</tt>.</dd> | |||
r <tt>k</tt> and the group generator <tt>B</tt>.</li> | <dt>ScalarBaseMult(k):</dt><dd>Outputs the Scalar multiplication betwe | |||
<li>SerializeElement(A): Maps an <tt>Element</tt> <tt>A</tt> to a cano | en Scalar <tt>k</tt> and the group generator <tt>B</tt>.</dd> | |||
nical byte array <tt>buf</tt> of fixed length <tt>Ne</tt>. This | <dt>SerializeElement(A):</dt><dd>Maps an <tt>Element</tt> <tt>A</tt> t | |||
function raises an error if <tt>A</tt> is the identity element of the group.</li | o a canonical byte array <tt>buf</tt> of fixed length <tt>Ne</tt>. This | |||
> | function raises an error if <tt>A</tt> is the identity element of the group.</dd | |||
<li>DeserializeElement(buf): Attempts to map a byte array <tt>buf</tt> | > | |||
to an <tt>Element</tt> <tt>A</tt>, | <dt>DeserializeElement(buf):</dt><dd>Attempts to map a byte array <tt> | |||
buf</tt> to an <tt>Element</tt> <tt>A</tt> | ||||
and fails if the input is not the valid canonical byte representation of an elem ent of | and fails if the input is not the valid canonical byte representation of an elem ent of | |||
the group. This function raises an error if deserialization fails | the group. This function raises an error if deserialization fails | |||
or if <tt>A</tt> is the identity element of the group; see <xref target="ciphers uites"/> for group-specific | or if <tt>A</tt> is the identity element of the group; see <xref target="ciphers uites"/> for group-specific | |||
input validation steps.</li> | input validation steps.</dd> | |||
<li>SerializeScalar(s): Maps a Scalar <tt>s</tt> to a canonical byte a | <dt>SerializeScalar(s):</dt><dd>Maps a Scalar <tt>s</tt> to a canonica | |||
rray <tt>buf</tt> of fixed length <tt>Ns</tt>.</li> | l byte array <tt>buf</tt> of fixed length <tt>Ns</tt>.</dd> | |||
<li>DeserializeScalar(buf): Attempts to map a byte array <tt>buf</tt> | <dt>DeserializeScalar(buf):</dt><dd>Attempts to map a byte array <tt>b | |||
to a <tt>Scalar</tt> <tt>s</tt>. | uf</tt> to a <tt>Scalar</tt> <tt>s</tt>. | |||
This function raises an error if deserialization fails; see | This function raises an error if deserialization fails; see | |||
<xref target="ciphersuites"/> for group-specific input validation steps.</li> | <xref target="ciphersuites"/> for group-specific input validation steps.</dd> | |||
</ul> | </dl> | |||
</section> | </section> | |||
<section anchor="dep-hash"> | <section anchor="dep-hash"> | |||
<name>Cryptographic Hash Function</name> | <name>Cryptographic Hash Function</name> <t>FROST requires the use of | |||
<t>FROST requires the use of a cryptographically secure hash function, g | a cryptographically secure hash function, generically written as H, | |||
enerically | which is modeled as a random oracle in security proofs for the | |||
written as H, which is modeled as a random oracle in security proofs for the pro | protocol (see <xref target="FROST20"/> and <xref | |||
tocol | target="StrongerSec22"/>). For concrete recommendations on hash | |||
(see <xref target="FROST20"/> and <xref target="StrongerSec22"/>). For concrete | functions that <bcp14>SHOULD</bcp14> be used in practice, see <xref | |||
recommendations on hash functions | target="ciphersuites"/>. Using H, we introduce distinct | |||
which SHOULD be used in practice, see <xref target="ciphersuites"/>. Using H, we | domain-separated hashes H1, H2, H3, H4, and H5:</t> | |||
introduce distinct | ||||
domain-separated hashes, H1, H2, H3, H4, and H5:</t> | ||||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>H1, H2, and H3 map arbitrary byte strings to Scalar elements assoc iated with the prime-order group.</li> | <li>H1, H2, and H3 map arbitrary byte strings to Scalar elements assoc iated with the prime-order group.</li> | |||
<li>H4 and H5 are aliases for H with distinct domain separators.</li> | <li>H4 and H5 are aliases for H with distinct domain separators.</li> | |||
</ul> | </ul> | |||
<t>The details of H1, H2, H3, H4, and H5 vary based on ciphersuite. See | ||||
<xref target="ciphersuites"/> | <t>The details of H1, H2, H3, H4, and H5 vary based on the ciphersuite u | |||
sed. See <xref target="ciphersuites"/> | ||||
for more details about each.</t> | for more details about each.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="helpers"> | <section anchor="helpers"> | |||
<name>Helper Functions</name> | <name>Helper Functions</name> | |||
<t>Beyond the core dependencies, the protocol in this document depends on the | <t>Beyond the core dependencies, the protocol in this document depends on the | |||
following helper operations:</t> | following helper operations:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Nonce generation, <xref target="dep-nonces"/>;</li> | <li>Nonce generation (<xref target="dep-nonces"/>);</li> | |||
<li>Polynomials, <xref target="dep-polynomial"/>;</li> | <li>Polynomials (<xref target="dep-polynomial"/>);</li> | |||
<li>Encoding operations, <xref target="dep-encoding"/>;</li> | <li>List operations (<xref target="dep-encoding"/>);</li> | |||
<li>Signature binding computation <xref target="dep-binding-factor"/>;</ | <li>Binding factors computation (<xref target="dep-binding-factor"/>);</ | |||
li> | li> | |||
<li>Group commitment computation <xref target="dep-group-commit"/>; and< | <li>Group commitment computation (<xref target="dep-group-commit"/>); an | |||
/li> | d</li> | |||
<li>Signature challenge computation <xref target="dep-sig-challenge"/>.< | <li>Signature challenge computation (<xref target="dep-sig-challenge"/>) | |||
/li> | .</li> | |||
</ul> | </ul> | |||
<t>The following sections describe these operations in more detail.</t> | <t>The following sections describe these operations in more detail.</t> | |||
<section anchor="dep-nonces"> | <section anchor="dep-nonces"> | |||
<name>Nonce generation</name> | <name>Nonce Generation</name> | |||
<t>To hedge against a bad RNG that outputs predictable values, nonces ar | <t>To hedge against a bad random number generator (RNG) that outputs pre | |||
e | dictable values, nonces are | |||
generated with the <tt>nonce_generate</tt> function by combining fresh randomnes s | generated with the <tt>nonce_generate</tt> function by combining fresh randomnes s | |||
with the secret key as input to a domain-separated hash function built | with the secret key as input to a domain-separated hash function built | |||
from the ciphersuite hash function <tt>H</tt>. This domain-separated hash functi on | from the ciphersuite hash function <tt>H</tt>. This domain-separated hash functi on | |||
is denoted <tt>H3</tt>. This function always samples 32 bytes of fresh randomnes s | is denoted as <tt>H3</tt>. This function always samples 32 bytes of fresh random ness | |||
to ensure that the probability of nonce reuse is at most 2<sup>-128</sup> | to ensure that the probability of nonce reuse is at most 2<sup>-128</sup> | |||
as long as no more than 2<sup>64</sup> signatures are computed by a given | as long as no more than 2<sup>64</sup> signatures are computed by a given | |||
signing participant.</t> | signing participant.</t> | |||
<artwork><![CDATA[ | ||||
<sourcecode type="pseudocode"><![CDATA[ | ||||
Inputs: | Inputs: | |||
- secret, a Scalar. | - secret, a Scalar. | |||
Outputs: | Outputs: | |||
- nonce, a Scalar. | - nonce, a Scalar. | |||
def nonce_generate(secret): | def nonce_generate(secret): | |||
random_bytes = random_bytes(32) | random_bytes = random_bytes(32) | |||
secret_enc = G.SerializeScalar(secret) | secret_enc = G.SerializeScalar(secret) | |||
return H3(random_bytes || secret_enc) | return H3(random_bytes || secret_enc) | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="dep-polynomial"> | <section anchor="dep-polynomial"> | |||
<name>Polynomials</name> | <name>Polynomials</name> | |||
<t>This section defines polynomials over Scalars that are used in the ma in protocol. | <t>This section defines polynomials over Scalars that are used in the ma in protocol. | |||
A polynomial of maximum degree t is represented as a list of t+1 coefficients, | A polynomial of maximum degree t is represented as a list of t+1 coefficients, | |||
where the constant term of the polynomial is in the first position and the | where the constant term of the polynomial is in the first position and the | |||
highest-degree coefficient is in the last position. For example, the polynomial | highest-degree coefficient is in the last position. For example, the polynomial | |||
<tt>x^2 + 2x + 3</tt> has degree 2 and is represented as a list of 3 coefficient s <tt>[3, 2, 1]</tt>. | <tt>x<sup>2</sup> + 2x + 3</tt> has degree 2 and is represented as a list of thr ee coefficients <tt>[3, 2, 1]</tt>. | |||
A point on the polynomial <tt>f</tt> is a tuple (x, y), where <tt>y = f(x)</tt>. </t> | A point on the polynomial <tt>f</tt> is a tuple (x, y), where <tt>y = f(x)</tt>. </t> | |||
<t>The function <tt>derive_interpolating_value</tt> derives a value used | <t>The function <tt>derive_interpolating_value</tt> derives a value that | |||
for polynomial | is used for polynomial | |||
interpolation. It is provided a list of x-coordinates as input, each of which | interpolation. | |||
It is provided a list of x-coordinates as input, each of which | ||||
cannot equal 0.</t> | cannot equal 0.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- L, the list of x-coordinates, each a NonZeroScalar. | - L, the list of x-coordinates, each a NonZeroScalar. | |||
- x_i, an x-coordinate contained in L, a NonZeroScalar. | - x_i, an x-coordinate contained in L, a NonZeroScalar. | |||
Outputs: | Outputs: | |||
- value, a Scalar. | - value, a Scalar. | |||
Errors: | Errors: | |||
- "invalid parameters", if 1) x_i is not in L, or if 2) any | - "invalid parameters", if 1) x_i is not in L, or if 2) any | |||
x-coordinate is represented more than once in L. | x-coordinate is represented more than once in L. | |||
skipping to change at line 381 ¶ | skipping to change at line 290 ¶ | |||
numerator = Scalar(1) | numerator = Scalar(1) | |||
denominator = Scalar(1) | denominator = Scalar(1) | |||
for x_j in L: | for x_j in L: | |||
if x_j == x_i: continue | if x_j == x_i: continue | |||
numerator *= x_j | numerator *= x_j | |||
denominator *= x_j - x_i | denominator *= x_j - x_i | |||
value = numerator / denominator | value = numerator / denominator | |||
return value | return value | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="dep-encoding"> | <section anchor="dep-encoding"> | |||
<name>List Operations</name> | <name>List Operations</name> | |||
<t>This section describes helper functions that work on lists of values produced | <t>This section describes helper functions that work on lists of values produced | |||
during the FROST protocol. The following function encodes a list of participant | during the FROST protocol. The following function encodes a list of participant | |||
commitments into a byte string for use in the FROST protocol.</t> | commitments into a byte string for use in the FROST protocol.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
Outputs: | Outputs: | |||
- encoded_group_commitment, the serialized representation of | - encoded_group_commitment, the serialized representation of | |||
skipping to change at line 413 ¶ | skipping to change at line 322 ¶ | |||
for (identifier, hiding_nonce_commitment, | for (identifier, hiding_nonce_commitment, | |||
binding_nonce_commitment) in commitment_list: | binding_nonce_commitment) in commitment_list: | |||
encoded_commitment = ( | encoded_commitment = ( | |||
G.SerializeScalar(identifier) || | G.SerializeScalar(identifier) || | |||
G.SerializeElement(hiding_nonce_commitment) || | G.SerializeElement(hiding_nonce_commitment) || | |||
G.SerializeElement(binding_nonce_commitment)) | G.SerializeElement(binding_nonce_commitment)) | |||
encoded_group_commitment = ( | encoded_group_commitment = ( | |||
encoded_group_commitment || | encoded_group_commitment || | |||
encoded_commitment) | encoded_commitment) | |||
return encoded_group_commitment | return encoded_group_commitment | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The following function is used to extract identifiers from a commitme nt list.</t> | <t>The following function is used to extract identifiers from a commitme nt list.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
Outputs: | Outputs: | |||
- identifiers, a list of NonZeroScalar values. | - identifiers, a list of NonZeroScalar values. | |||
def participants_from_commitment_list(commitment_list): | def participants_from_commitment_list(commitment_list): | |||
identifiers = [] | identifiers = [] | |||
for (identifier, _, _) in commitment_list: | for (identifier, _, _) in commitment_list: | |||
identifiers.append(identifier) | identifiers.append(identifier) | |||
return identifiers | return identifiers | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The following function is used to extract a binding factor from a lis | <t keepWithNext="true">The following function is used to extract a bindi | |||
t of binding factors.</t> | ng factor from a list of binding factors.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- binding_factor_list = [(i, binding_factor), ...], | - binding_factor_list = [(i, binding_factor), ...], | |||
a list of binding factors for each participant, where each element | a list of binding factors for each participant, where each element | |||
in the list indicates a NonZeroScalar identifier i and Scalar | in the list indicates a NonZeroScalar identifier i and Scalar | |||
binding factor. | binding factor. | |||
- identifier, participant identifier, a NonZeroScalar. | - identifier, participant identifier, a NonZeroScalar. | |||
Outputs: | Outputs: | |||
- binding_factor, a Scalar. | - binding_factor, a Scalar. | |||
Errors: | Errors: | |||
- "invalid participant", when the designated participant is | - "invalid participant", when the designated participant is | |||
not known. | not known. | |||
def binding_factor_for_participant(binding_factor_list, identifier): | def binding_factor_for_participant(binding_factor_list, identifier): | |||
for (i, binding_factor) in binding_factor_list: | for (i, binding_factor) in binding_factor_list: | |||
if identifier == i: | if identifier == i: | |||
return binding_factor | return binding_factor | |||
raise "invalid participant" | raise "invalid participant" | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="dep-binding-factor"> | <section anchor="dep-binding-factor"> | |||
<name>Binding Factors Computation</name> | <name>Binding Factors Computation</name> | |||
<t>This section describes the subroutine for computing binding factors b ased | <t>This section describes the subroutine for computing binding factors b ased | |||
on the participant commitment list, message to be signed, and group public key.< | on the participant commitment list, message to be signed, and group publi | |||
/t> | c key.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- group_public_key, the public key corresponding to the group signing | - group_public_key, the public key corresponding to the group signing | |||
key, an Element. | key, an Element. | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
- msg, the message to be signed. | - msg, the message to be signed. | |||
Outputs: | Outputs: | |||
- binding_factor_list, a list of (NonZeroScalar, Scalar) tuples | - binding_factor_list, a list of (NonZeroScalar, Scalar) tuples | |||
representing the binding factors. | representing the binding factors. | |||
def compute_binding_factors(group_public_key, commitment_list, msg): | def compute_binding_factors(group_public_key, commitment_list, msg): | |||
group_public_key_enc = G.SerializeElement(group_public_key) | group_public_key_enc = G.SerializeElement(group_public_key) | |||
// Hashed to a fixed-length. | // Hashed to a fixed length. | |||
msg_hash = H4(msg) | msg_hash = H4(msg) | |||
// Hashed to a fixed-length. | // Hashed to a fixed length. | |||
encoded_commitment_hash = | encoded_commitment_hash = | |||
H5(encode_group_commitment_list(commitment_list)) | H5(encode_group_commitment_list(commitment_list)) | |||
// The encoding of the group public key is a fixed length within a ciphersuite | // The encoding of the group public key is a fixed length | |||
. | // within a ciphersuite. | |||
rho_input_prefix = group_public_key_enc || msg_hash || encoded_commitment_hash | rho_input_prefix = group_public_key_enc || msg_hash || | |||
encoded_commitment_hash | ||||
binding_factor_list = [] | binding_factor_list = [] | |||
for (identifier, hiding_nonce_commitment, | for (identifier, hiding_nonce_commitment, | |||
binding_nonce_commitment) in commitment_list: | binding_nonce_commitment) in commitment_list: | |||
rho_input = rho_input_prefix || G.SerializeScalar(identifier) | rho_input = rho_input_prefix || G.SerializeScalar(identifier) | |||
binding_factor = H1(rho_input) | binding_factor = H1(rho_input) | |||
binding_factor_list.append((identifier, binding_factor)) | binding_factor_list.append((identifier, binding_factor)) | |||
return binding_factor_list | return binding_factor_list | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="dep-group-commit"> | <section anchor="dep-group-commit"> | |||
<name>Group Commitment Computation</name> | <name>Group Commitment Computation</name> | |||
<t>This section describes the subroutine for creating the group commitme nt | <t>This section describes the subroutine for creating the group commitme nt | |||
from a commitment list.</t> | from a commitment list.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
- binding_factor_list = [(i, binding_factor), ...], | - binding_factor_list = [(i, binding_factor), ...], | |||
a list of (NonZeroScalar, Scalar) tuples representing the binding | a list of (NonZeroScalar, Scalar) tuples representing the binding | |||
factor Scalar for the given identifier. | factor Scalar for the given identifier. | |||
skipping to change at line 528 ¶ | skipping to change at line 439 ¶ | |||
binding_factor = binding_factor_for_participant( | binding_factor = binding_factor_for_participant( | |||
binding_factor_list, identifier) | binding_factor_list, identifier) | |||
binding_nonce = G.ScalarMult( | binding_nonce = G.ScalarMult( | |||
binding_nonce_commitment, | binding_nonce_commitment, | |||
binding_factor) | binding_factor) | |||
group_commitment = ( | group_commitment = ( | |||
group_commitment + | group_commitment + | |||
hiding_nonce_commitment + | hiding_nonce_commitment + | |||
binding_nonce) | binding_nonce) | |||
return group_commitment | return group_commitment | |||
]]></artwork> | ]]></sourcecode> | |||
<t>Note that the performance of this algorithm is defined | <t>Note that the performance of this algorithm is defined | |||
naively and scales linearly relative to the number of signers. For improved | naively and scales linearly relative to the number of signers. For improved | |||
performance, the group commitment can be computed using multi-exponentation | performance, the group commitment can be computed using multi-exponentiation | |||
techniques such as Pippinger's algorithm; see <xref target="MultExp"/> for more details.</t> | techniques such as Pippinger's algorithm; see <xref target="MultExp"/> for more details.</t> | |||
</section> | </section> | |||
<section anchor="dep-sig-challenge"> | <section anchor="dep-sig-challenge"> | |||
<name>Signature Challenge Computation</name> | <name>Signature Challenge Computation</name> | |||
<t>This section describes the subroutine for creating the per-message ch allenge.</t> | <t>This section describes the subroutine for creating the per-message ch allenge.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- group_commitment, the group commitment, an Element. | - group_commitment, the group commitment, an Element. | |||
- group_public_key, the public key corresponding to the group signing | - group_public_key, the public key corresponding to the group signing | |||
key, an Element. | key, an Element. | |||
- msg, the message to be signed, a byte string. | - msg, the message to be signed, a byte string. | |||
Outputs: | Outputs: | |||
- challenge, a Scalar. | - challenge, a Scalar. | |||
def compute_challenge(group_commitment, group_public_key, msg): | def compute_challenge(group_commitment, group_public_key, msg): | |||
group_comm_enc = G.SerializeElement(group_commitment) | group_comm_enc = G.SerializeElement(group_commitment) | |||
group_public_key_enc = G.SerializeElement(group_public_key) | group_public_key_enc = G.SerializeElement(group_public_key) | |||
challenge_input = group_comm_enc || group_public_key_enc || msg | challenge_input = group_comm_enc || group_public_key_enc || msg | |||
challenge = H2(challenge_input) | challenge = H2(challenge_input) | |||
return challenge | return challenge | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="frost-spec"> | <section anchor="frost-spec"> | |||
<name>Two-Round FROST Signing Protocol</name> | <name>Two-Round FROST Signing Protocol</name> | |||
<t>This section describes the two-round FROST signing protocol for produci ng Schnorr signatures. | <t>This section describes the two-round FROST signing protocol for produci ng Schnorr signatures. | |||
The protocol is configured to run with a selection of <tt>NUM_PARTICIPANTS</tt> | The protocol is configured to run with a selection of <tt>NUM_PARTICIPANTS | |||
signer participants and a Coordinator. | </tt> signer participants and a Coordinator. | |||
<tt>NUM_PARTICIPANTS</tt> is a positive non-zero integer which MUST be at least | ||||
<tt>MIN_PARTICIPANTS</tt> but | <tt>NUM_PARTICIPANTS</tt> is a positive and | |||
MUST NOT be larger than <tt>MAX_PARTICIPANTS</tt>, where <tt>MIN_PARTICIPANTS &l | non-zero integer that <bcp14>MUST</bcp14> be at least | |||
t;= MAX_PARTICIPANTS</tt>, | <tt>MIN_PARTICIPANTS</tt>, but <bcp14>MUST NOT</bcp14> be larger than | |||
<tt>MIN_PARTICIPANTS</tt> is a positive non-zero integer and <tt>MAX_PARTICIPANT | <tt>MAX_PARTICIPANTS</tt>, where <tt>MIN_PARTICIPANTS <= | |||
S</tt> MUST be a positive integer | MAX_PARTICIPANTS</tt> and <tt>MIN_PARTICIPANTS</tt> is a positive and non-zero | |||
less than the group order. A signer participant, or simply participant, is an en | integer. Additionally, <tt>MAX_PARTICIPANTS</tt> <bcp14>MUST</bcp14> be a positi | |||
tity that is trusted | ve | |||
to hold and use a signing key share. The Coordinator is an entity with the follo | integer less than the group order. | |||
wing responsibilities:</t> | A signer participant, or simply | |||
<ol spacing="normal" type="1"><li>Determining which participants will part | "participant", is an entity that is trusted to hold and use a signing key | |||
icipate (at least MIN_PARTICIPANTS in number);</li> | share. The Coordinator is an entity with the following responsibilities:</ | |||
<li>Coordinating rounds (receiving and forwarding inputs among participa | t> | |||
nts); and</li> | <ol spacing="normal" type="1"><li>Determining the participants that will p | |||
<li>Aggregating signature shares output by each participant, and publish | articipate (at least MIN_PARTICIPANTS in number);</li> | |||
ing the resulting signature.</li> | <li>Coordinating rounds (receiving and forwarding inputs among participa | |||
nts);</li> | ||||
<li>Aggregating signature shares output by each participant; and</li> | ||||
<li>Publishing the resulting signature.</li> | ||||
</ol> | </ol> | |||
<t>FROST assumes that the Coordinator and the set of signer participants a re chosen | <t>FROST assumes that the Coordinator and the set of signer participants a re chosen | |||
externally to the protocol. Note that it is possible to deploy the protocol with out | externally to the protocol. Note that it is possible to deploy the protocol with out | |||
designating a single Coordinator; see <xref target="no-coordinator"/> for more i nformation.</t> | designating a single Coordinator; see <xref target="no-coordinator"/> for more i nformation.</t> | |||
<t>FROST produces signatures that can be verified as if they were produced from a single signer | <t>FROST produces signatures that can be verified as if they were produced from a single signer | |||
using a signing key <tt>s</tt> with corresponding public key <tt>PK</tt>, where <tt>s</tt> is a Scalar | using a signing key <tt>s</tt> with corresponding public key <tt>PK</tt>, where <tt>s</tt> is a Scalar | |||
value and <tt>PK = G.ScalarBaseMult(s)</tt>. As a threshold signing protocol, th e group signing | value and <tt>PK = G.ScalarBaseMult(s)</tt>. As a threshold signing protocol, th e group signing | |||
key <tt>s</tt> is Shamir secret-shared amongst each of the <tt>MAX_PARTICIPANTS< /tt> participants | key <tt>s</tt> is Shamir secret-shared amongst each of the <tt>MAX_PARTICIPANTS< /tt> participants | |||
and used to produce signatures; see <xref target="dep-shamir"/> for more informa tion about Shamir secret sharing. | and is used to produce signatures; see <xref target="dep-shamir"/> for more info rmation about Shamir secret sharing. | |||
In particular, FROST assumes each participant is configured with the following i nformation:</t> | In particular, FROST assumes each participant is configured with the following i nformation:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>An identifier, which is a NonZeroScalar value denoted <tt>i</tt> in | <li>An identifier, which is a NonZeroScalar value denoted as <tt>i</tt> | |||
the range <tt>[1, MAX_PARTICIPANTS]</tt> | in the range <tt>[1, MAX_PARTICIPANTS]</tt> | |||
and MUST be distinct from the identifier of every other participant.</li> | and <bcp14>MUST</bcp14> be distinct from the identifier of every other participa | |||
nt.</li> | ||||
<li>A signing key <tt>sk_i</tt>, which is a Scalar value representing th e i-th Shamir secret share | <li>A signing key <tt>sk_i</tt>, which is a Scalar value representing th e i-th Shamir secret share | |||
of the group signing key <tt>s</tt>. In particular, <tt>sk_i</tt> is the value < tt>f(i)</tt> on a secret | of the group signing key <tt>s</tt>. In particular, <tt>sk_i</tt> is the value < tt>f(i)</tt> on a secret | |||
polynomial <tt>f</tt> of degree <tt>(MIN_PARTICIPANTS - 1)</tt>, where <tt>s</tt > is <tt>f(0)</tt>. The public key | polynomial <tt>f</tt> of degree <tt>(MIN_PARTICIPANTS - 1)</tt>, where <tt>s</tt > is <tt>f(0)</tt>. The public key | |||
corresponding to this signing key share is <tt>PK_i = G.ScalarBaseMult(sk_i)</tt >.</li> | corresponding to this signing key share is <tt>PK_i = G.ScalarBaseMult(sk_i)</tt >.</li> | |||
</ul> | </ul> | |||
<t>The Coordinator and each participant are additionally configured with c | <t>Additionally, the Coordinator and each participant are configured with | |||
ommon group | common group | |||
information, denoted "group info," which consists of the following:</t> | information, denoted as "group info," which consists of the following:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Group public key, which is an <tt>Element</tt> in <tt>G</tt> denoted | <li>Group public key, which is an <tt>Element</tt> in <tt>G</tt> denoted | |||
<tt>PK</tt>.</li> | as <tt>PK</tt>.</li> | |||
<li>Public keys <tt>PK_i</tt> for each participant, which are <tt>Elemen | <li>Public keys <tt>PK_i</tt> for each participant, which are <tt>Elemen | |||
t</tt> values in <tt>G</tt> denoted <tt>PK_i</tt> | t</tt> values in <tt>G</tt> denoted as <tt>PK_i</tt> | |||
for each <tt>i</tt> in <tt>[1, MAX_PARTICIPANTS]</tt>.</li> | for each <tt>i</tt> in <tt>[1, MAX_PARTICIPANTS]</tt>.</li> | |||
</ul> | </ul> | |||
<t>This document does not specify how this information, including the sign ing key shares, | <t>This document does not specify how this information, including the sign ing key shares, | |||
are configured and distributed to participants. In general, two possible configu | are configured and distributed to participants. | |||
ration | In general, two configuration | |||
mechanisms are possible: one that requires a single, trusted dealer, and the oth | mechanisms are possible: one that requires a single trusted dealer and one | |||
er | that requires performing a distributed key generation protocol. We highlight | |||
which requires performing a distributed key generation protocol. We highlight | the key generation mechanism by a trusted dealer in <xref target="dep-dealer"/> | |||
key generation mechanism by a trusted dealer in <xref target="dep-dealer"/> for | for reference.</t> | |||
reference.</t> | <t>FROST requires two rounds to complete. In the first round, | |||
<t>FROST requires two rounds to complete. In the first round, participants | participants generate and publish one-time-use commitments to be used in | |||
generate | the second round. In the second round, each participant produces a share | |||
and publish one-time-use commitments to be used in the second round. In the seco | of the signature over the Coordinator-chosen message and the other | |||
nd | participant commitments. After the second round is completed, the | |||
round, each participant produces a share of the signature over the Coordinator-c | Coordinator aggregates the signature shares to produce a final | |||
hosen | signature. The Coordinator <bcp14>SHOULD</bcp14> abort the protocol if | |||
message and the other participant commitments. After the second round completes, | the signature is invalid; see <xref target="abort"/> for more | |||
the | information about dealing with invalid signatures and misbehaving | |||
Coordinator aggregates the signature shares to produce a final signature. The Co | participants. This complete interaction (without being aborted) is shown | |||
ordinator | in <xref target="fig-frost"/>.</t> | |||
SHOULD abort if the signature is invalid; see <xref target="abort"/> for more in | ||||
formation about dealing | ||||
with invalid signatures and misbehaving participants. This complete interaction, | ||||
without abort, is shown in <xref target="fig-frost"/>.</t> | ||||
<figure anchor="fig-frost"> | <figure anchor="fig-frost"> | |||
<name>FROST protocol overview</name> | <name>FROST Protocol Overview</name> | |||
<artwork><![CDATA[ | <artwork><![CDATA[ | |||
(group info) (group info, (group info, | (group info) (group info, (group info, | |||
| signing key share) signing key share) | | signing key share) signing key share) | |||
| | | | | | | | |||
v v v | v v v | |||
Coordinator Signer-1 ... Signer-n | Coordinator Signer-1 ... Signer-n | |||
------------------------------------------------------------ | ------------------------------------------------------------ | |||
message | signing request | |||
------------> | ------------> | |||
| | | | |||
== Round 1 (Commitment) == | == Round 1 (Commitment) == | |||
| participant commitment | | | | participant commitment | | | |||
|<-----------------------+ | | |<-----------------------+ | | |||
| ... | | | ... | | |||
| participant commitment (commit state) ==\ | | participant commitment (commit state) ==\ | |||
|<-----------------------------------------+ | | |<-----------------------------------------+ | | |||
| | | | |||
== Round 2 (Signature Share Generation) == | | == Round 2 (Signature Share Generation) == | | |||
message | ||||
------------> | ||||
| | | | | | |||
| participant input | | | | | participant input | | | | |||
+------------------------> | | | +------------------------> | | | |||
| signature share | | | | | signature share | | | | |||
|<-----------------------+ | | | |<-----------------------+ | | | |||
| ... | | | | ... | | | |||
| participant input | | | | participant input | | | |||
+------------------------------------------> / | +------------------------------------------> / | |||
| signature share |<=======/ | | signature share |<=======/ | |||
<------------------------------------------+ | <------------------------------------------+ | |||
| | | | |||
== Aggregation == | == Aggregation == | |||
| | | | |||
signature | | signature | | |||
<-----------+ | <-----------+ | |||
]]></artwork> | ]]></artwork> | |||
</figure> | </figure> | |||
<t>Details for round one are described in <xref target="frost-round-one"/> | <t>Details for round one are described in <xref target="frost-round-one"/> | |||
, and details for round two | and details for round two | |||
are described in <xref target="frost-round-two"/>. Note that each participant pe | are described in <xref target="frost-round-two"/>. | |||
rsists some state between | Note that each participant persists some state between | |||
the two rounds, and this state is deleted as described in <xref target="frost-ro | the two rounds; this state is deleted as described in <xref target="frost-round- | |||
und-two"/>. The final | two"/>. The final | |||
Aggregation step is described in <xref target="frost-aggregation"/>.</t> | Aggregation step is described in <xref target="frost-aggregation"/>.</t> | |||
<t>FROST assumes that all inputs to each round, especially those of which | <t>FROST assumes that all inputs to each round, especially those that are | |||
are received | received | |||
over the network, are validated before use. In particular, this means that any v | over the network, are validated before use. | |||
alue | In particular, this means that any value of type Element or Scalar received | |||
of type Element or Scalar received over the network MUST be deserialized using D | over the network <bcp14>MUST</bcp14> be deserialized using DeserializeElement | |||
eserializeElement | and DeserializeScalar, respectively, as these functions perform the necessary | |||
and DeserializeScalar, respectively, as these functions perform the necessary in | input validation steps. Additionally, all messages sent over the wire | |||
put validation steps, | <bcp14>MUST</bcp14> be encoded using their respective functions, e.g., Scalars | |||
and that all messages sent over the wire MUST be encoded appropriately, e.g., th | and Elements are encoded using SerializeScalar and SerializeElement.</t> | |||
at Scalars and Elements are | ||||
encoded using their respective functions SerializeScalar and SerializeElement.</ | ||||
t> | ||||
<t>FROST assumes reliable message delivery between the Coordinator and par ticipants in | <t>FROST assumes reliable message delivery between the Coordinator and par ticipants in | |||
order for the protocol to complete. An attacker masquerading as another particip ant | order for the protocol to complete. An attacker masquerading as another particip ant | |||
will result only in an invalid signature; see <xref target="sec-considerations"/ >. However, in order | will result only in an invalid signature; see <xref target="sec-considerations"/ >. However, in order | |||
to identify misbehaving participants, | to identify misbehaving participants, | |||
we assume that the network channel is additionally authenticated; confidentialit y is | we assume that the network channel is additionally authenticated; confidentialit y is | |||
not required.</t> | not required.</t> | |||
<section anchor="frost-round-one"> | <section anchor="frost-round-one"> | |||
<name>Round One - Commitment</name> | <name>Round One - Commitment</name> | |||
<t>Round one involves each participant generating nonces and their corre sponding public commitments. | <t>Round one involves each participant generating nonces and their corre sponding public commitments. | |||
A nonce is a pair of Scalar values, and a commitment is a pair of Element values | A nonce is a pair of Scalar values, and a commitment is a pair of Element values | |||
. Each participant's | . Each participant's behavior in this round is described by the <tt>commit</tt> | |||
behavior in this round is described by the <tt>commit</tt> function below. Note | function below. Note that this function invokes <tt>nonce_generate</tt> twice, o | |||
that this function | nce for each type of nonce produced. The output of this function is a pair of se | |||
invokes <tt>nonce_generate</tt> twice, once for each type of nonce produced. The | cret nonces <tt>(hiding_nonce, binding_nonce)</tt> and their corresponding publi | |||
output of this function is | c commitments | |||
a pair of secret nonces <tt>(hiding_nonce, binding_nonce)</tt> and their corresp | ||||
onding public commitments | ||||
<tt>(hiding_nonce_commitment, binding_nonce_commitment)</tt>.</t> | <tt>(hiding_nonce_commitment, binding_nonce_commitment)</tt>.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- sk_i, the secret key share, a Scalar. | - sk_i, the secret key share, a Scalar. | |||
Outputs: | Outputs: | |||
- (nonce, comm), a tuple of nonce and nonce commitment pairs, | - (nonce, comm), a tuple of nonce and nonce commitment pairs, | |||
where each value in the nonce pair is a Scalar and each value in | where each value in the nonce pair is a Scalar and each value in | |||
the nonce commitment pair is an Element. | the nonce commitment pair is an Element. | |||
def commit(sk_i): | def commit(sk_i): | |||
hiding_nonce = nonce_generate(sk_i) | hiding_nonce = nonce_generate(sk_i) | |||
binding_nonce = nonce_generate(sk_i) | binding_nonce = nonce_generate(sk_i) | |||
hiding_nonce_commitment = G.ScalarBaseMult(hiding_nonce) | hiding_nonce_commitment = G.ScalarBaseMult(hiding_nonce) | |||
binding_nonce_commitment = G.ScalarBaseMult(binding_nonce) | binding_nonce_commitment = G.ScalarBaseMult(binding_nonce) | |||
nonces = (hiding_nonce, binding_nonce) | nonces = (hiding_nonce, binding_nonce) | |||
comms = (hiding_nonce_commitment, binding_nonce_commitment) | comms = (hiding_nonce_commitment, binding_nonce_commitment) | |||
return (nonces, comms) | return (nonces, comms) | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The outputs <tt>nonce</tt> and <tt>comm</tt> from participant <tt>P_i </tt> are both stored locally and | <t>The outputs <tt>nonce</tt> and <tt>comm</tt> from participant <tt>P_i </tt> are both stored locally and | |||
kept for use in the second round. The <tt>nonce</tt> value is secret and MUST NO | kept for use in the second round. The <tt>nonce</tt> value is secret and <bcp14> | |||
T be shared, whereas | MUST NOT</bcp14> be shared, whereas | |||
the public output <tt>comm</tt> is sent to the Coordinator. The nonce values pro | the public output <tt>comm</tt> is sent to the Coordinator. The nonce values pro | |||
duced by this | duced by this function <bcp14>MUST NOT</bcp14> be used in more than one invocati | |||
function MUST NOT be used in more than one invocation of <tt>sign</tt>, and the | on of <tt>sign</tt>, and the nonces <bcp14>MUST</bcp14> be generated | |||
nonces MUST be generated | ||||
from a source of secure randomness.</t> | from a source of secure randomness.</t> | |||
</section> | </section> | |||
<section anchor="frost-round-two"> | <section anchor="frost-round-two"> | |||
<name>Round Two - Signature Share Generation</name> | <name>Round Two - Signature Share Generation</name> | |||
<t>In round two, the Coordinator is responsible for sending the message | <t>In round two, the Coordinator is responsible for sending the message | |||
to be signed, and | to be signed and choosing the participants that will participate (a number of at | |||
for choosing which participants will participate (of number at least MIN_PARTICI | least MIN_PARTICIPANTS). Signers | |||
PANTS). Signers | additionally require locally held data, specifically their private key and the | |||
additionally require locally held data; specifically, their private key and the | ||||
nonces corresponding to their commitment issued in round one.</t> | nonces corresponding to their commitment issued in round one.</t> | |||
<t>The Coordinator begins by sending each participant the message to be | <t>The Coordinator begins by sending each participant the message to be | |||
signed along with the | signed along with the set of signing commitments for all participants in the par | |||
set of signing commitments for all participants in the participant list. Each pa | ticipant list. Each participant | |||
rticipant | <bcp14>MUST</bcp14> validate the inputs before processing the Coordinator's requ | |||
MUST validate the inputs before processing the Coordinator's request. In particu | est. In particular, | |||
lar, | the signer <bcp14>MUST</bcp14> validate commitment_list, deserializing each grou | |||
the Signer MUST validate commitment_list, deserializing each group Element in th | p Element in the | |||
e | list using DeserializeElement from <xref target="dep-pog"/>. If deserialization | |||
list using DeserializeElement from <xref target="dep-pog"/>. If deserialization | fails, the signer | |||
fails, the Signer | <bcp14>MUST</bcp14> abort the protocol. Moreover, each participant <bcp14>MUST</ | |||
MUST abort the protocol. Moreover, each participant MUST ensure that | bcp14> ensure that | |||
its identifier and commitments (from the first round) appear in commitment_list. | its identifier and commitments (from the first round) appear in commitment_list. | |||
Applications which require that participants not process arbitrary | ||||
input messages are also required to perform relevant application-layer input | Applications that restrict participants from processing arbitrary input | |||
validation checks; see <xref target="message-validation"/> for more details.</t> | messages are also required to perform relevant application-layer input | |||
<t>Upon receipt and successful input validation, each Signer then runs t | validation checks; see <xref target="message-validation"/> for more | |||
he following | details.</t> | |||
<t>Upon receipt and successful input validation, each signer then runs t | ||||
he following | ||||
procedure to produce its own signature share.</t> | procedure to produce its own signature share.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- identifier, identifier i of the participant, a NonZeroScalar. | - identifier, identifier i of the participant, a NonZeroScalar. | |||
- sk_i, Signer secret key share, a Scalar. | - sk_i, signer secret key share, a Scalar. | |||
- group_public_key, public key corresponding to the group signing | - group_public_key, public key corresponding to the group signing | |||
key, an Element. | key, an Element. | |||
- nonce_i, pair of Scalar values (hiding_nonce, binding_nonce) | - nonce_i, pair of Scalar values (hiding_nonce, binding_nonce) | |||
generated in round one. | generated in round one. | |||
- msg, the message to be signed, a byte string. | - msg, the message to be signed, a byte string. | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
Outputs: | Outputs: | |||
- sig_share, a signature share, a Scalar. | - sig_share, a signature share, a Scalar. | |||
def sign(identifier, sk_i, group_public_key, | def sign(identifier, sk_i, group_public_key, | |||
nonce_i, msg, commitment_list): | nonce_i, msg, commitment_list): | |||
# Compute the binding factor(s) | # Compute the binding factor(s) | |||
binding_factor_list = compute_binding_factors(group_public_key, commitment_lis | binding_factor_list = compute_binding_factors(group_public_key, | |||
t, msg) | commitment_list, msg) | |||
binding_factor = binding_factor_for_participant( | binding_factor = binding_factor_for_participant( | |||
binding_factor_list, identifier) | binding_factor_list, identifier) | |||
# Compute the group commitment | # Compute the group commitment | |||
group_commitment = compute_group_commitment( | group_commitment = compute_group_commitment( | |||
commitment_list, binding_factor_list) | commitment_list, binding_factor_list) | |||
# Compute the interpolating value | # Compute the interpolating value | |||
participant_list = participants_from_commitment_list( | participant_list = participants_from_commitment_list( | |||
commitment_list) | commitment_list) | |||
skipping to change at line 754 ¶ | skipping to change at line 678 ¶ | |||
# Compute the per-message challenge | # Compute the per-message challenge | |||
challenge = compute_challenge( | challenge = compute_challenge( | |||
group_commitment, group_public_key, msg) | group_commitment, group_public_key, msg) | |||
# Compute the signature share | # Compute the signature share | |||
(hiding_nonce, binding_nonce) = nonce_i | (hiding_nonce, binding_nonce) = nonce_i | |||
sig_share = hiding_nonce + (binding_nonce * binding_factor) + | sig_share = hiding_nonce + (binding_nonce * binding_factor) + | |||
(lambda_i * sk_i * challenge) | (lambda_i * sk_i * challenge) | |||
return sig_share | return sig_share | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The output of this procedure is a signature share. Each participant t | <t>The output of this procedure is a signature share. Each participant s | |||
hen sends | ends | |||
these shares back to the Coordinator. Each participant MUST delete the nonce and | these shares back to the Coordinator. Each participant <bcp14>MUST</bcp14> delet | |||
corresponding commitment after completing <tt>sign</tt>, and MUST NOT use the no | e the nonce and | |||
nce | corresponding commitment after completing <tt>sign</tt> and <bcp14>MUST NOT</bcp | |||
14> use the nonce | ||||
as input more than once to <tt>sign</tt>.</t> | as input more than once to <tt>sign</tt>.</t> | |||
<t>Note that the <tt>lambda_i</tt> value derived during this procedure d oes not change | <t>Note that the <tt>lambda_i</tt> value derived during this procedure d oes not change | |||
across FROST signing operations for the same signing group. As such, participant s | across FROST signing operations for the same signing group. As such, participant s | |||
can compute it once and store it for reuse across signing sessions.</t> | can compute it once and store it for reuse across signing sessions.</t> | |||
</section> | </section> | |||
<section anchor="frost-aggregation"> | <section anchor="frost-aggregation"> | |||
<name>Signature Share Aggregation</name> | <name>Signature Share Aggregation</name> | |||
<t>After participants perform round two and send their signature shares to the Coordinator, | <t>After participants perform round two and send their signature shares to the Coordinator, | |||
the Coordinator aggregates each share to produce a final signature. Before aggre gating, | the Coordinator aggregates each share to produce a final signature. Before aggre gating, | |||
the Coordinator MUST validate each signature share using DeserializeScalar. If v | the Coordinator <bcp14>MUST</bcp14> validate each signature share using Deserial | |||
alidation | izeScalar. If validation | |||
fails, the Coordinator MUST abort the protocol as the resulting signature will b | fails, the Coordinator <bcp14>MUST</bcp14> abort the protocol, as the resulting | |||
e invalid. | signature will be invalid. | |||
If all signature shares are valid, the Coordinator aggregates them to produce th e final | If all signature shares are valid, the Coordinator aggregates them to produce th e final | |||
signature using the following procedure.</t> | signature using the following procedure.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
binding_nonce_commitment_i), ...], a list of commitments issued by | binding_nonce_commitment_i), ...], a list of commitments issued by | |||
each participant, where each element in the list indicates a | each participant, where each element in the list indicates a | |||
NonZeroScalar identifier i and two commitment Element values | NonZeroScalar identifier i and two commitment Element values | |||
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | (hiding_nonce_commitment_i, binding_nonce_commitment_i). This list | |||
MUST be sorted in ascending order by identifier. | MUST be sorted in ascending order by identifier. | |||
- msg, the message to be signed, a byte string. | - msg, the message to be signed, a byte string. | |||
- group_public_key, public key corresponding to the group signing | - group_public_key, public key corresponding to the group signing | |||
key, an Element. | key, an Element. | |||
- sig_shares, a set of signature shares z_i, Scalar values, for each | - sig_shares, a set of signature shares z_i, Scalar values, for each | |||
participant, of length NUM_PARTICIPANTS, where | participant, of length NUM_PARTICIPANTS, where | |||
MIN_PARTICIPANTS <= NUM_PARTICIPANTS <= MAX_PARTICIPANTS. | MIN_PARTICIPANTS <= NUM_PARTICIPANTS <= MAX_PARTICIPANTS. | |||
Outputs: | Outputs: | |||
- (R, z), a Schnorr signature consisting of an Element R and | - (R, z), a Schnorr signature consisting of an Element R and | |||
Scalar z. | Scalar z. | |||
def aggregate(commitment_list, msg, group_public_key, sig_shares): | def aggregate(commitment_list, msg, group_public_key, sig_shares): | |||
# Compute the binding factors | # Compute the binding factors | |||
binding_factor_list = compute_binding_factors(group_public_key, commitment_lis | binding_factor_list = compute_binding_factors(group_public_key, | |||
t, msg) | commitment_list, msg) | |||
# Compute the group commitment | # Compute the group commitment | |||
group_commitment = compute_group_commitment( | group_commitment = compute_group_commitment( | |||
commitment_list, binding_factor_list) | commitment_list, binding_factor_list) | |||
# Compute aggregated signature | # Compute aggregated signature | |||
z = Scalar(0) | z = Scalar(0) | |||
for z_i in sig_shares: | for z_i in sig_shares: | |||
z = z + z_i | z = z + z_i | |||
return (group_commitment, z) | return (group_commitment, z) | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The output from the aggregation step is the output signature (R, z). The canonical encoding | <t>The output from the aggregation step is the output signature (R, z). The canonical encoding | |||
of this signature is specified in <xref target="ciphersuites"/>.</t> | of this signature is specified in <xref target="ciphersuites"/>.</t> | |||
<t>The Coordinator SHOULD verify this signature using the group public k ey before publishing or | <t>The Coordinator <bcp14>SHOULD</bcp14> verify this signature using the group public key before publishing or | |||
releasing the signature. Signature verification is as specified for the correspo nding | releasing the signature. Signature verification is as specified for the correspo nding | |||
ciphersuite; see <xref target="ciphersuites"/> for details. The aggregate signat ure will verify successfully | ciphersuite; see <xref target="ciphersuites"/> for details. The aggregate signat ure will verify successfully | |||
if all signature shares are valid. Moreover, subsets of valid signature shares w | if all signature shares are valid. Moreover, subsets of valid signature shares w | |||
ill themselves not yield | ill not yield | |||
a valid aggregate signature.</t> | a valid aggregate signature themselves.</t> | |||
<t>If the aggregate signature verification fails, the Coordinator MAY ve | <t>If the aggregate signature verification fails, the Coordinator <bcp14 | |||
rify each signature | >MAY</bcp14> verify each signature | |||
share individually to identify and act on misbehaving participants. The mechanis m for acting on | share individually to identify and act on misbehaving participants. The mechanis m for acting on | |||
a misbehaving participant is out of scope for this specification; see <xref targ et="abort"/> for more information | a misbehaving participant is out of scope for this specification; see <xref targ et="abort"/> for more information | |||
about dealing with invalid signatures and misbehaving participants.</t> | about dealing with invalid signatures and misbehaving participants.</t> | |||
<t>The function for verifying a signature share, denoted <tt>verify_sign | <t>The function for verifying a signature share, denoted as <tt>verify_s | |||
ature_share</tt>, is described below. | ignature_share</tt>, is described below. | |||
Recall that the Coordinator is configured with "group info" which contains | Recall that the Coordinator is configured with "group info" that contains | |||
the group public key <tt>PK</tt> and public keys <tt>PK_i</tt> for each particip | the group public key <tt>PK</tt> and public keys <tt>PK_i</tt> for each particip | |||
ant, so the <tt>group_public_key</tt> and | ant. The <tt>group_public_key</tt> and | |||
<tt>PK_i</tt> function arguments MUST come from that previously stored group inf | <tt>PK_i</tt> function arguments <bcp14>MUST</bcp14> come from that previously s | |||
o.</t> | tored group info.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- identifier, identifier i of the participant, a NonZeroScalar. | - identifier, identifier i of the participant, a NonZeroScalar. | |||
- PK_i, the public key for the i-th participant, where | - PK_i, the public key for the i-th participant, where | |||
PK_i = G.ScalarBaseMult(sk_i), an Element. | PK_i = G.ScalarBaseMult(sk_i), an Element. | |||
- comm_i, pair of Element values in G | - comm_i, pair of Element values in G | |||
(hiding_nonce_commitment, binding_nonce_commitment) generated in | (hiding_nonce_commitment, binding_nonce_commitment) generated in | |||
round one from the i-th participant. | round one from the i-th participant. | |||
- sig_share_i, a Scalar value indicating the signature share as | - sig_share_i, a Scalar value indicating the signature share as | |||
produced in round two from the i-th participant. | produced in round two from the i-th participant. | |||
- commitment_list = [(i, hiding_nonce_commitment_i, | - commitment_list = [(i, hiding_nonce_commitment_i, | |||
skipping to change at line 846 ¶ | skipping to change at line 771 ¶ | |||
key, an Element. | key, an Element. | |||
- msg, the message to be signed, a byte string. | - msg, the message to be signed, a byte string. | |||
Outputs: | Outputs: | |||
- True if the signature share is valid, and False otherwise. | - True if the signature share is valid, and False otherwise. | |||
def verify_signature_share( | def verify_signature_share( | |||
identifier, PK_i, comm_i, sig_share_i, commitment_list, | identifier, PK_i, comm_i, sig_share_i, commitment_list, | |||
group_public_key, msg): | group_public_key, msg): | |||
# Compute the binding factors | # Compute the binding factors | |||
binding_factor_list = compute_binding_factors(group_public_key, commitment_lis | binding_factor_list = compute_binding_factors(group_public_key, | |||
t, msg) | commitment_list, msg) | |||
binding_factor = binding_factor_for_participant( | binding_factor = binding_factor_for_participant( | |||
binding_factor_list, identifier) | binding_factor_list, identifier) | |||
# Compute the group commitment | # Compute the group commitment | |||
group_commitment = compute_group_commitment( | group_commitment = compute_group_commitment( | |||
commitment_list, binding_factor_list) | commitment_list, binding_factor_list) | |||
# Compute the commitment share | # Compute the commitment share | |||
(hiding_nonce_commitment, binding_nonce_commitment) = comm_i | (hiding_nonce_commitment, binding_nonce_commitment) = comm_i | |||
comm_share = hiding_nonce_commitment + G.ScalarMult( | comm_share = hiding_nonce_commitment + G.ScalarMult( | |||
skipping to change at line 873 ¶ | skipping to change at line 799 ¶ | |||
# Compute the interpolating value | # Compute the interpolating value | |||
participant_list = participants_from_commitment_list( | participant_list = participants_from_commitment_list( | |||
commitment_list) | commitment_list) | |||
lambda_i = derive_interpolating_value(participant_list, identifier) | lambda_i = derive_interpolating_value(participant_list, identifier) | |||
# Compute relation values | # Compute relation values | |||
l = G.ScalarBaseMult(sig_share_i) | l = G.ScalarBaseMult(sig_share_i) | |||
r = comm_share + G.ScalarMult(PK_i, challenge * lambda_i) | r = comm_share + G.ScalarMult(PK_i, challenge * lambda_i) | |||
return l == r | return l == r | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The Coordinator can verify each signature share before first aggregat | <t>The Coordinator can verify each signature share before aggregating and | |||
ing and verifying the | verifying the signature under the group public key. However, since the | |||
signature under the group public key. However, since the aggregate signature is | aggregate signature is valid if all signature shares are valid, this order of | |||
valid if | operations is more expensive if the signature is valid.</t> | |||
all signature shares are valid, this order of operations is more expensive if th | ||||
e | ||||
signature is valid.</t> | ||||
</section> | </section> | |||
<section anchor="abort"> | <section anchor="abort"> | |||
<name>Identifiable Abort</name> | <name>Identifiable Abort</name> | |||
<t>FROST does not provide robustness; i.e, all participants are required to complete the | <t>FROST does not provide robustness; i.e, all participants are required to complete the | |||
protocol honestly in order to generate a valid signature. When the signing proto col | protocol honestly in order to generate a valid signature. When the signing proto col | |||
does not produce a valid signature, the Coordinator SHOULD abort; see <xref targ et="sec-considerations"/> | does not produce a valid signature, the Coordinator <bcp14>SHOULD</bcp14> abort; see <xref target="sec-considerations"/> | |||
for more information about FROST's security properties and the threat model.</t> | for more information about FROST's security properties and the threat model.</t> | |||
<t>As a result of this property, a misbehaving participant can cause a d enial-of-service on | <t>As a result of this property, a misbehaving participant can cause a d enial of service (DoS) on | |||
the signing protocol by contributing malformed signature shares or refusing to p articipate. | the signing protocol by contributing malformed signature shares or refusing to p articipate. | |||
Identifying misbehaving participants that produce invalid shares can be done by checking | Identifying misbehaving participants that produce invalid shares can be done by checking | |||
signature shares from each participant using <tt>verify_signature_share</tt> as described in <xref target="frost-aggregation"/>. | signature shares from each participant using <tt>verify_signature_share</tt> as described in <xref target="frost-aggregation"/>. | |||
FROST assumes the network channel is authenticated to identify which signer misb ehaved. | FROST assumes the network channel is authenticated to identify the signer that m isbehaved. | |||
FROST allows for identifying misbehaving participants that produce invalid signa ture shares | FROST allows for identifying misbehaving participants that produce invalid signa ture shares | |||
as described in <xref target="frost-aggregation"/>. FROST does not provide accom modations for identifying | as described in <xref target="frost-aggregation"/>. FROST does not provide accom modations for identifying | |||
participants that refuse to participate, though applications are assumed to dete ct when participants | participants that refuse to participate, though applications are assumed to dete ct when participants | |||
fail to engage in the signing protocol.</t> | fail to engage in the signing protocol.</t> | |||
<t>In both cases, preventing this type of attack requires the Coordinato r to identify | <t>In both cases, preventing this type of attack requires the Coordinato r to identify | |||
misbehaving participants such that applications can take corrective action. The mechanism | misbehaving participants such that applications can take corrective action. The mechanism | |||
for acting on misbehaving participants is out of scope for this specification. H owever, | for acting on misbehaving participants is out of scope for this specification. H owever, | |||
one reasonable approach would be to remove the misbehaving participant from the set of allowed | one reasonable approach would be to remove the misbehaving participant from the set of allowed | |||
participants in future runs of FROST.</t> | participants in future runs of FROST.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="ciphersuites"> | <section anchor="ciphersuites"> | |||
<name>Ciphersuites</name> | <name>Ciphersuites</name> | |||
<t>A FROST ciphersuite must specify the underlying prime-order group detai ls | <t>A FROST ciphersuite must specify the underlying prime-order group detai ls | |||
and cryptographic hash function. Each ciphersuite is denoted as (Group, Hash), | and cryptographic hash function. Each ciphersuite is denoted as (Group, Hash), | |||
e.g., (ristretto255, SHA-512). This section contains some ciphersuites. | e.g., (ristretto255, SHA-512). This section contains some ciphersuites. | |||
Each ciphersuite also includes a context string, denoted <tt>contextString</tt>, | Each ciphersuite also includes a context string, denoted as <tt>contextString</t | |||
which is an ASCII string literal (with no NULL terminating character).</t> | t>, | |||
<t>The RECOMMENDED ciphersuite is (ristretto255, SHA-512) as described in | which is an ASCII string literal (with no terminating NUL character).</t> | |||
<xref target="recommended-suite"/>. | <t>The <bcp14>RECOMMENDED</bcp14> ciphersuite is (ristretto255, SHA-512) a | |||
s described in <xref target="recommended-suite"/>. | ||||
The (Ed25519, SHA-512) and (Ed448, SHAKE256) ciphersuites are included | The (Ed25519, SHA-512) and (Ed448, SHAKE256) ciphersuites are included | |||
for compatibility with Ed25519 and Ed448 as defined in <xref target="RFC8032"/>. </t> | for compatibility with Ed25519 and Ed448 as defined in <xref target="RFC8032"/>. </t> | |||
<t>The DeserializeElement and DeserializeScalar functions instantiated for a | <t>The DeserializeElement and DeserializeScalar functions instantiated for a | |||
particular prime-order group corresponding to a ciphersuite MUST adhere | particular prime-order group corresponding to a ciphersuite <bcp14>MUST</bcp14> adhere | |||
to the description in <xref target="dep-pog"/>. Validation steps for these funct ions | to the description in <xref target="dep-pog"/>. Validation steps for these funct ions | |||
are described for each of the ciphersuites below. Future ciphersuites MUST | are described for each of the ciphersuites below. Future ciphersuites <bcp14>MUS T</bcp14> | |||
describe how input validation is done for DeserializeElement and DeserializeScal ar.</t> | describe how input validation is done for DeserializeElement and DeserializeScal ar.</t> | |||
<t>Each ciphersuite includes explicit instructions for verifying signature s produced | <t>Each ciphersuite includes explicit instructions for verifying signature s produced | |||
by FROST. Note that these instructions are equivalent to those produced by a sin gle | by FROST. Note that these instructions are equivalent to those produced by a sin gle | |||
participant.</t> | participant.</t> | |||
<t>Each ciphersuite adheres to the requirements in <xref target="ciphersui te-reqs"/>. Future | <t>Each ciphersuite adheres to the requirements in <xref target="ciphersui te-reqs"/>. Future | |||
ciphersuites MUST also adhere to these requirements.</t> | ciphersuites <bcp14>MUST</bcp14> also adhere to these requirements.</t> | |||
<section anchor="frosted25519-sha-512"> | <section anchor="frosted25519-sha-512"> | |||
<name>FROST(Ed25519, SHA-512)</name> | <name>FROST(Ed25519, SHA-512)</name> | |||
<t>This ciphersuite uses edwards25519 for the Group and SHA-512 for the Hash function <tt>H</tt> | <t>This ciphersuite uses edwards25519 for the Group and SHA-512 for the hash function <tt>H</tt> | |||
meant to produce Ed25519-compliant signatures as specified in <xref section="5.1 " sectionFormat="of" target="RFC8032"/>. | meant to produce Ed25519-compliant signatures as specified in <xref section="5.1 " sectionFormat="of" target="RFC8032"/>. | |||
The value of the contextString parameter is "FROST-ED25519-SHA512-v1".</t> | The value of the contextString parameter is "FROST-ED25519-SHA512-v1".</t> | |||
<ul spacing="normal"> | <dl newline="false" spacing="normal"> | |||
<li> | <dt>Group:</dt> <dd><t>edwards25519 <xref target="RFC8032"/>, where Ne | |||
<t>Group: edwards25519 <xref target="RFC8032"/>, where Ne = 32 and N | = 32 and Ns = 32.</t> | |||
s = 32. | <dl newline="false" spacing="normal"> | |||
</t> | <dt>Order():</dt> <dd>Return 2<sup>252</sup> + 2774231777737235353 | |||
<ul spacing="normal"> | 5851937790883648493 (see <xref target="RFC7748"/>).</dd> | |||
<li>Order(): Return 2^252 + 27742317777372353535851937790883648493 | <dt>Identity():</dt> <dd>As defined in <xref target="RFC7748"/>.</ | |||
(see <xref target="RFC7748"/>).</li> | dd> | |||
<li>Identity(): As defined in <xref target="RFC7748"/>.</li> | <dt>RandomScalar():</dt> <dd>Implemented by returning a uniformly | |||
<li>RandomScalar(): Implemented by returning a uniformly random Sc | random Scalar in the range | |||
alar in the range | [0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | |||
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | ntation guidance.</dd> | |||
ntation guidance.</li> | <dt>SerializeElement(A):</dt> <dd>Implemented as specified in <xre | |||
<li>SerializeElement(A): Implemented as specified in <xref section | f section="5.1.2" sectionFormat="comma" target="RFC8032"/>. | |||
="5.1.2" sectionFormat="comma" target="RFC8032"/>. | ||||
Additionally, this function validates that the input element is not the group | Additionally, this function validates that the input element is not the group | |||
identity element.</li> | identity element.</dd> | |||
<li>DeserializeElement(buf): Implemented as specified in <xref sec | <dt>DeserializeElement(buf):</dt> <dd>Implemented as specified in | |||
tion="5.1.3" sectionFormat="comma" target="RFC8032"/>. | <xref section="5.1.3" sectionFormat="comma" target="RFC8032"/>. | |||
Additionally, this function validates that the resulting element is not the grou p | Additionally, this function validates that the resulting element is not the grou p | |||
identity element and is in the prime-order subgroup. If any of these checks fail , | identity element and is in the prime-order subgroup. If any of these checks fail , | |||
deserialization returns an error. The latter check can | deserialization returns an error. The latter check can | |||
be implemented by multiplying the resulting point by the order of the group and | be implemented by multiplying the resulting point by the order of the group and | |||
checking that the result is the identity element. Note that optimizations for | checking that the result is the identity element. Note that optimizations for | |||
this check exist; see <xref target="Pornin22"/>.</li> | this check exist; see <xref target="Pornin22"/>.</dd> | |||
<li>SerializeScalar(s): Implemented by outputting the little-endia | <dt>SerializeScalar(s):</dt> <dd>Implemented by outputting the lit | |||
n 32-byte encoding of | tle-endian 32-byte encoding of | |||
the Scalar value with the top three bits set to zero.</li> | the Scalar value with the top three bits set to zero.</dd> | |||
<li>DeserializeScalar(buf): Implemented by attempting to deseriali | <dt>DeserializeScalar(buf):</dt> <dd>Implemented by attempting to | |||
ze a Scalar from a | deserialize a Scalar from a | |||
little-endian 32-byte string. This function can fail if the input does not | little-endian 32-byte string. This function can fail if the input does not | |||
represent a Scalar in the range [0, <tt>G.Order()</tt> - 1]. Note that this mean s the | represent a Scalar in the range [0, <tt>G.Order()</tt> - 1]. Note that this mean s the | |||
top three bits of the input MUST be zero.</li> | top three bits of the input <bcp14>MUST</bcp14> be zero.</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
<li> | <dt>Hash (<tt>H</tt>):</dt> <dd><t>SHA-512, which has an output of 6 | |||
<t>Hash (<tt>H</tt>): SHA-512, which has 64 bytes of output | 4 bytes.</t> | |||
</t> | <dl newline="false" spacing="normal"> | |||
<ul spacing="normal"> | <dt>H1(m):</dt> <dd>Implemented by computing H(contextString || "r | |||
<li>H1(m): Implemented by computing H(contextString || "rho" || m) | ho" || m), interpreting the 64-byte digest | |||
, interpreting the 64-byte digest | ||||
as a little-endian integer, and reducing the resulting integer modulo | as a little-endian integer, and reducing the resulting integer modulo | |||
2^252+27742317777372353535851937790883648493.</li> | 2<sup>252</sup> + 27742317777372353535851937790883648493.</dd> | |||
<li>H2(m): Implemented by computing H(m), interpreting the 64-byte | <dt>H2(m):</dt> <dd>Implemented by computing H(m), interpreting th | |||
digest | e 64-byte digest | |||
as a little-endian integer, and reducing the resulting integer modulo | as a little-endian integer, and reducing the resulting integer modulo | |||
2^252+27742317777372353535851937790883648493.</li> | 2<sup>252</sup> + 27742317777372353535851937790883648493.</dd> | |||
<li>H3(m): Implemented by computing H(contextString || "nonce" || | <dt>H3(m):</dt> <dd>Implemented by computing H(contextString || "n | |||
m), interpreting the 64-byte digest | once" || m), interpreting the 64-byte digest | |||
as a little-endian integer, and reducing the resulting integer modulo | as a little-endian integer, and reducing the resulting integer modulo | |||
2^252+27742317777372353535851937790883648493.</li> | 2<sup>252</sup> + 27742317777372353535851937790883648493.</dd> | |||
<li>H4(m): Implemented by computing H(contextString || "msg" || m) | <dt>H4(m):</dt> <dd>Implemented by computing H(contextString || "m | |||
.</li> | sg" || m).</dd> | |||
<li>H5(m): Implemented by computing H(contextString || "com" || m) | <dt>H5(m):</dt> <dd>Implemented by computing H(contextString || "c | |||
.</li> | om" || m).</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
</ul> | </dl> | |||
<t>Normally H2 would also include a domain separator, but for compatibil | ||||
ity with <xref target="RFC8032"/>, it is omitted.</t> | <t>Normally, H2 would also include a domain separator; however, for comp | |||
atibility with <xref target="RFC8032"/>, it is omitted.</t> | ||||
<t>Signature verification is as specified in <xref section="5.1.7" secti onFormat="of" target="RFC8032"/> with the | <t>Signature verification is as specified in <xref section="5.1.7" secti onFormat="of" target="RFC8032"/> with the | |||
constraint that implementations MUST check the group equation <tt>[8][z]B = [8]R + [8][c]PK</tt> | constraint that implementations <bcp14>MUST</bcp14> check the group equation <tt >[8][z]B = [8]R + [8][c]PK</tt> | |||
(changed to use the notation in this document).</t> | (changed to use the notation in this document).</t> | |||
<t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | <t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | |||
</section> | </section> | |||
<section anchor="recommended-suite"> | <section anchor="recommended-suite"> | |||
<name>FROST(ristretto255, SHA-512)</name> | <name>FROST(ristretto255, SHA-512)</name> | |||
<t>This ciphersuite uses ristretto255 for the Group and SHA-512 for the Hash function <tt>H</tt>. | <t>This ciphersuite uses ristretto255 for the Group and SHA-512 for the hash function <tt>H</tt>. | |||
The value of the contextString parameter is "FROST-RISTRETTO255-SHA512-v1".</t> | The value of the contextString parameter is "FROST-RISTRETTO255-SHA512-v1".</t> | |||
<ul spacing="normal"> | <dl newline="false" spacing="normal"> | |||
<li> | <dt>Group:</dt> <dd><t>ristretto255 <xref target="RFC9496"/>, where Ne | |||
<t>Group: ristretto255 <xref target="RISTRETTO"/>, | = 32 and Ns = 32.</t> | |||
where Ne = 32 and Ns = 32. | <dl newline="false" spacing="normal"> | |||
</t> | <dt>Order():</dt> <dd>Return 2<sup>252</sup> + 2774231777737235353 | |||
<ul spacing="normal"> | 5851937790883648493 (see <xref target="RFC9496"/>).</dd> | |||
<li>Order(): Return 2^252 + 27742317777372353535851937790883648493 | <dt>Identity():</dt> <dd>As defined in <xref target="RFC9496"/>.</ | |||
(see <xref target="RISTRETTO"/>).</li> | dd> | |||
<li>Identity(): As defined in <xref target="RISTRETTO"/>.</li> | <dt>RandomScalar():</dt> <dd>Implemented by returning a uniformly | |||
<li>RandomScalar(): Implemented by returning a uniformly random Sc | random Scalar in the range | |||
alar in the range | [0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | |||
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | ntation guidance.</dd> | |||
ntation guidance.</li> | <dt>SerializeElement(A):</dt> <dd>Implemented using the "Encode" f | |||
<li>SerializeElement(A): Implemented using the 'Encode' function f | unction from <xref target="RFC9496"/>. | |||
rom <xref target="RISTRETTO"/>. | ||||
Additionally, this function validates that the input element is not the group | Additionally, this function validates that the input element is not the group | |||
identity element.</li> | identity element.</dd> | |||
<li>DeserializeElement(buf): Implemented using the 'Decode' functi | <dt>DeserializeElement(buf):</dt> <dd>Implemented using the "Decod | |||
on from <xref target="RISTRETTO"/>. | e" function from <xref target="RFC9496"/>. | |||
Additionally, this function validates that the resulting element is not the grou p | Additionally, this function validates that the resulting element is not the grou p | |||
identity element. If either 'Decode' or that check fails, deserialization return | identity element. If either the "Decode" function or the check fails, deserializ | |||
s an error.</li> | ation returns an error.</dd> | |||
<li>SerializeScalar(s): Implemented by outputting the little-endia | <dt>SerializeScalar(s):</dt> <dd>Implemented by outputting the lit | |||
n 32-byte encoding of | tle-endian 32-byte encoding of | |||
the Scalar value with the top three bits set to zero.</li> | the Scalar value with the top three bits set to zero.</dd> | |||
<li>DeserializeScalar(buf): Implemented by attempting to deseriali | <dt>DeserializeScalar(buf):</dt> <dd>Implemented by attempting to | |||
ze a Scalar from a | deserialize a Scalar from a | |||
little-endian 32-byte string. This function can fail if the input does not | little-endian 32-byte string. This function can fail if the input does not | |||
represent a Scalar in the range [0, <tt>G.Order()</tt> - 1]. Note that this mean s the | represent a Scalar in the range [0, <tt>G.Order()</tt> - 1]. Note that this mean s the | |||
top three bits of the input MUST be zero.</li> | top three bits of the input <bcp14>MUST</bcp14> be zero.</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
<li> | <dt>Hash (<tt>H</tt>):</dt> <dd><t>SHA-512, which has 64 bytes of outp | |||
<t>Hash (<tt>H</tt>): SHA-512, which has 64 bytes of output | ut.</t> | |||
</t> | <dl newline="false" spacing="normal"> | |||
<ul spacing="normal"> | <dt>H1(m):</dt> <dd>Implemented by computing H(contextString || "rho | |||
<li>H1(m): Implemented by computing H(contextString || "rho" || m) | " || m) and mapping the | |||
and mapping the | output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | |||
output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | get="RFC9496"/>.</dd> | |||
get="RISTRETTO"/>.</li> | <dt>H2(m):</dt> <dd>Implemented by computing H(contextString || "cha | |||
<li>H2(m): Implemented by computing H(contextString || "chal" || m | l" || m) and mapping the | |||
) and mapping the | output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | |||
output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | get="RFC9496"/>.</dd> | |||
get="RISTRETTO"/>.</li> | <dt>H3(m):</dt> <dd>Implemented by computing H(contextString || "n | |||
<li>H3(m): Implemented by computing H(contextString || "nonce" || | once" || m) and mapping the | |||
m) and mapping the | output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | |||
output to a Scalar as described in <xref section="4.4" sectionFormat="comma" tar | get="RFC9496"/>.</dd> | |||
get="RISTRETTO"/>.</li> | <dt>H4(m):</dt> <dd>Implemented by computing H(contextString || "m | |||
<li>H4(m): Implemented by computing H(contextString || "msg" || m) | sg" || m).</dd> | |||
.</li> | <dt>H5(m):</dt> <dd>Implemented by computing H(contextString || "c | |||
<li>H5(m): Implemented by computing H(contextString || "com" || m) | om" || m).</dd> | |||
.</li> | </dl> | |||
</ul> | </dd> | |||
</li> | </dl> | |||
</ul> | ||||
<t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | <t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | |||
<t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | <t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | |||
</section> | </section> | |||
<section anchor="frosted448-shake256"> | <section anchor="frosted448-shake256"> | |||
<name>FROST(Ed448, SHAKE256)</name> | <name>FROST(Ed448, SHAKE256)</name> | |||
<t>This ciphersuite uses edwards448 for the Group and SHAKE256 for the H | <t>This ciphersuite uses edwards448 for the Group and SHAKE256 for the h | |||
ash function <tt>H</tt> | ash function <tt>H</tt> | |||
meant to produce Ed448-compliant signatures as specified in <xref section="5.2" | meant to produce Ed448-compliant signatures as specified in <xref section | |||
sectionFormat="of" target="RFC8032"/>. Note that this | ="5.2" sectionFormat="of" target="RFC8032"/>. | |||
ciphersuite does not allow applications to specify a context string as is allowe | Unlike Ed448 in <xref target="RFC8032"/>, this ciphersuite does not allow app | |||
d for Ed448 | lications to | |||
in <xref target="RFC8032"/>, and always sets the <xref target="RFC8032"/> contex | specify a context string and always sets the context of <xref target="RFC8032 | |||
t string to the empty string. | "/> to the empty string. | |||
The value of the (internal to FROST) contextString parameter is "FROST-ED448-SHA | Note that this ciphersuite does not allow applications to specify a context | |||
KE256-v1".</t> | string as is allowed for Ed448 in <xref target="RFC8032"/>, and always sets | |||
<ul spacing="normal"> | the <xref target="RFC8032"/> context string to the empty string. The value of | |||
<li> | the (internal to FROST) contextString parameter is | |||
<t>Group: edwards448 <xref target="RFC8032"/>, where Ne = 57 and Ns | "FROST-ED448-SHAKE256-v1".</t> | |||
= 57. | <dl newline="false" spacing="normal"> | |||
</t> | <dt>Group:</dt> <dd><t>edwards448 <xref target="RFC8032"/>, where Ne | |||
<ul spacing="normal"> | = 57 and Ns = 57.</t> | |||
<li>Order(): Return 2^446 - 13818066809895115352007386748515426880 | <dl newline="false" spacing="normal"> | |||
336692474882178609894547503885.</li> | <dt>Order():</dt> <dd>Return 2<sup>446</sup> - 1381806680989511535 | |||
<li>Identity(): As defined in <xref target="RFC7748"/>.</li> | 2007386748515426880336692474882178609894547503885.</dd> | |||
<li>RandomScalar(): Implemented by returning a uniformly random Sc | <dt>Identity():</dt> <dd>As defined in <xref target="RFC7748"/>.</ | |||
alar in the range | dd> | |||
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | <dt>RandomScalar():</dt> <dd>Implemented by returning a uniformly | |||
ntation guidance.</li> | random Scalar in the range | |||
<li>SerializeElement(A): Implemented as specified in <xref section | [0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | |||
="5.2.2" sectionFormat="comma" target="RFC8032"/>. | ntation guidance.</dd> | |||
<dt>SerializeElement(A):</dt> <dd>Implemented as specified in <xre | ||||
f section="5.2.2" sectionFormat="comma" target="RFC8032"/>. | ||||
Additionally, this function validates that the input element is not the group | Additionally, this function validates that the input element is not the group | |||
identity element.</li> | identity element.</dd> | |||
<li>DeserializeElement(buf): Implemented as specified in <xref sec | <dt>DeserializeElement(buf):</dt> <dd>Implemented as specified in | |||
tion="5.2.3" sectionFormat="comma" target="RFC8032"/>. | <xref section="5.2.3" sectionFormat="comma" target="RFC8032"/>. | |||
Additionally, this function validates that the resulting element is not the grou p | Additionally, this function validates that the resulting element is not the grou p | |||
identity element and is in the prime-order subgroup. If any of these checks fail , | identity element and is in the prime-order subgroup. If any of these checks fail , | |||
deserialization returns an error. The latter check can | deserialization returns an error. The latter check can | |||
be implemented by multiplying the resulting point by the order of the group and | be implemented by multiplying the resulting point by the order of the group and | |||
checking that the result is the identity element. Note that optimizations for | checking that the result is the identity element. Note that optimizations for | |||
this check exist; see <xref target="Pornin22"/>.</li> | this check exist; see <xref target="Pornin22"/>.</dd> | |||
<li>SerializeScalar(s): Implemented by outputting the little-endia | <dt>SerializeScalar(s):</dt> <dd>Implemented by outputting the lit | |||
n 57-byte encoding of | tle-endian 57-byte encoding of | |||
the Scalar value.</li> | the Scalar value.</dd> | |||
<li>DeserializeScalar(buf): Implemented by attempting to deseriali | <dt>DeserializeScalar(buf):</dt> <dd>Implemented by attempting to | |||
ze a Scalar from a | deserialize a Scalar from a | |||
little-endian 57-byte string. This function can fail if the input does not | little-endian 57-byte string. This function can fail if the input does not | |||
represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</li> | represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
<li> | <dt>Hash (<tt>H</tt>):</dt> <dd><t>SHAKE256 with 114 bytes of output | |||
<t>Hash (<tt>H</tt>): SHAKE256 with 114 bytes of output | .</t> | |||
</t> | <dl newline="false" spacing="normal"> | |||
<ul spacing="normal"> | <dt>H1(m):</dt> <dd>Implemented by computing H(contextString || "r | |||
<li>H1(m): Implemented by computing H(contextString || "rho" || m) | ho" || m), interpreting the | |||
, interpreting the | ||||
114-byte digest as a little-endian integer, and reducing the resulting integer m odulo | 114-byte digest as a little-endian integer, and reducing the resulting integer m odulo | |||
2^446 - 13818066809895115352007386748515426880336692474882178609894547503885.</l | 2<sup>446</sup> - 13818066809895115352007386748515426880336692474882178609894547 | |||
i> | 503885.</dd> | |||
<li>H2(m): Implemented by computing H("SigEd448" || 0 || 0 || m), | <dt>H2(m):</dt> <dd>Implemented by computing H("SigEd448" || 0 || | |||
interpreting | 0 || m), interpreting | |||
the 114-byte digest as a little-endian integer, and reducing the resulting integ er | the 114-byte digest as a little-endian integer, and reducing the resulting integ er | |||
modulo 2^446 - 13818066809895115352007386748515426880336692474882178609894547503 | modulo 2<sup>446</sup> - 1381806680989511535200738674851542688033669247488217860 | |||
885.</li> | 9894547503885.</dd> | |||
<li>H3(m): Implemented by computing H(contextString || "nonce" || | <dt>H3(m):</dt> <dd>Implemented by computing H(contextString || "n | |||
m), interpreting the | once" || m), interpreting the | |||
114-byte digest as a little-endian integer, and reducing the resulting integer m odulo | 114-byte digest as a little-endian integer, and reducing the resulting integer m odulo | |||
2^446 - 13818066809895115352007386748515426880336692474882178609894547503885.</l | 2<sup>446</sup> - 13818066809895115352007386748515426880336692474882178609894547 | |||
i> | 503885.</dd> | |||
<li>H4(m): Implemented by computing H(contextString || "msg" || m) | <dt>H4(m):</dt> <dd>Implemented by computing H(contextString || "m | |||
.</li> | sg" || m).</dd> | |||
<li>H5(m): Implemented by computing H(contextString || "com" || m) | <dt>H5(m):</dt> <dd>Implemented by computing H(contextString || "c | |||
.</li> | om" || m).</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
</ul> | </dl> | |||
<t>Normally H2 would also include a domain separator, but for compatibil | <t>Normally, H2 would also include a domain separator. However, it is om | |||
ity with <xref target="RFC8032"/>, it is omitted.</t> | itted for compatibility with <xref target="RFC8032"/>.</t> | |||
<t>Signature verification is as specified in <xref section="5.2.7" secti onFormat="of" target="RFC8032"/> with the | <t>Signature verification is as specified in <xref section="5.2.7" secti onFormat="of" target="RFC8032"/> with the | |||
constraint that implementations MUST check the group equation <tt>[4][z]B = [4]R + [4][c]PK</tt> | constraint that implementations <bcp14>MUST</bcp14> check the group equation <tt >[4][z]B = [4]R + [4][c]PK</tt> | |||
(changed to use the notation in this document).</t> | (changed to use the notation in this document).</t> | |||
<t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | <t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | |||
</section> | </section> | |||
<section anchor="frostp-256-sha-256"> | <section anchor="frostp-256-sha-256"> | |||
<name>FROST(P-256, SHA-256)</name> | <name>FROST(P-256, SHA-256)</name> | |||
<t>This ciphersuite uses P-256 for the Group and SHA-256 for the Hash fu nction <tt>H</tt>. | <t>This ciphersuite uses P-256 for the Group and SHA-256 for the hash fu nction <tt>H</tt>. | |||
The value of the contextString parameter is "FROST-P256-SHA256-v1".</t> | The value of the contextString parameter is "FROST-P256-SHA256-v1".</t> | |||
<ul spacing="normal"> | <dl newline="false" spacing="normal"> | |||
<li> | <dt>Group:</dt> <dd><t>P-256 (secp256r1) <xref target="x9.62"/>, whe | |||
<t>Group: P-256 (secp256r1) <xref target="x9.62"/>, where Ne = 33 an | re Ne = 33 and Ns = 32.</t> | |||
d Ns = 32. | <dl newline="false" spacing="normal"> | |||
</t> | <dt>Order():</dt> <dd>Return 0xffffffff00000000ffffffffffffffffbce | |||
<ul spacing="normal"> | 6faada7179e84f3b9cac2fc632551.</dd> | |||
<li>Order(): Return 0xffffffff00000000ffffffffffffffffbce6faada717 | <dt>Identity():</dt> <dd>As defined in <xref target="x9.62"/>.</dd | |||
9e84f3b9cac2fc632551.</li> | > | |||
<li>Identity(): As defined in <xref target="x9.62"/>.</li> | <dt>RandomScalar():</dt> <dd>Implemented by returning a uniformly | |||
<li>RandomScalar(): Implemented by returning a uniformly random Sc | random Scalar in the range | |||
alar in the range | [0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | |||
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | ntation guidance.</dd> | |||
ntation guidance.</li> | <dt>SerializeElement(A):</dt> <dd>Implemented using the compressed | |||
<li>SerializeElement(A): Implemented using the compressed Elliptic | Elliptic-Curve-Point-to-Octet-String | |||
-Curve-Point-to-Octet-String | ||||
method according to <xref target="SEC1"/>, yielding a 33-byte output. Additional ly, this function validates | method according to <xref target="SEC1"/>, yielding a 33-byte output. Additional ly, this function validates | |||
that the input element is not the group identity element.</li> | that the input element is not the group identity element.</dd> | |||
<li>DeserializeElement(buf): Implemented by attempting to deserial | ||||
ize a 33-byte input string to | <dt>DeserializeElement(buf):</dt> <dd>Implemented by attempting to | |||
a public key using the compressed Octet-String-to-Elliptic-Curve-Point method ac | deserialize a 33-byte input string to | |||
cording to <xref target="SEC1"/>, | a public key using the compressed Octet-String-to-Elliptic-Curve-Point method ac | |||
and then performs public-key validation as defined in section 3.2.2.1 of <xref t | cording to <xref target="SEC1"/> and then performing public key validation as de | |||
arget="SEC1"/>. | fined in Section 3.2.2.1 of <xref target="SEC1"/>. | |||
This includes checking that the coordinates of the resulting point are | This includes checking that the coordinates of the resulting point are | |||
in the correct range, that the point is on the curve, and that the point is not | in the correct range, that the point is on the curve, and that the point is not | |||
the point at infinity. (As noted in the specification, validation of the point | the point at infinity. (As noted in the specification, validation of the point | |||
order is not required since the cofactor is 1.) If any of these checks fail, | order is not required since the cofactor is 1.) If any of these checks fail, | |||
deserialization returns an error.</li> | deserialization returns an error.</dd> | |||
<li>SerializeScalar(s): Implemented using the Field-Element-to-Oct | <dt>SerializeScalar(s):</dt> <dd>Implemented using the Field-Eleme | |||
et-String conversion | nt-to-Octet-String conversion | |||
according to <xref target="SEC1"/>.</li> | according to <xref target="SEC1"/>.</dd> | |||
<li>DeserializeScalar(buf): Implemented by attempting to deseriali | <dt>DeserializeScalar(buf):</dt> <dd>Implemented by attempting to | |||
ze a Scalar from a 32-byte | deserialize a Scalar from a 32-byte | |||
string using Octet-String-to-Field-Element from <xref target="SEC1"/>. This func tion can fail if the | string using Octet-String-to-Field-Element from <xref target="SEC1"/>. This func tion can fail if the | |||
input does not represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</li> | input does not represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
<li> | <dt>Hash (<tt>H</tt>):</dt> <dd><t>SHA-256, which has 32 bytes of outp | |||
<t>Hash (<tt>H</tt>): SHA-256, which has 32 bytes of output | ut.</t> | |||
</t> | ||||
<ul spacing="normal"> | <dl newline="false" spacing="normal"> | |||
<li>H1(m): Implemented as hash_to_field(m, 1) from <xref section=" | <dt>H1(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "rho", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "rho", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H2(m): Implemented as hash_to_field(m, 1) from <xref section=" | <dt>H2(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "chal", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "chal", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H3(m): Implemented as hash_to_field(m, 1) from <xref section=" | <dt>H3(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "nonce", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "nonce", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H4(m): Implemented by computing H(contextString || "msg" || m) | <dt>H4(m):</dt> <dd>Implemented by computing H(contextString || "m | |||
.</li> | sg" || m).</dd> | |||
<li>H5(m): Implemented by computing H(contextString || "com" || m) | <dt>H5(m):</dt> <dd>Implemented by computing H(contextString || "c | |||
.</li> | om" || m).</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
</ul> | </dl> | |||
<t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | <t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | |||
<t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | <t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | |||
</section> | </section> | |||
<section anchor="frostsecp256k1-sha-256"> | <section anchor="frostsecp256k1-sha-256"> | |||
<name>FROST(secp256k1, SHA-256)</name> | <name>FROST(secp256k1, SHA-256)</name> | |||
<t>This ciphersuite uses secp256k1 for the Group and SHA-256 for the Has h function <tt>H</tt>. | <t>This ciphersuite uses secp256k1 for the Group and SHA-256 for the has h function <tt>H</tt>. | |||
The value of the contextString parameter is "FROST-secp256k1-SHA256-v1".</t> | The value of the contextString parameter is "FROST-secp256k1-SHA256-v1".</t> | |||
<ul spacing="normal"> | <dl newline="false" spacing="normal"> | |||
<li> | <dt>Group:</dt> <dd><t>secp256k1 <xref target="SEC2"/>, where Ne = 3 | |||
<t>Group: secp256k1 <xref target="SEC2"/>, where Ne = 33 and Ns = 32 | 3 and Ns = 32.</t> | |||
. | <dl newline="false" spacing="normal"> | |||
</t> | <dt>Order():</dt> <dd>Return 0xfffffffffffffffffffffffffffffffebaa | |||
<ul spacing="normal"> | edce6af48a03bbfd25e8cd0364141.</dd> | |||
<li>Order(): Return 0xfffffffffffffffffffffffffffffffebaaedce6af48 | <dt>Identity():</dt> <dd>As defined in <xref target="SEC2"/>.</dd> | |||
a03bbfd25e8cd0364141.</li> | <dt>RandomScalar():</dt> <dd>Implemented by returning a uniformly | |||
<li>Identity(): As defined in <xref target="SEC2"/>.</li> | random Scalar in the range | |||
<li>RandomScalar(): Implemented by returning a uniformly random Sc | [0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | |||
alar in the range | ntation guidance.</dd> | |||
[0, <tt>G.Order()</tt> - 1]. Refer to <xref target="random-scalar"/> for impleme | <dt>SerializeElement(A):</dt> <dd>Implemented using the compressed | |||
ntation guidance.</li> | Elliptic-Curve-Point-to-Octet-String | |||
<li>SerializeElement(A): Implemented using the compressed Elliptic | ||||
-Curve-Point-to-Octet-String | ||||
method according to <xref target="SEC1"/>, yielding a 33-byte output. Additional ly, this function validates | method according to <xref target="SEC1"/>, yielding a 33-byte output. Additional ly, this function validates | |||
that the input element is not the group identity element.</li> | that the input element is not the group identity element.</dd> | |||
<li>DeserializeElement(buf): Implemented by attempting to deserial | <dt>DeserializeElement(buf):</dt> <dd>Implemented by attempting to | |||
ize a 33-byte input string to | deserialize a 33-byte input string to | |||
a public key using the compressed Octet-String-to-Elliptic-Curve-Point method ac | a public key using the compressed Octet-String-to-Elliptic-Curve-Point method ac | |||
cording to <xref target="SEC1"/>, | cording to <xref target="SEC1"/> and then performing public key validation as de | |||
and then performs public-key validation as defined in section 3.2.2.1 of <xref t | fined in Section 3.2.2.1 of <xref target="SEC1"/>. | |||
arget="SEC1"/>. | ||||
This includes checking that the coordinates of the resulting point are | This includes checking that the coordinates of the resulting point are | |||
in the correct range, that the point is on the curve, and that the point is not | in the correct range, the point is on the curve, and the point is not | |||
the point at infinity. (As noted in the specification, validation of the point | the point at infinity. (As noted in the specification, validation of the point | |||
order is not required since the cofactor is 1.) If any of these checks fail, | order is not required since the cofactor is 1.) If any of these checks fail, | |||
deserialization returns an error.</li> | deserialization returns an error.</dd> | |||
<li>SerializeScalar(s): Implemented using the Field-Element-to-Oct | <dt>SerializeScalar(s):</dt> <dd>Implemented using the Field-Eleme | |||
et-String conversion | nt-to-Octet-String conversion | |||
according to <xref target="SEC1"/>.</li> | according to <xref target="SEC1"/>.</dd> | |||
<li>DeserializeScalar(buf): Implemented by attempting to deseriali | <dt>DeserializeScalar(buf):</dt> <dd>Implemented by attempting to | |||
ze a Scalar from a 32-byte | deserialize a Scalar from a 32-byte | |||
string using Octet-String-to-Field-Element from <xref target="SEC1"/>. This func tion can fail if the | string using Octet-String-to-Field-Element from <xref target="SEC1"/>. This func tion can fail if the | |||
input does not represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</li> | input does not represent a Scalar in the range [0, <tt>G.Order()</tt> - 1].</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
<li> | <dt>Hash (<tt>H</tt>):</dt> <dd><t>SHA-256, which has 32 bytes of ou | |||
<t>Hash (<tt>H</tt>): SHA-256, which has 32 bytes of output | tput.</t> | |||
</t> | <dl newline="false" spacing="normal"> | |||
<ul spacing="normal"> | <dt>H1(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
<li>H1(m): Implemented as hash_to_field(m, 1) from <xref section=" | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | ||||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "rho", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "rho", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H2(m): Implemented as hash_to_field(m, 1) from <xref section=" | <dt>H2(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "chal", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "chal", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H3(m): Implemented as hash_to_field(m, 1) from <xref section=" | <dt>H3(m):</dt> <dd>Implemented as hash_to_field(m, 1) (see <xref | |||
5.2" sectionFormat="comma" target="HASH-TO-CURVE"/> | section="5.2" sectionFormat="comma" target="RFC9380"/>) | |||
using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "nonce", | using <tt>expand_message_xmd</tt> with SHA-256 with parameters DST = contextStri ng || "nonce", | |||
F set to the scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</li> | F set to the Scalar field, p set to <tt>G.Order()</tt>, m = 1, and L = 48.</dd> | |||
<li>H4(m): Implemented by computing H(contextString || "msg" || m) | <dt>H4(m):</dt> <dd>Implemented by computing H(contextString || "m | |||
.</li> | sg" || m).</dd> | |||
<li>H5(m): Implemented by computing H(contextString || "com" || m) | <dt>H5(m):</dt> <dd>Implemented by computing H(contextString || "c | |||
.</li> | om" || m).</dd> | |||
</ul> | </dl> | |||
</li> | </dd> | |||
</ul> | </dl> | |||
<t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | <t>Signature verification is as specified in <xref target="prime-order-v erify"/>.</t> | |||
<t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | <t>Canonical signature encoding is as specified in <xref target="sig-enc oding"/>.</t> | |||
</section> | </section> | |||
<section anchor="ciphersuite-reqs"> | <section anchor="ciphersuite-reqs"> | |||
<name>Ciphersuite Requirements</name> | <name>Ciphersuite Requirements</name> | |||
<t>Future documents that introduce new ciphersuites MUST adhere to | <t>Future documents that introduce new ciphersuites <bcp14>MUST</bcp14> adhere to | |||
the following requirements.</t> | the following requirements.</t> | |||
<ol spacing="normal" type="1"><li>H1, H2, and H3 all have output distrib utions that are close to | <ol spacing="normal" type="1"><li>H1, H2, and H3 all have output distrib utions that are close to | |||
(indistinguishable from) the uniform distribution.</li> | (indistinguishable from) the uniform distribution.</li> | |||
<li>All hash functions MUST be domain separated with a per-suite conte xt | <li>All hash functions <bcp14>MUST</bcp14> be domain-separated with a per-suite context | |||
string. Note that the FROST(Ed25519, SHA-512) ciphersuite does not | string. Note that the FROST(Ed25519, SHA-512) ciphersuite does not | |||
adhere to this requirement for H2 alone to maintain compatibility | adhere to this requirement for H2 alone in order to maintain compatibility | |||
with <xref target="RFC8032"/>.</li> | with <xref target="RFC8032"/>.</li> | |||
<li>The group MUST be of prime-order, and all deserialization function | ||||
s MUST | <li>The group <bcp14>MUST</bcp14> be of prime order and all deserializ | |||
output elements that belong to their respective sets of Elements or Scalars, | ation functions <bcp14>MUST</bcp14> | |||
or failure when deserialization fails.</li> | output elements that belong to their respective sets of Elements or Scalars, o | |||
r else fail.</li> | ||||
<li>The canonical signature encoding details are clearly specified.</l i> | <li>The canonical signature encoding details are clearly specified.</l i> | |||
</ol> | </ol> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="sec-considerations"> | <section anchor="sec-considerations"> | |||
<name>Security Considerations</name> | <name>Security Considerations</name> | |||
<t>A security analysis of FROST exists in <xref target="FROST20"/> and <xr | <t>A security analysis of FROST is documented in <xref target="FROST20"/> | |||
ef target="StrongerSec22"/>. At a high | and <xref target="StrongerSec22"/>. At a high level, FROST provides security aga | |||
level, FROST provides security against Existential Unforgeability Under Chosen M | inst Existential Unforgeability Under Chosen Message | |||
essage | Attacks (EUF-CMA) as defined in <xref target="StrongerSec22"/>. | |||
Attack (EUF-CMA) attacks, as defined in <xref target="StrongerSec22"/>. Satisfyi | To satisfy this requirement, the ciphersuite needs to adhere to the | |||
ng this requirement | requirements in <xref target="ciphersuite-reqs"/> and the following | |||
requires the ciphersuite to adhere to the requirements in <xref target="ciphersu | assumptions must hold.</t> | |||
ite-reqs"/>, as well | ||||
as the following assumptions to hold.</t> | ||||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>The signer key shares are generated and distributed securely, e.g., via a trusted dealer | <li>The signer key shares are generated and distributed securely, e.g., via a trusted dealer | |||
that performs key generation (see <xref target="dep-vss"/>) or through a distrib uted key generation protocol.</li> | that performs key generation (see <xref target="dep-vss"/>) or through a distrib uted key generation protocol.</li> | |||
<li>The Coordinator and at most <tt>(MIN_PARTICIPANTS-1)</tt> participan ts may be corrupted.</li> | <li>The Coordinator and at most <tt>(MIN_PARTICIPANTS-1)</tt> participan ts may be corrupted.</li> | |||
</ul> | </ul> | |||
<t>Note that the Coordinator is not trusted with any private information a | <t>Note that the Coordinator is not trusted with any private information, | |||
nd communication | and communication at the time of signing can be performed over a public channel | |||
at the time of signing can be performed over a public channel, as long as it is | as long as it is authenticated and reliable.</t> | |||
authenticated and reliable.</t> | <t>FROST provides security against DoS attacks under the following assumpt | |||
<t>FROST provides security against denial of service attacks under the fol | ions:</t> | |||
lowing assumptions:</t> | ||||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>The Coordinator does not perform a denial of service attack.</li> | <li>The Coordinator does not perform a DoS attack.</li> | |||
<li>The Coordinator identifies misbehaving participants such that they c an be removed from | <li>The Coordinator identifies misbehaving participants such that they c an be removed from | |||
future invocations of FROST. The Coordinator may also abort upon detecting a mis behaving | future invocations of FROST. The Coordinator may also abort upon detecting a mis behaving | |||
participant to ensure that invalid signatures are not produced.</li> | participant to ensure that invalid signatures are not produced.</li> | |||
</ul> | </ul> | |||
<t>FROST does not aim to achieve the following goals:</t> | <t>FROST does not aim to achieve the following goals:</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Post-quantum security. FROST, like plain Schnorr signatures, require s the hardness of the Discrete Logarithm Problem.</li> | <li>Post-quantum security. FROST, like plain Schnorr signatures, require s the hardness of the Discrete Logarithm Problem.</li> | |||
<li>Robustness. Preventing denial-of-service attacks against misbehaving | <li>Robustness. Preventing DoS attacks against misbehaving participants | |||
participants requires the Coordinator | requires the Coordinator | |||
to identify and act on misbehaving participants; see <xref target="abort"/> for | to identify and act on misbehaving participants; see <xref target="abort"/> for | |||
more information. While FROST | more information. | |||
does not provide robustness, <xref target="ROAST"/> is as a wrapper protocol aro | While FROST | |||
und FROST that does.</li> | does not provide robustness, <xref target="ROAST"/> is a wrapper protocol around | |||
<li>Downgrade prevention. All participants in the protocol are assumed t | FROST that does.</li> | |||
o agree on what algorithms to use.</li> | <li>Downgrade prevention. All participants in the protocol are assumed t | |||
o agree on which algorithms to use.</li> | ||||
<li>Metadata protection. If protection for metadata is desired, a higher -level communication | <li>Metadata protection. If protection for metadata is desired, a higher -level communication | |||
channel can be used to facilitate key generation and signing.</li> | channel can be used to facilitate key generation and signing.</li> | |||
</ul> | </ul> | |||
<t>The rest of this section documents issues particular to implementations or deployments.</t> | <t>The rest of this section documents issues particular to implementations or deployments.</t> | |||
<section anchor="side-channel-mitigations"> | <section anchor="side-channel-mitigations"> | |||
<name>Side-channel mitigations</name> | <name>Side-Channel Mitigations</name> | |||
<t>Several routines process secret values (nonces, signing keys / shares ), and depending | <t>Several routines process secret values (nonces, signing keys / shares ), and depending | |||
on the implementation and deployment environment, mitigating side-channels may b e | on the implementation and deployment environment, mitigating side-channels may b e | |||
pertinent. Mitigating these side-channels requires implementing <tt>G.ScalarMult ()</tt>, <tt>G.ScalarBaseMult()</tt>, | pertinent. Mitigating these side-channels requires implementing <tt>G.ScalarMult ()</tt>, <tt>G.ScalarBaseMult()</tt>, | |||
<tt>G.SerializeScalar()</tt>, and <tt>G.DeserializeScalar()</tt> in constant (va lue-independent) time. | <tt>G.SerializeScalar()</tt>, and <tt>G.DeserializeScalar()</tt> in constant (va lue-independent) time. | |||
The various ciphersuites lend themselves differently to specific implementation techniques | The various ciphersuites lend themselves differently to specific implementation techniques | |||
and ease of achieving side-channel resistance, though ultimately avoiding value- dependent | and ease of achieving side-channel resistance, though ultimately avoiding value- dependent | |||
computation or branching is the goal.</t> | computation or branching is the goal.</t> | |||
</section> | </section> | |||
<section anchor="optimizations"> | <section anchor="optimizations"> | |||
<name>Optimizations</name> | <name>Optimizations</name> | |||
<t><xref target="StrongerSec22"/> presented an optimization to FROST tha t reduces the total number of scalar multiplications | <t><xref target="StrongerSec22"/> presented an optimization to FROST tha t reduces the total number of Scalar multiplications | |||
from linear in the number of signing participants to a constant. However, as des cribed in <xref target="StrongerSec22"/>, | from linear in the number of signing participants to a constant. However, as des cribed in <xref target="StrongerSec22"/>, | |||
this optimization removes the guarantee that the set of signer participants that started round one of | this optimization removes the guarantee that the set of signer participants that started round one of | |||
the protocol is the same set of signing participants that produced the signature output by round two. | the protocol is the same set of signing participants that produced the signature output by round two. | |||
As such, the optimization is NOT RECOMMENDED, and it is not covered in this docu ment.</t> | As such, the optimization is <bcp14>NOT RECOMMENDED</bcp14> and is not covered i n this document.</t> | |||
</section> | </section> | |||
<section anchor="nonce-reuse-attacks"> | <section anchor="nonce-reuse-attacks"> | |||
<name>Nonce Reuse Attacks</name> | <name>Nonce Reuse Attacks</name> | |||
<t><xref target="dep-nonces"/> describes the procedure that participants use to produce nonces during | <t><xref target="dep-nonces"/> describes the procedure that participants use to produce nonces during | |||
the first round of signing. The randomness produced in this procedure MUST be sa mpled | the first round of signing. The randomness produced in this procedure <bcp14>MUS T</bcp14> be sampled | |||
uniformly at random. The resulting nonces produced via <tt>nonce_generate</tt> a re indistinguishable | uniformly at random. The resulting nonces produced via <tt>nonce_generate</tt> a re indistinguishable | |||
from values sampled uniformly at random. This requirement is necessary to avoid | from values sampled uniformly at random. This requirement is necessary to avoid | |||
replay attacks initiated by other participants, which allow for a complete key-r | replay attacks initiated by other participants that allow for a complete key-rec | |||
ecovery attack. | overy attack. | |||
The Coordinator MAY further hedge against nonce reuse attacks by tracking partic | The Coordinator <bcp14>MAY</bcp14> further hedge against nonce reuse attacks by | |||
ipant nonce | tracking participant nonce | |||
commitments used for a given group key, at the cost of additional state.</t> | commitments used for a given group key at the cost of additional state.</t> | |||
</section> | </section> | |||
<section anchor="protocol-failures"> | <section anchor="protocol-failures"> | |||
<name>Protocol Failures</name> | <name>Protocol Failures</name> | |||
<t>We do not specify what implementations should do when the protocol fa | <t>We do not specify what implementations should do when the protocol fa | |||
ils, other than requiring that | ils other than requiring | |||
the protocol abort. Examples of viable failure include when a verification check | the protocol to abort. Examples of viable failures include when a verification c | |||
returns invalid or | heck returns invalid or the underlying transport failed to deliver the required | |||
if the underlying transport failed to deliver the required messages.</t> | messages.</t> | |||
</section> | </section> | |||
<section anchor="no-coordinator"> | <section anchor="no-coordinator"> | |||
<name>Removing the Coordinator Role</name> | <name>Removing the Coordinator Role</name> | |||
<t>In some settings, it may be desirable to omit the role of the Coordin ator entirely. | <t>In some settings, it may be desirable to omit the role of the Coordin ator entirely. | |||
Doing so does not change the security implications of FROST, but instead simply | Doing so does not change the security implications of FROST; instead, it simply | |||
requires each participant to communicate with all other participants. We loosely | requires each participant to communicate with all other participants. We loosely | |||
describe how to perform FROST signing among participants without this coordinato r role. | describe how to perform FROST signing among participants without this coordinato r role. | |||
We assume that every participant receives as input from an external source the | We assume that every participant receives a message to be signed from an externa | |||
message to be signed prior to performing the protocol.</t> | l source as input prior to performing the protocol.</t> | |||
<t>Every participant begins by performing <tt>commit()</tt> as is done i n the setting | <t>Every participant begins by performing <tt>commit()</tt> as is done i n the setting | |||
where a Coordinator is used. However, instead of sending the commitment | where a Coordinator is used. However, instead of sending the commitment | |||
to the Coordinator, every participant instead will publish | to the Coordinator, every participant will publish this commitment to every othe | |||
this commitment to every other participant. Then, in the second round, participa | r participant. In the second round, participants will already have sufficient in | |||
nts will already have | formation to perform signing, and they will directly perform <tt>sign()</tt>. Al | |||
sufficient information to perform signing. They will directly perform <tt>sign() | l participants will then publish their signature shares to one another. After ha | |||
</tt>. | ving received all signature shares from all other participants, each participant | |||
All participants will then publish their signature shares to one another. After | will then perform <tt>verify_signature_share</tt> and then <tt>aggregate</tt> d | |||
having | irectly.</t> | |||
received all signature shares from all other participants, each participant will | <t>The requirements for the underlying network channel remain the same in the | |||
then perform | setting where all participants play the role of the Coordinator, in that all | |||
<tt>verify_signature_share</tt> and then <tt>aggregate</tt> directly.</t> | exchanged messages are public and the channel must be reliable. However, in the | |||
<t>The requirements for the underlying network channel remain the same i | setting | |||
n the setting | where a player attempts to split the view of all other players by sending | |||
where all participants play the role of the Coordinator, in that all messages th | disjoint values to a subset of players, the signing operation will output an | |||
at | invalid signature. To avoid this DoS, implementations may wish to define a | |||
are exchanged are public and so the channel simply must be reliable. However, in | mechanism where messages are authenticated so that cheating players can be | |||
the setting that a player attempts to split the view of all other players by | identified and excluded.</t> | |||
sending disjoint values to a subset of players, the signing operation will outpu | ||||
t | ||||
an invalid signature. To avoid this denial of service, implementations may wish | ||||
to define a mechanism where messages are authenticated, so that cheating players | ||||
can be identified and excluded.</t> | ||||
</section> | </section> | |||
<section anchor="pre-hashing"> | <section anchor="pre-hashing"> | |||
<name>Input Message Hashing</name> | <name>Input Message Hashing</name> | |||
<t>FROST signatures do not pre-hash message inputs. This means that the | <t>FROST signatures do not pre-hash message inputs. This means that | |||
entire message | the entire message must be known in advance of invoking the signing | |||
must be known in advance of invoking the signing protocol. Applications can appl | protocol. Applications can apply pre-hashing in settings where storing | |||
y | the full message is prohibitively expensive. In such cases, | |||
pre-hashing in settings where storing the full message is prohibitively expensiv | pre-hashing <bcp14>MUST</bcp14> use a collision-resistant hash | |||
e. | function with a security level commensurate with the security inherent | |||
In such cases, pre-hashing MUST use a collision-resistant hash function with a s | to the ciphersuite chosen. For applications that choose to apply | |||
ecurity | pre-hashing, it is <bcp14>RECOMMENDED</bcp14> that they use the hash | |||
level commensurate with the security inherent to the ciphersuite chosen. It is | function (<tt>H</tt>) associated with the chosen ciphersuite in a | |||
RECOMMENDED that applications which choose to apply pre-hashing use the hash fun | manner similar to how <tt>H4</tt> is defined. In particular, a | |||
ction | different prefix <bcp14>SHOULD</bcp14> be used to differentiate this | |||
(<tt>H</tt>) associated with the chosen ciphersuite in a manner similar to how < | pre-hash from <tt>H4</tt>. For example, if a fictional protocol Quux | |||
tt>H4</tt> is defined. | decided to pre-hash its input messages, one possible way to do so is | |||
In particular, a different prefix SHOULD be used to differentiate this pre-hash | via <tt>H(contextString || "Quux-pre-hash" || m)</tt>.</t> | |||
from | ||||
<tt>H4</tt>. For example, if a fictional protocol Quux decided to pre-hash its i | ||||
nput messages, | ||||
one possible way to do so is via <tt>H(contextString || "Quux-pre-hash" || m)</t | ||||
t>.</t> | ||||
</section> | </section> | |||
<section anchor="message-validation"> | <section anchor="message-validation"> | |||
<name>Input Message Validation</name> | <name>Input Message Validation</name> | |||
<t>Message validation varies by application. For example, some applicati ons may | <t>Message validation varies by application. For example, some applicati ons may | |||
require that participants only process messages of a certain structure. In digit al | require that participants only process messages of a certain structure. In digit al | |||
currency applications, wherein multiple participants may collectively sign a tra nsaction, | currency applications, wherein multiple participants may collectively sign a tra nsaction, | |||
it is reasonable to require that each participant check the input message to be a | it is reasonable to require each participant to check that the input message is a | |||
syntactically valid transaction.</t> | syntactically valid transaction.</t> | |||
<t>As another example, some applications may require that participants o nly process | <t>As another example, some applications may require that participants o nly process | |||
messages with permitted content according to some policy. In digital currency | messages with permitted content according to some policy. In digital currency | |||
applications, this might mean that a transaction being signed is allowed and | applications, this might mean that a transaction being signed is allowed and | |||
intended by the relevant stakeholders. Another instance of this type of message | intended by the relevant stakeholders. Another instance of this type of message | |||
validation is in the context of <xref target="TLS"/>, wherein implementations ma y | validation is in the context of <xref target="RFC8446"/>, wherein implementation s may | |||
use threshold signing protocols to produce signatures of transcript hashes. In | use threshold signing protocols to produce signatures of transcript hashes. In | |||
this setting, signing participants might require the raw TLS handshake messages | this setting, signing participants might require the raw TLS handshake messages | |||
to validate before computing the transcript hash that is signed.</t> | to validate before computing the transcript hash that is signed.</t> | |||
<t>In general, input message validation is an application-specific consi deration | <t>In general, input message validation is an application-specific consi deration | |||
that varies based on the use case and threat model. However, it is RECOMMENDED | that varies based on the use case and threat model. However, it is <bcp14>RECOMM ENDED</bcp14> | |||
that applications take additional precautions and validate inputs so that | that applications take additional precautions and validate inputs so that | |||
participants do not operate as signing oracles for arbitrary messages.</t> | participants do not operate as signing oracles for arbitrary messages.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="iana-considerations"> | <section anchor="iana-considerations"> | |||
<name>IANA Considerations</name> | <name>IANA Considerations</name> | |||
<t>This document makes no IANA requests.</t> | <t>This document has no IANA actions.</t> | |||
</section> | </section> | |||
</middle> | </middle> | |||
<back> | <back> | |||
<displayreference target="RFC9496" to="RISTRETTO"/> | ||||
<displayreference target="RFC9380" to="HASH-TO-CURVE"/> | ||||
<displayreference target="RFC8446" to="TLS"/> | ||||
<references> | <references> | |||
<name>References</name> | <name>References</name> | |||
<references> | <references> | |||
<name>Normative References</name> | <name>Normative References</name> | |||
<reference anchor="x9.62"> | <reference anchor="x9.62"> | |||
<front> | <front> | |||
<title>Public Key Cryptography for the Financial Services Industry: the Elliptic Curve Digital Signature Algorithm (ECDSA)</title> | <title>Public Key Cryptography for the Financial Services Industry: the Elliptic Curve Digital Signature Algorithm (ECDSA)</title> | |||
<author> | <author> | |||
<organization>ANS</organization> | <organization>American National Standards Institute</organization> | |||
</author> | </author> | |||
<date year="2005" month="November"/> | <date year="2005" month="November"/> | |||
</front> | </front> | |||
<seriesInfo name="ANS" value="X9.62-2005"/> | <seriesInfo name="ANSI" value="X9.62-2005"/> | |||
</reference> | </reference> | |||
<reference anchor="SEC1" target="https://secg.org/sec1-v2.pdf"> | <reference anchor="SEC1" target="https://secg.org/sec1-v2.pdf"> | |||
<front> | <front> | |||
<title>Elliptic Curve Cryptography, Standards for Efficient Cryptogr aphy Group, ver. 2</title> | <title>SEC 1: Elliptic Curve Cryptography</title> | |||
<author> | <author> | |||
<organization/> | <organization>Standards for Efficient Cryptography</organization> | |||
</author> | </author> | |||
<date year="2009"/> | <date year="2009" month="May"/> | |||
</front> | </front> | |||
<refcontent>Version 2.0</refcontent> | ||||
</reference> | </reference> | |||
<reference anchor="SEC2" target="https://secg.org/sec2-v2.pdf"> | <reference anchor="SEC2" target="https://secg.org/sec2-v2.pdf"> | |||
<front> | <front> | |||
<title>Recommended Elliptic Curve Domain Parameters, Standards for E fficient Cryptography Group, ver. 2</title> | <title>SEC 2: Recommended Elliptic Curve Domain Parameters</title> | |||
<author> | <author> | |||
<organization/> | <organization>Standards for Efficient Cryptography</organization> | |||
</author> | </author> | |||
<date year="2010"/> | <date year="2010" month="January"/> | |||
</front> | ||||
</reference> | ||||
<reference anchor="RFC8032"> | ||||
<front> | ||||
<title>Edwards-Curve Digital Signature Algorithm (EdDSA)</title> | ||||
<author fullname="S. Josefsson" initials="S." surname="Josefsson"/> | ||||
<author fullname="I. Liusvaara" initials="I." surname="Liusvaara"/> | ||||
<date month="January" year="2017"/> | ||||
<abstract> | ||||
<t>This document describes elliptic curve signature scheme Edwards | ||||
-curve Digital Signature Algorithm (EdDSA). The algorithm is instantiated with r | ||||
ecommended parameters for the edwards25519 and edwards448 curves. An example imp | ||||
lementation and test vectors are provided.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="RFC" value="8032"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8032"/> | ||||
</reference> | ||||
<reference anchor="RFC2119"> | ||||
<front> | ||||
<title>Key words for use in RFCs to Indicate Requirement Levels</tit | ||||
le> | ||||
<author fullname="S. Bradner" initials="S." surname="Bradner"/> | ||||
<date month="March" year="1997"/> | ||||
<abstract> | ||||
<t>In many standards track documents several words are used to sig | ||||
nify the requirements in the specification. These words are often capitalized. T | ||||
his document defines these words as they should be interpreted in IETF documents | ||||
. This document specifies an Internet Best Current Practices for the Internet Co | ||||
mmunity, and requests discussion and suggestions for improvements.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="14"/> | ||||
<seriesInfo name="RFC" value="2119"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC2119"/> | ||||
</reference> | ||||
<reference anchor="RFC8174"> | ||||
<front> | ||||
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</ti | ||||
tle> | ||||
<author fullname="B. Leiba" initials="B." surname="Leiba"/> | ||||
<date month="May" year="2017"/> | ||||
<abstract> | ||||
<t>RFC 2119 specifies common key words that may be used in protoco | ||||
l specifications. This document aims to reduce the ambiguity by clarifying that | ||||
only UPPERCASE usage of the key words have the defined special meanings.</t> | ||||
</abstract> | ||||
</front> | </front> | |||
<seriesInfo name="BCP" value="14"/> | <refcontent>Version 2.0</refcontent> | |||
<seriesInfo name="RFC" value="8174"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8174"/> | ||||
</reference> | </reference> | |||
<reference anchor="RISTRETTO"> | ||||
<front> | ||||
<title>The ristretto255 and decaf448 Groups</title> | ||||
<author fullname="Henry de Valence" initials="H." surname="de Valenc | ||||
e"> | ||||
</author> | ||||
<author fullname="Jack Grigg" initials="J." surname="Grigg"> | ||||
</author> | ||||
<author fullname="Mike Hamburg" initials="M." surname="Hamburg"> | ||||
</author> | ||||
<author fullname="Isis Lovecruft" initials="I." surname="Lovecruft"> | ||||
</author> | ||||
<author fullname="George Tankersley" initials="G." surname="Tankersl | ||||
ey"> | ||||
</author> | ||||
<author fullname="Filippo Valsorda" initials="F." surname="Valsorda" | ||||
> | ||||
</author> | ||||
<date day="5" month="September" year="2023"/> | ||||
<abstract> | ||||
<t> This memo specifies two prime-order groups, ristretto255 and | ||||
decaf448, suitable for safely implementing higher-level and complex | ||||
cryptographic protocols. The ristretto255 group can be implemented | ||||
using Curve25519, allowing existing Curve25519 implementations to be | ||||
reused and extended to provide a prime-order group. Likewise, the | ||||
decaf448 group can be implemented using edwards448. | ||||
This document is a product of the Crypto Forum Research Group (CFRG) | <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8 | |||
in the IRTF. | 032.xml"/> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2 | ||||
119.xml"/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8 | ||||
174.xml"/> | ||||
<!-- [I-D.irtf-cfrg-ristretto255-decaf448] Published as RFC 9496 --> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9 | ||||
496.xml"/> | ||||
<!-- [I-D.irtf-cfrg-hash-to-curve] Published as RFC 9380 --> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9 | ||||
380.xml"/> | ||||
</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-ristretto255- | ||||
decaf448-08"/> | ||||
</reference> | ||||
<reference anchor="HASH-TO-CURVE"> | ||||
<front> | ||||
<title>Hashing to Elliptic Curves</title> | ||||
<author fullname="Armando Faz-Hernandez" initials="A." surname="Faz- | ||||
Hernandez"> | ||||
<organization>Cloudflare, Inc.</organization> | ||||
</author> | ||||
<author fullname="Sam Scott" initials="S." surname="Scott"> | ||||
<organization>Cornell Tech</organization> | ||||
</author> | ||||
<author fullname="Nick Sullivan" initials="N." surname="Sullivan"> | ||||
<organization>Cloudflare, Inc.</organization> | ||||
</author> | ||||
<author fullname="Riad S. Wahby" initials="R. S." surname="Wahby"> | ||||
<organization>Stanford University</organization> | ||||
</author> | ||||
<author fullname="Christopher A. Wood" initials="C. A." surname="Woo | ||||
d"> | ||||
<organization>Cloudflare, Inc.</organization> | ||||
</author> | ||||
<date day="15" month="June" year="2022"/> | ||||
<abstract> | ||||
<t>This document specifies a number of algorithms for encoding or | ||||
hashing an arbitrary string to a point on an elliptic curve. This document is a | ||||
product of the Crypto Forum Research Group (CFRG) in the IRTF. | ||||
</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="Internet-Draft" value="draft-irtf-cfrg-hash-to-curve | ||||
-16"/> | ||||
</reference> | ||||
</references> | </references> | |||
<references> | <references> | |||
<name>Informative References</name> | <name>Informative References</name> | |||
<reference anchor="FROST20" target="https://eprint.iacr.org/2020/852.pdf "> | <reference anchor="FROST20" target="https://eprint.iacr.org/2020/852.pdf "> | |||
<front> | <front> | |||
<title>Two-Round Threshold Signatures with FROST</title> | <title>FROST: Flexible Round-Optimized Schnorr Threshold Signatures< /title> | |||
<author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | <author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="I." surname="Goldberg" fullname="Ian Goldberg"> | <author initials="I." surname="Goldberg" fullname="Ian Goldberg"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date year="2020" month="December" day="22"/> | <date year="2020" month="December"/> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="StrongerSec22" target="https://crypto.iacr.org/2022/p apers/538806_1_En_18_Chapter_OnlinePDF.pdf"> | <reference anchor="StrongerSec22" target="https://crypto.iacr.org/2022/p apers/538806_1_En_18_Chapter_OnlinePDF.pdf"> | |||
<front> | <front> | |||
<title>Better than Advertised Security for Non-interactive Threshold Signatures</title> | <title>Better than Advertised Security for Non-interactive Threshold Signatures</title> | |||
<author initials="M." surname="Bellare" fullname="Mihir Bellare"> | <author initials="M." surname="Bellare" fullname="Mihir Bellare"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="E." surname="Crites" fullname="Elizabeth Crites"> | <author initials="E." surname="Crites" fullname="Elizabeth Crites"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | <author initials="C." surname="Komlo" fullname="Chelsea Komlo"> | |||
skipping to change at line 1498 ¶ | skipping to change at line 1330 ¶ | |||
</author> | </author> | |||
<author initials="M." surname="Maller" fullname="Mary Maller"> | <author initials="M." surname="Maller" fullname="Mary Maller"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="S." surname="Tessaro" fullname="Stefano Tessaro"> | <author initials="S." surname="Tessaro" fullname="Stefano Tessaro"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="C." surname="Zhu" fullname="Chenzhi Zhu"> | <author initials="C." surname="Zhu" fullname="Chenzhi Zhu"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date year="2022" month="June" day="01"/> | <date month="August" year="2022"/> | |||
</front> | </front> | |||
<seriesInfo name="DOI" value="10.1007/978-3-031-15985-5_18"/> | ||||
</reference> | </reference> | |||
<reference anchor="Pornin22" target="https://eprint.iacr.org/2022/1164.p df"> | <reference anchor="Pornin22" target="https://eprint.iacr.org/2022/1164.p df"> | |||
<front> | <front> | |||
<title>Point-Halving and Subgroup Membership in Twisted Edwards Curv es</title> | <title>Point-Halving and Subgroup Membership in Twisted Edwards Curv es</title> | |||
<author initials="T." surname="Pornin" fullname="Thomas Pornin"> | <author initials="T." surname="Pornin" fullname="Thomas Pornin"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date year="2022" month="September" day="06"/> | <date year="2022" month="September"/> | |||
</front> | </front> | |||
</reference> | </reference> | |||
<reference anchor="ROAST" target="https://eprint.iacr.org/2022/550"> | <reference anchor="ROAST" target="https://eprint.iacr.org/2022/550"> | |||
<front> | <front> | |||
<title>ROAST: Robust Asynchronous Schnorr Threshold Signatures</titl e> | <title>ROAST: Robust Asynchronous Schnorr Threshold Signatures</titl e> | |||
<author initials="T." surname="Ruffing" fullname="Tim Ruffing"> | <author initials="T." surname="Ruffing" fullname="Tim Ruffing"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="V." surname="Ronge" fullname="Viktoria Ronge"> | <author initials="V." surname="Ronge" fullname="Viktoria Ronge"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="E." surname="Jin" fullname="Elliott Jin"> | <author initials="E." surname="Jin" fullname="Elliott Jin"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="J." surname="Schneider-Bensch" fullname="Jonas Sch neider-Bensch"> | <author initials="J." surname="Schneider-Bensch" fullname="Jonas Sch neider-Bensch"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="D." surname="Schröder" fullname="Dominique Schröde r"> | <author initials="D." surname="Schröder" fullname="Dominique Schröde r"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date year="2022" month="September" day="18"/> | <date year="2022" month="November"/> | |||
</front> | </front> | |||
<seriesInfo name="DOI" value="10.1145/3548606"/> | ||||
<refcontent>Paper 2022/550</refcontent> | ||||
</reference> | </reference> | |||
<reference anchor="MultExp" target="https://zfnd.org/speeding-up-frost-w ith-multi-scalar-multiplication/"> | <reference anchor="MultExp" target="https://zfnd.org/speeding-up-frost-w ith-multi-scalar-multiplication/"> | |||
<front> | <front> | |||
<title>Speeding up FROST with multi-scalar multiplication</title> | <title>Speeding up FROST with multi-scalar multiplication</title> | |||
<author initials="D." surname="Connolly" fullname="Deirdre Connolly" > | <author initials="D." surname="Connolly" fullname="Deirdre Connolly" > | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<author initials="C." surname="Gouvea" fullname="Conrado Gouvea"> | <author initials="C." surname="Gouvea" fullname="Conrado Gouvea"> | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date>n.d.</date> | <date year="2023" month="June"/> | |||
</front> | ||||
</reference> | ||||
<reference anchor="RFC4086"> | ||||
<front> | ||||
<title>Randomness Requirements for Security</title> | ||||
<author fullname="D. Eastlake 3rd" initials="D." surname="Eastlake 3 | ||||
rd"/> | ||||
<author fullname="J. Schiller" initials="J." surname="Schiller"/> | ||||
<author fullname="S. Crocker" initials="S." surname="Crocker"/> | ||||
<date month="June" year="2005"/> | ||||
<abstract> | ||||
<t>Security systems are built on strong cryptographic algorithms t | ||||
hat foil pattern analysis attempts. However, the security of these systems is de | ||||
pendent on generating secret quantities for passwords, cryptographic keys, and s | ||||
imilar quantities. The use of pseudo-random processes to generate secret quantit | ||||
ies can result in pseudo-security. A sophisticated attacker may find it easier t | ||||
o reproduce the environment that produced the secret quantities and to search th | ||||
e resulting small set of possibilities than to locate the quantities in the whol | ||||
e of the potential number space.</t> | ||||
<t>Choosing random quantities to foil a resourceful and motivated | ||||
adversary is surprisingly difficult. This document points out many pitfalls in u | ||||
sing poor entropy sources or traditional pseudo-random number generation techniq | ||||
ues for generating such quantities. It recommends the use of truly random hardwa | ||||
re techniques and shows that the existing hardware on many systems can be used f | ||||
or this purpose. It provides suggestions to ameliorate the problem when a hardwa | ||||
re solution is not available, and it gives examples of how large such quantities | ||||
need to be for some applications. This document specifies an Internet Best Curr | ||||
ent Practices for the Internet Community, and requests discussion and suggestion | ||||
s for improvements.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="BCP" value="106"/> | ||||
<seriesInfo name="RFC" value="4086"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC4086"/> | ||||
</reference> | ||||
<reference anchor="RFC7748"> | ||||
<front> | ||||
<title>Elliptic Curves for Security</title> | ||||
<author fullname="A. Langley" initials="A." surname="Langley"/> | ||||
<author fullname="M. Hamburg" initials="M." surname="Hamburg"/> | ||||
<author fullname="S. Turner" initials="S." surname="Turner"/> | ||||
<date month="January" year="2016"/> | ||||
<abstract> | ||||
<t>This memo specifies two elliptic curves over prime fields that | ||||
offer a high level of practical security in cryptographic applications, includin | ||||
g Transport Layer Security (TLS). These curves are intended to operate at the ~1 | ||||
28-bit and ~224-bit security level, respectively, and are generated deterministi | ||||
cally based on a list of required properties.</t> | ||||
</abstract> | ||||
</front> | ||||
<seriesInfo name="RFC" value="7748"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC7748"/> | ||||
</reference> | ||||
<reference anchor="TLS"> | ||||
<front> | ||||
<title>The Transport Layer Security (TLS) Protocol Version 1.3</titl | ||||
e> | ||||
<author fullname="E. Rescorla" initials="E." surname="Rescorla"/> | ||||
<date month="August" year="2018"/> | ||||
<abstract> | ||||
<t>This document specifies version 1.3 of the Transport Layer Secu | ||||
rity (TLS) protocol. TLS allows client/server applications to communicate over t | ||||
he Internet in a way that is designed to prevent eavesdropping, tampering, and m | ||||
essage forgery.</t> | ||||
<t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 50 | ||||
77, 5246, and 6961. This document also specifies new requirements for TLS 1.2 im | ||||
plementations.</t> | ||||
</abstract> | ||||
</front> | </front> | |||
<seriesInfo name="RFC" value="8446"/> | ||||
<seriesInfo name="DOI" value="10.17487/RFC8446"/> | ||||
</reference> | </reference> | |||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4 | ||||
086.xml"/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7 | ||||
748.xml"/> | ||||
<xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8 | ||||
446.xml"/> | ||||
<reference anchor="ShamirSecretSharing"> | <reference anchor="ShamirSecretSharing"> | |||
<front> | <front> | |||
<title>How to share a secret</title> | <title>How to share a secret</title> | |||
<author fullname="Adi Shamir" initials="A." surname="Shamir"> | <author fullname="Adi Shamir" initials="A." surname="Shamir"> | |||
<organization>Massachusetts Institute of Technology, Cambridge</or ganization> | <organization>Massachusetts Institute of Technology</organization> | |||
</author> | </author> | |||
<date month="November" year="1979"/> | <date month="November" year="1979"/> | |||
</front> | </front> | |||
<seriesInfo name="Communications of the ACM" value="vol. 22, no. 11, p p. 612-613"/> | ||||
<seriesInfo name="DOI" value="10.1145/359168.359176"/> | <seriesInfo name="DOI" value="10.1145/359168.359176"/> | |||
<refcontent>Association for Computing Machinery (ACM)</refcontent> | <refcontent>Association for Computing Machinery (ACM)</refcontent> | |||
</reference> | <refcontent>Communications of the ACM, Vol. 22, Issue 11, pp. 612-613< | |||
/refcontent> | ||||
</reference> | ||||
<reference anchor="FeldmanSecretSharing"> | <reference anchor="FeldmanSecretSharing"> | |||
<front> | <front> | |||
<title>A practical scheme for non-interactive verifiable secret shar ing</title> | <title>A practical scheme for non-interactive verifiable secret shar ing</title> | |||
<author fullname="Paul Feldman" initials="P." surname="Feldman"> | <author fullname="Paul Feldman" initials="P." surname="Feldman" > | |||
<organization/> | <organization/> | |||
</author> | </author> | |||
<date month="October" year="1987"/> | <date month="October" year="1987"/> | |||
</front> | </front> | |||
<seriesInfo name="28th Annual Symposium on Foundations of Computer Sci ence (sfcs" value="1987)"/> | ||||
<seriesInfo name="DOI" value="10.1109/sfcs.1987.4"/> | <seriesInfo name="DOI" value="10.1109/sfcs.1987.4"/> | |||
<refcontent>IEEE</refcontent> | <refcontent>IEEE</refcontent> | |||
<refcontent>28th Annual Symposium on Foundations of Computer Science ( | ||||
sfcs 1987)</refcontent> | ||||
</reference> | </reference> | |||
</references> | </references> | |||
</references> | </references> | |||
<?line 1380?> | ||||
<section anchor="acknowledgments"> | ||||
<name>Acknowledgments</name> | ||||
<t>This document was improved based on input and contributions by the Zcas | ||||
h Foundation engineering team. | ||||
In addition, the authors of this document would like to thank | ||||
Isis Lovecruft, | ||||
Alden Torres, | ||||
T. Wilson-Brown, | ||||
and Conrado Gouvea | ||||
for their inputs and contributions.</t> | ||||
</section> | ||||
<section anchor="sig-encoding"> | <section anchor="sig-encoding"> | |||
<name>Schnorr Signature Encoding</name> | <name>Schnorr Signature Encoding</name> | |||
<t>This section describes one possible canonical encoding of FROST signatu res. Using notation | <t>This section describes one possible canonical encoding of FROST signatu res. Using notation | |||
from <xref section="3" sectionFormat="of" target="TLS"/>, the encoding of a FROS | from <xref section="3" sectionFormat="of" target="RFC8446"/>, the encoding of a | |||
T signature (R, z) is as follows:</t> | FROST signature (R, z) is as follows:</t> | |||
<artwork><![CDATA[ | <sourcecode type=""><![CDATA[ | |||
struct { | struct { | |||
opaque R_encoded[Ne]; | opaque R_encoded[Ne]; | |||
opaque z_encoded[Ns]; | opaque z_encoded[Ns]; | |||
} Signature; | } Signature; | |||
]]></artwork> | ]]></sourcecode> | |||
<t>Where Signature.R_encoded is <tt>G.SerializeElement(R)</tt> and Signatu | <t>Where Signature.R_encoded is <tt>G.SerializeElement(R)</tt>, Signature. | |||
re.z_encoded is | z_encoded is | |||
<tt>G.SerializeScalar(z)</tt> and <tt>G</tt> is determined by ciphersuite.</t> | <tt>G.SerializeScalar(z)</tt>, and <tt>G</tt> is determined by ciphersuite.</t> | |||
</section> | </section> | |||
<section anchor="prime-order-verify"> | <section anchor="prime-order-verify"> | |||
<name>Schnorr Signature Generation and Verification for Prime-Order Groups </name> | <name>Schnorr Signature Generation and Verification for Prime-Order Groups </name> | |||
<t>This section contains descriptions of functions for generating and veri fying Schnorr signatures. | <t>This section contains descriptions of functions for generating and veri fying Schnorr signatures. | |||
It is included to complement the routines present in <xref target="RFC8032"/> fo r prime-order groups, including | It is included to complement the routines present in <xref target="RFC8032"/> fo r prime-order groups, including | |||
ristretto255, P-256, and secp256k1. The functions for generating and verifying s ignatures are | ristretto255, P-256, and secp256k1. The functions for generating and verifying s ignatures are | |||
<tt>prime_order_sign</tt> and <tt>prime_order_verify</tt>, respectively.</t> | <tt>prime_order_sign</tt> and <tt>prime_order_verify</tt>, respectively.</t> | |||
<t>The function <tt>prime_order_sign</tt> produces a Schnorr signature ove r a message given a full secret signing | <t>The function <tt>prime_order_sign</tt> produces a Schnorr signature ove r a message given a full secret signing | |||
key as input (as opposed to a key share.)</t> | key as input (as opposed to a key share).</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- msg, message to sign, a byte string. | - msg, message to sign, a byte string. | |||
- sk, secret key, a Scalar. | - sk, secret key, a Scalar. | |||
Outputs: | Outputs: | |||
- (R, z), a Schnorr signature consisting of an Element R and | - (R, z), a Schnorr signature consisting of an Element R and | |||
Scalar z. | Scalar z. | |||
def prime_order_sign(msg, sk): | def prime_order_sign(msg, sk): | |||
r = G.RandomScalar() | r = G.RandomScalar() | |||
R = G.ScalarBaseMult(r) | R = G.ScalarBaseMult(r) | |||
PK = G.ScalarBaseMult(sk) | PK = G.ScalarBaseMult(sk) | |||
comm_enc = G.SerializeElement(R) | comm_enc = G.SerializeElement(R) | |||
pk_enc = G.SerializeElement(PK) | pk_enc = G.SerializeElement(PK) | |||
challenge_input = comm_enc || pk_enc || msg | challenge_input = comm_enc || pk_enc || msg | |||
c = H2(challenge_input) | c = H2(challenge_input) | |||
z = r + (c * sk) // Scalar addition and multiplication | z = r + (c * sk) // Scalar addition and multiplication | |||
return (R, z) | return (R, z) | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The function <tt>prime_order_verify</tt> verifies Schnorr signatures wi th validated inputs. | <t>The function <tt>prime_order_verify</tt> verifies Schnorr signatures wi th validated inputs. | |||
Specifically, it assumes that signature R component and public key belong to the | Specifically, it assumes that the signature R component and public key belong to | |||
prime-order group.</t> | the prime-order group.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- msg, signed message, a byte string. | - msg, signed message, a byte string. | |||
- sig, a tuple (R, z) output from signature generation. | - sig, a tuple (R, z) output from signature generation. | |||
- PK, public key, an Element. | - PK, public key, an Element. | |||
Outputs: | Outputs: | |||
- True if signature is valid, and False otherwise. | - True if signature is valid, and False otherwise. | |||
def prime_order_verify(msg, sig = (R, z), PK): | def prime_order_verify(msg, sig = (R, z), PK): | |||
comm_enc = G.SerializeElement(R) | comm_enc = G.SerializeElement(R) | |||
pk_enc = G.SerializeElement(PK) | pk_enc = G.SerializeElement(PK) | |||
challenge_input = comm_enc || pk_enc || msg | challenge_input = comm_enc || pk_enc || msg | |||
c = H2(challenge_input) | c = H2(challenge_input) | |||
l = G.ScalarBaseMult(z) | l = G.ScalarBaseMult(z) | |||
r = R + G.ScalarMult(PK, c) | r = R + G.ScalarMult(PK, c) | |||
return l == r | return l == r | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="dep-dealer"> | <section anchor="dep-dealer"> | |||
<name>Trusted Dealer Key Generation</name> | <name>Trusted Dealer Key Generation</name> | |||
<t>One possible key generation mechanism is to depend on a trusted dealer, wherein the | <t>One possible key generation mechanism is to depend on a trusted dealer, wherein the | |||
dealer generates a group secret <tt>s</tt> uniformly at random and uses Shamir a nd Verifiable | dealer generates a group secret <tt>s</tt> uniformly at random and uses Shamir a nd Verifiable | |||
Secret Sharing <xref target="ShamirSecretSharing"/>, as described in <xref targe | Secret Sharing <xref target="ShamirSecretSharing"/> as described in Appendices < | |||
t="dep-shamir"/> and <xref target="dep-vss"/> to create secret | xref target="dep-shamir" format="counter"/> and <xref target="dep-vss" format="c | |||
shares of s, denoted <tt>s_i</tt> for <tt>i = 1, ..., MAX_PARTICIPANTS</tt>, to | ounter"/> to create secret | |||
be sent to all <tt>MAX_PARTICIPANTS</tt> participants. | shares of s, denoted as <tt>s_i</tt> for <tt>i = 1, ..., MAX_PARTICIPANTS</tt>, | |||
to be sent to all <tt>MAX_PARTICIPANTS</tt> participants. | ||||
This operation is specified in the <tt>trusted_dealer_keygen</tt> algorithm. The mathematical relation | This operation is specified in the <tt>trusted_dealer_keygen</tt> algorithm. The mathematical relation | |||
between the secret key <tt>s</tt> and the <tt>MAX_PARTICIPANTS</tt> secret share s is formalized in the <tt>secret_share_combine(shares)</tt> | between the secret key <tt>s</tt> and the <tt>MAX_PARTICIPANTS</tt> secret share s is formalized in the <tt>secret_share_combine(shares)</tt> | |||
algorithm, defined in <xref target="dep-shamir"/>.</t> | algorithm, defined in <xref target="dep-shamir"/>.</t> | |||
<t>The dealer that performs <tt>trusted_dealer_keygen</tt> is trusted to 1 | <t>The dealer that performs <tt>trusted_dealer_keygen</tt> is trusted to 1 | |||
) generate good randomness, and 2) delete secret values after distributing share | ) generate good randomness, 2) delete secret values after distributing shares to | |||
s to each participant, and 3) keep secret values confidential.</t> | each participant, and 3) keep secret values confidential.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- secret_key, a group secret, a Scalar, that MUST be derived from at | - secret_key, a group secret, a Scalar, that MUST be derived from at | |||
least Ns bytes of entropy. | least Ns bytes of entropy. | |||
- MAX_PARTICIPANTS, the number of shares to generate, an integer. | - MAX_PARTICIPANTS, the number of shares to generate, an integer. | |||
- MIN_PARTICIPANTS, the threshold of the secret sharing scheme, | - MIN_PARTICIPANTS, the threshold of the secret sharing scheme, | |||
an integer. | an integer. | |||
Outputs: | Outputs: | |||
- participant_private_keys, MAX_PARTICIPANTS shares of the secret | - participant_private_keys, MAX_PARTICIPANTS shares of the secret | |||
key s, each a tuple consisting of the participant identifier | key s, each a tuple consisting of the participant identifier | |||
skipping to change at line 1725 ¶ | skipping to change at line 1515 ¶ | |||
def trusted_dealer_keygen( | def trusted_dealer_keygen( | |||
secret_key, MAX_PARTICIPANTS, MIN_PARTICIPANTS): | secret_key, MAX_PARTICIPANTS, MIN_PARTICIPANTS): | |||
# Generate random coefficients for the polynomial | # Generate random coefficients for the polynomial | |||
coefficients = [] | coefficients = [] | |||
for i in range(0, MIN_PARTICIPANTS - 1): | for i in range(0, MIN_PARTICIPANTS - 1): | |||
coefficients.append(G.RandomScalar()) | coefficients.append(G.RandomScalar()) | |||
participant_private_keys, coefficients = secret_share_shard( | participant_private_keys, coefficients = secret_share_shard( | |||
secret_key, coefficients, MAX_PARTICIPANTS) | secret_key, coefficients, MAX_PARTICIPANTS) | |||
vss_commitment = vss_commit(coefficients): | vss_commitment = vss_commit(coefficients): | |||
return participant_private_keys, vss_commitment[0], vss_commitment | return participant_private_keys, vss_commitment[0], vss_commitment | |||
]]></artwork> | ]]></sourcecode> | |||
<t>It is assumed the dealer then sends one secret key share to each of the | <t>It is assumed that the dealer then sends one secret key share to each o | |||
<tt>NUM_PARTICIPANTS</tt> participants, along with <tt>vss_commitment</tt>. | f the <tt>NUM_PARTICIPANTS</tt> participants, along with <tt>vss_commitment</tt> | |||
After receiving their secret key share and <tt>vss_commitment</tt>, participants | . | |||
MUST abort if they do not have the same view of <tt>vss_commitment</tt>. | After receiving their secret key share and <tt>vss_commitment</tt>, participants | |||
<bcp14>MUST</bcp14> abort if they do not have the same view of <tt>vss_commitme | ||||
nt</tt>. | ||||
The dealer can use a secure broadcast channel to ensure each participant has a c onsistent view of this commitment. | The dealer can use a secure broadcast channel to ensure each participant has a c onsistent view of this commitment. | |||
Furthermore, each participant MUST perform <tt>vss_verify(secret_key_share_i, vs | Furthermore, each participant <bcp14>MUST</bcp14> perform <tt>vss_verify(secret_ | |||
s_commitment)</tt>, and abort if the check fails. | key_share_i, vss_commitment)</tt> and abort if the check fails. | |||
The trusted dealer MUST delete the secret_key and secret_key_shares upon complet | The trusted dealer <bcp14>MUST</bcp14> delete the secret_key and secret_key_shar | |||
ion.</t> | es upon completion.</t> | |||
<t>Use of this method for key generation requires a mutually authenticated secure channel | <t>Use of this method for key generation requires a mutually authenticated secure channel | |||
between the dealer and participants to send secret key shares, wherein the chann | between the dealer and participants to send secret key shares, wherein the chann | |||
el provides confidentiality | el provides confidentiality and integrity. Mutually authenticated TLS is one pos | |||
and integrity. Mutually authenticated TLS is one possible deployment option.</t> | sible deployment option.</t> | |||
<section anchor="dep-shamir"> | <section anchor="dep-shamir"> | |||
<name>Shamir Secret Sharing</name> | <name>Shamir Secret Sharing</name> | |||
<t>In Shamir secret sharing, a dealer distributes a secret <tt>Scalar</t t> <tt>s</tt> to <tt>n</tt> participants | <t>In Shamir secret sharing, a dealer distributes a secret <tt>Scalar</t t> <tt>s</tt> to <tt>n</tt> participants | |||
in such a way that any cooperating subset of at least <tt>MIN_PARTICIPANTS</tt> participants can recover the | in such a way that any cooperating subset of at least <tt>MIN_PARTICIPANTS</tt> participants can recover the | |||
secret. There are two basic steps in this scheme: (1) splitting a secret into | secret. There are two basic steps in this scheme: 1) splitting a secret into | |||
multiple shares, and (2) combining shares to reveal the resulting secret.</t> | multiple shares and 2) combining shares to reveal the resulting secret.</t> | |||
<t>This secret sharing scheme works over any field <tt>F</tt>. In this s pecification, <tt>F</tt> is | <t>This secret sharing scheme works over any field <tt>F</tt>. In this s pecification, <tt>F</tt> is | |||
the scalar field of the prime-order group <tt>G</tt>.</t> | the Scalar field of the prime-order group <tt>G</tt>.</t> | |||
<t>The procedure for splitting a secret into shares is as follows. | <t>The procedure for splitting a secret into shares is as follows. | |||
The algorithm <tt>polynomial_evaluate</tt> is defined in <xref target="dep-exten ded-polynomial-operations"/>.</t> | The algorithm <tt>polynomial_evaluate</tt> is defined in <xref target="dep-exten ded-polynomial-operations"/>.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- s, secret value to be shared, a Scalar. | - s, secret value to be shared, a Scalar. | |||
- coefficients, an array of size MIN_PARTICIPANTS - 1 with randomly | - coefficients, an array of size MIN_PARTICIPANTS - 1 with randomly | |||
generated Scalars, not including the 0th coefficient of the | generated Scalars, not including the 0th coefficient of the | |||
polynomial. | polynomial. | |||
- MAX_PARTICIPANTS, the number of shares to generate, an integer less | - MAX_PARTICIPANTS, the number of shares to generate, an integer less | |||
than the group order. | than the group order. | |||
Outputs: | Outputs: | |||
- secret_key_shares, A list of MAX_PARTICIPANTS number of secret | - secret_key_shares, A list of MAX_PARTICIPANTS number of secret | |||
skipping to change at line 1771 ¶ | skipping to change at line 1560 ¶ | |||
# Prepend the secret to the coefficients | # Prepend the secret to the coefficients | |||
coefficients = [s] + coefficients | coefficients = [s] + coefficients | |||
# Evaluate the polynomial for each point x=1,...,n | # Evaluate the polynomial for each point x=1,...,n | |||
secret_key_shares = [] | secret_key_shares = [] | |||
for x_i in range(1, MAX_PARTICIPANTS + 1): | for x_i in range(1, MAX_PARTICIPANTS + 1): | |||
y_i = polynomial_evaluate(Scalar(x_i), coefficients) | y_i = polynomial_evaluate(Scalar(x_i), coefficients) | |||
secret_key_share_i = (x_i, y_i) | secret_key_share_i = (x_i, y_i) | |||
secret_key_shares.append(secret_key_share_i) | secret_key_shares.append(secret_key_share_i) | |||
return secret_key_shares, coefficients | return secret_key_shares, coefficients | |||
]]></artwork> | ]]></sourcecode> | |||
<t>Let <tt>points</tt> be the output of this function. The i-th element in <tt>points</tt> is | <t>Let <tt>points</tt> be the output of this function. The i-th element in <tt>points</tt> is | |||
the share for the i-th participant, which is the randomly generated polynomial | the share for the i-th participant, which is the randomly generated polynomial | |||
evaluated at coordinate <tt>i</tt>. We denote a secret share as the tuple <tt>(i | evaluated at coordinate <tt>i</tt>. We denote a secret share as the tuple <tt>(i | |||
, points[i])</tt>, | , points[i])</tt> | |||
and the list of these shares as <tt>shares</tt>. <tt>i</tt> MUST never equal <tt | and the list of these shares as <tt>shares</tt>. <tt>i</tt> <bcp14>MUST</bcp14> | |||
>0</tt>; recall that | never equal <tt>0</tt>; recall that | |||
<tt>f(0) = s</tt>, where <tt>f</tt> is the polynomial defined in a Shamir secret sharing operation.</t> | <tt>f(0) = s</tt>, where <tt>f</tt> is the polynomial defined in a Shamir secret sharing operation.</t> | |||
<t>The procedure for combining a <tt>shares</tt> list of length <tt>MIN_ PARTICIPANTS</tt> to recover the | <t>The procedure for combining a <tt>shares</tt> list of length <tt>MIN_ PARTICIPANTS</tt> to recover the | |||
secret <tt>s</tt> is as follows; the algorithm <tt>polynomial_interpolate_consta nt</tt> is defined in <xref target="dep-extended-polynomial-operations"/>.</t> | secret <tt>s</tt> is as follows; the algorithm <tt>polynomial_interpolate_consta nt</tt> is defined in <xref target="dep-extended-polynomial-operations"/>.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- shares, a list of at minimum MIN_PARTICIPANTS secret shares, each a | - shares, a list of at minimum MIN_PARTICIPANTS secret shares, each a | |||
tuple (i, f(i)) where i and f(i) are Scalars. | tuple (i, f(i)) where i and f(i) are Scalars. | |||
Outputs: | Outputs: | |||
- s, the resulting secret that was previously split into shares, | - s, the resulting secret that was previously split into shares, | |||
a Scalar. | a Scalar. | |||
Errors: | Errors: | |||
- "invalid parameters", if fewer than MIN_PARTICIPANTS input shares | - "invalid parameters", if fewer than MIN_PARTICIPANTS input shares | |||
are provided. | are provided. | |||
def secret_share_combine(shares): | def secret_share_combine(shares): | |||
if len(shares) < MIN_PARTICIPANTS: | if len(shares) < MIN_PARTICIPANTS: | |||
raise "invalid parameters" | raise "invalid parameters" | |||
s = polynomial_interpolate_constant(shares) | s = polynomial_interpolate_constant(shares) | |||
return s | return s | |||
]]></artwork> | ]]></sourcecode> | |||
<section anchor="dep-extended-polynomial-operations"> | <section anchor="dep-extended-polynomial-operations"> | |||
<name>Additional polynomial operations</name> | <name>Additional Polynomial Operations</name> | |||
<t>This section describes two functions. One function, denoted <tt>pol | <t>This section describes two functions. One function, denoted as <tt> | |||
ynomial_evaluate</tt>, | polynomial_evaluate</tt>, | |||
is for evaluating a polynomial <tt>f(x)</tt> at a particular point <tt>x</tt> us ing Horner's method, | is for evaluating a polynomial <tt>f(x)</tt> at a particular point <tt>x</tt> us ing Horner's method, | |||
i.e., computing <tt>y = f(x)</tt>. The other function, <tt>polynomial_interpolat e_constant</tt>, is for | i.e., computing <tt>y = f(x)</tt>. The other function, <tt>polynomial_interpolat e_constant</tt>, is for | |||
recovering the constant term of an interpolating polynomial defined by a set of points.</t> | recovering the constant term of an interpolating polynomial defined by a set of points.</t> | |||
<t>The function <tt>polynomial_evaluate</tt> is defined as follows.</t > | <t>The function <tt>polynomial_evaluate</tt> is defined as follows.</t > | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- x, input at which to evaluate the polynomial, a Scalar | - x, input at which to evaluate the polynomial, a Scalar | |||
- coeffs, the polynomial coefficients, a list of Scalars | - coeffs, the polynomial coefficients, a list of Scalars | |||
Outputs: Scalar result of the polynomial evaluated at input x | Outputs: Scalar result of the polynomial evaluated at input x | |||
def polynomial_evaluate(x, coeffs): | def polynomial_evaluate(x, coeffs): | |||
value = Scalar(0) | value = Scalar(0) | |||
for coeff in reverse(coeffs): | for coeff in reverse(coeffs): | |||
value *= x | value *= x | |||
value += coeff | value += coeff | |||
return value | return value | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The function <tt>polynomial_interpolate_constant</tt> is defined as | <t keepWithNext="true">The function <tt>polynomial_interpolate_constan | |||
follows.</t> | t</tt> is defined as follows.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- points, a set of t points with distinct x coordinates on | - points, a set of t points with distinct x coordinates on | |||
a polynomial f, each a tuple of two Scalar values representing the | a polynomial f, each a tuple of two Scalar values representing the | |||
x and y coordinates. | x and y coordinates. | |||
Outputs: | Outputs: | |||
- f_zero, the constant term of f, i.e., f(0), a Scalar. | - f_zero, the constant term of f, i.e., f(0), a Scalar. | |||
def polynomial_interpolate_constant(points): | def polynomial_interpolate_constant(points): | |||
x_coords = [] | x_coords = [] | |||
for (x, y) in points: | for (x, y) in points: | |||
x_coords.append(x) | x_coords.append(x) | |||
f_zero = Scalar(0) | f_zero = Scalar(0) | |||
for (x, y) in points: | for (x, y) in points: | |||
delta = y * derive_interpolating_value(x_coords, x) | delta = y * derive_interpolating_value(x_coords, x) | |||
f_zero += delta | f_zero += delta | |||
return f_zero | return f_zero | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="dep-vss"> | <section anchor="dep-vss"> | |||
<name>Verifiable Secret Sharing</name> | <name>Verifiable Secret Sharing</name> | |||
<t>Feldman's Verifiable Secret Sharing (VSS) <xref target="FeldmanSecret Sharing"/> | <t>Feldman's Verifiable Secret Sharing (VSS) <xref target="FeldmanSecret Sharing"/> | |||
builds upon Shamir secret sharing, adding a verification step to demonstrate the consistency of a participant's | builds upon Shamir secret sharing, adding a verification step to demonstrate the consistency of a participant's | |||
share with a public commitment to the polynomial <tt>f</tt> for which the secret <tt>s</tt> | share with a public commitment to the polynomial <tt>f</tt> for which the secret <tt>s</tt> | |||
is the constant term. This check ensures that all participants have a point | is the constant term. This check ensures that all participants have a point | |||
(their share) on the same polynomial, ensuring that they can later reconstruct | (their share) on the same polynomial, ensuring that they can reconstruct | |||
the correct secret.</t> | the correct secret later.</t> | |||
<t>The procedure for committing to a polynomial <tt>f</tt> of degree at | <t>The procedure for committing to a polynomial <tt>f</tt> of degree at most <tt | |||
most <tt>MIN_PARTICIPANTS-1</tt> is as follows.</t> | >MIN_PARTICIPANTS-1</tt> is as follows.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- coeffs, a vector of the MIN_PARTICIPANTS coefficients which | - coeffs, a vector of the MIN_PARTICIPANTS coefficients that | |||
uniquely determine a polynomial f. | uniquely determine a polynomial f. | |||
Outputs: | Outputs: | |||
- vss_commitment, a vector commitment to each of the coefficients in | - vss_commitment, a vector commitment to each of the coefficients in | |||
coeffs, where each item of the vector commitment is an Element. | coeffs, where each item of the vector commitment is an Element. | |||
def vss_commit(coeffs): | def vss_commit(coeffs): | |||
vss_commitment = [] | vss_commitment = [] | |||
for coeff in coeffs: | for coeff in coeffs: | |||
A_i = G.ScalarBaseMult(coeff) | A_i = G.ScalarBaseMult(coeff) | |||
vss_commitment.append(A_i) | vss_commitment.append(A_i) | |||
return vss_commitment | return vss_commitment | |||
]]></artwork> | ]]></sourcecode> | |||
<t>The procedure for verification of a participant's share is as follows . | <t>The procedure for verification of a participant's share is as follows . | |||
If <tt>vss_verify</tt> fails, the participant MUST abort the protocol, and failu | If <tt>vss_verify</tt> fails, the participant <bcp14>MUST</bcp14> abort the prot | |||
re should be investigated out of band.</t> | ocol, and the failure should be investigated out of band.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- share_i: A tuple of the form (i, sk_i), where i indicates the | - share_i: A tuple of the form (i, sk_i), where i indicates the | |||
participant identifier (a NonZeroScalar), and sk_i the | participant identifier (a NonZeroScalar), and sk_i the | |||
participant's secret key, a secret share of the constant term of f, | participant's secret key, a secret share of the constant term of f, | |||
where sk_i is a Scalar. | where sk_i is a Scalar. | |||
- vss_commitment, a VSS commitment to a secret polynomial f, a vector | - vss_commitment, a VSS commitment to a secret polynomial f, a vector | |||
commitment to each of the coefficients in coeffs, where each | commitment to each of the coefficients in coeffs, where each | |||
element of the vector commitment is an Element. | element of the vector commitment is an Element. | |||
Outputs: | Outputs: | |||
- True if sk_i is valid, and False otherwise. | - True if sk_i is valid, and False otherwise. | |||
def vss_verify(share_i, vss_commitment) | def vss_verify(share_i, vss_commitment) | |||
(i, sk_i) = share_i | (i, sk_i) = share_i | |||
S_i = G.ScalarBaseMult(sk_i) | S_i = G.ScalarBaseMult(sk_i) | |||
S_i' = G.Identity() | S_i' = G.Identity() | |||
for j in range(0, MIN_PARTICIPANTS): | for j in range(0, MIN_PARTICIPANTS): | |||
S_i' += G.ScalarMult(vss_commitment[j], pow(i, j)) | S_i' += G.ScalarMult(vss_commitment[j], pow(i, j)) | |||
return S_i == S_i' | return S_i == S_i' | |||
]]></artwork> | ]]></sourcecode> | |||
<t>We now define how the Coordinator and participants can derive group i nfo, | <t>We now define how the Coordinator and participants can derive group i nfo, | |||
which is an input into the FROST signing protocol.</t> | which is an input into the FROST signing protocol.</t> | |||
<artwork><![CDATA[ | <sourcecode type="pseudocode"><![CDATA[ | |||
Inputs: | Inputs: | |||
- MAX_PARTICIPANTS, the number of shares to generate, an integer. | - MAX_PARTICIPANTS, the number of shares to generate, an integer. | |||
- MIN_PARTICIPANTS, the threshold of the secret sharing scheme, | - MIN_PARTICIPANTS, the threshold of the secret sharing scheme, | |||
an integer. | an integer. | |||
- vss_commitment, a VSS commitment to a secret polynomial f, a vector | - vss_commitment, a VSS commitment to a secret polynomial f, a vector | |||
commitment to each of the coefficients in coeffs, where each | commitment to each of the coefficients in coeffs, where each | |||
element of the vector commitment is an Element. | element of the vector commitment is an Element. | |||
Outputs: | Outputs: | |||
- PK, the public key representing the group, an Element. | - PK, the public key representing the group, an Element. | |||
- participant_public_keys, a list of MAX_PARTICIPANTS public keys | - participant_public_keys, a list of MAX_PARTICIPANTS public keys | |||
PK_i for i=1,...,MAX_PARTICIPANTS, where each PK_i is the public | PK_i for i=1,...,MAX_PARTICIPANTS, where each PK_i is the public | |||
key, an Element, for participant i. | key, an Element, for participant i. | |||
def derive_group_info(MAX_PARTICIPANTS, MIN_PARTICIPANTS, vss_commitment) | def derive_group_info(MAX_PARTICIPANTS, MIN_PARTICIPANTS, | |||
vss_commitment): | ||||
PK = vss_commitment[0] | PK = vss_commitment[0] | |||
participant_public_keys = [] | participant_public_keys = [] | |||
for i in range(1, MAX_PARTICIPANTS+1): | for i in range(1, MAX_PARTICIPANTS+1): | |||
PK_i = G.Identity() | PK_i = G.Identity() | |||
for j in range(0, MIN_PARTICIPANTS): | for j in range(0, MIN_PARTICIPANTS): | |||
PK_i += G.ScalarMult(vss_commitment[j], pow(i, j)) | PK_i += G.ScalarMult(vss_commitment[j], pow(i, j)) | |||
participant_public_keys.append(PK_i) | participant_public_keys.append(PK_i) | |||
return PK, participant_public_keys | return PK, participant_public_keys | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="random-scalar"> | <section anchor="random-scalar"> | |||
<name>Random Scalar Generation</name> | <name>Random Scalar Generation</name> | |||
<t>Two popular algorithms for generating a random integer uniformly distri | <t>Two popular algorithms for | |||
buted in | generating a random integer uniformly distributed in the range [0, | |||
the range [0, G.Order() -1] are as follows:</t> | G.Order() -1] are described in the sections that follow.</t> | |||
<section anchor="rejection-sampling"> | <section anchor="rejection-sampling"> | |||
<name>Rejection Sampling</name> | <name>Rejection Sampling</name> | |||
<t>Generate a random byte array with <tt>Ns</tt> bytes, and attempt to m ap to a Scalar | <t>Generate a random byte array with <tt>Ns</tt> bytes and attempt to ma p to a Scalar | |||
by calling <tt>DeserializeScalar</tt> in constant time. If it succeeds, return t he | by calling <tt>DeserializeScalar</tt> in constant time. If it succeeds, return t he | |||
result. If it fails, try again with another random byte array, until the | result. If it fails, try again with another random byte array, until the | |||
procedure succeeds. Failure to implement <tt>DeserializeScalar</tt> in constant time | procedure succeeds. Failure to implement <tt>DeserializeScalar</tt> in constant time | |||
can leak information about the underlying corresponding Scalar.</t> | can leak information about the underlying corresponding Scalar.</t> | |||
<t>As an optimization, if the group order is very close to a power of | <t>As an optimization, if the group order is very close to a power of | |||
2, it is acceptable to omit the rejection test completely. In | 2, it is acceptable to omit the rejection test completely. In particular, if th | |||
particular, if the group order is p, and there is an integer b | e group order is p and there is an integer b such that |p - 2<sup>b</sup>| is le | |||
such that |p - 2<sup>b</sup>| is less than 2<sup>(b/2)</sup>, then | ss than 2<sup>(b/2)</sup>, then | |||
<tt>RandomScalar</tt> can simply return a uniformly random integer of at | <tt>RandomScalar</tt> can simply return a uniformly random integer of at | |||
most b bits.</t> | most b bits.</t> | |||
</section> | </section> | |||
<section anchor="wide-reduction"> | <section anchor="wide-reduction"> | |||
<name>Wide Reduction</name> | <name>Wide Reduction</name> | |||
<t>Generate a random byte array with <tt>l = ceil(((3 * ceil(log2(G.Orde r()))) / 2) / 8)</tt> | <t>Generate a random byte array with <tt>l = ceil(((3 * ceil(log2(G.Orde r()))) / 2) / 8)</tt> | |||
bytes, and interpret it as an integer; reduce the integer modulo <tt>G.Order()</ | bytes and interpret it as an integer; reduce the integer modulo <tt>G.Order()</t | |||
tt> and return the | t> and return the | |||
result. See <xref section="5" sectionFormat="of" target="HASH-TO-CURVE"/> for th | result. See <xref section="5" sectionFormat="of" target="RFC9380"/> for the unde | |||
e underlying derivation of <tt>l</tt>.</t> | rlying derivation of <tt>l</tt>.</t> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="test-vectors"> | <section anchor="test-vectors"> | |||
<name>Test Vectors</name> | <name>Test Vectors</name> | |||
<t>This section contains test vectors for all ciphersuites listed in <xref target="ciphersuites"/>. | <t>This section contains test vectors for all ciphersuites listed in <xref target="ciphersuites"/>. | |||
All <tt>Element</tt> and <tt>Scalar</tt> values are represented in serialized fo rm and encoded in | All <tt>Element</tt> and <tt>Scalar</tt> values are represented in serialized fo rm and encoded in | |||
hexadecimal strings. Signatures are represented as the concatenation of their | hexadecimal strings. Signatures are represented as the concatenation of their | |||
constituent parts. The input message to be signed is also encoded as a hexadecim al | constituent parts. The input message to be signed is also encoded as a hexadecim al | |||
string.</t> | string.</t> | |||
<t>Each test vector consists of the following information.</t> | <t>Each test vector consists of the following information.</t> | |||
<ul spacing="normal"> | <ul spacing="normal"> | |||
<li>Configuration. This lists the fixed parameters for the particular in stantiation | <li>Configuration. This lists the fixed parameters for the particular in stantiation | |||
of FROST, including MAX_PARTICIPANTS, MIN_PARTICIPANTS, and NUM_PARTICIPANTS.</l i> | of FROST, including MAX_PARTICIPANTS, MIN_PARTICIPANTS, and NUM_PARTICIPANTS.</l i> | |||
<li>Group input parameters. This lists the group secret key and shared p ublic key, | <li>Group input parameters. This lists the group secret key and shared p ublic key, | |||
generated by a trusted dealer as described in <xref target="dep-dealer"/>, as we ll as the | generated by a trusted dealer as described in <xref target="dep-dealer"/>, as we ll as the | |||
input message to be signed. The randomly generated coefficients produced by the | input message to be signed. The randomly generated coefficients produced by the | |||
trusted dealer to share the group signing secret are also listed. Each coefficie nt | trusted dealer to share the group signing secret are also listed. Each coefficie nt | |||
is identified by its index, e.g., <tt>share_polynomial_coefficients[1]</tt> is t he coefficient | is identified by its index, e.g., <tt>share_polynomial_coefficients[1]</tt> is t he coefficient | |||
of the first term in the polynomial. Note that the 0-th coefficient is omitted a s this | of the first term in the polynomial. Note that the 0-th coefficient is omitted, as this | |||
is equal to the group secret key. All values are encoded as hexadecimal strings. </li> | is equal to the group secret key. All values are encoded as hexadecimal strings. </li> | |||
<li>Signer input parameters. This lists the signing key share for each o f the | <li>Signer input parameters. This lists the signing key share for each o f the | |||
NUM_PARTICIPANTS participants.</li> | NUM_PARTICIPANTS participants.</li> | |||
<li>Round one parameters and outputs. This lists the NUM_PARTICIPANTS pa rticipants engaged | <li>Round one parameters and outputs. This lists the NUM_PARTICIPANTS pa rticipants engaged | |||
in the protocol, identified by their NonZeroScalar identifier, and for each part | in the protocol, identified by their NonZeroScalar identifier, and the following | |||
icipant: | for each participant: the hiding and binding commitment values produced in <xre | |||
the hiding and binding commitment values produced in <xref target="frost-round-o | f target="frost-round-one"/>; the randomness | |||
ne"/>; the randomness | ||||
values used to derive the commitment nonces in <tt>nonce_generate</tt>; the resu lting group | values used to derive the commitment nonces in <tt>nonce_generate</tt>; the resu lting group | |||
binding factor input computed in part from the group commitment list encoded as | binding factor input computed in part from the group commitment list encoded as | |||
described in <xref target="dep-encoding"/>; and group binding factor as computed in <xref target="frost-round-two"/>).</li> | described in <xref target="dep-encoding"/>; and the group binding factor as comp uted in <xref target="frost-round-two"/>.</li> | |||
<li>Round two parameters and outputs. This lists the NUM_PARTICIPANTS pa rticipants engaged | <li>Round two parameters and outputs. This lists the NUM_PARTICIPANTS pa rticipants engaged | |||
in the protocol, identified by their NonZeroScalar identifier, along with their corresponding | in the protocol, identified by their NonZeroScalar identifier, along with their corresponding | |||
output signature share as produced in <xref target="frost-round-two"/>.</li> | output signature share as produced in <xref target="frost-round-two"/>.</li> | |||
<li>Final output. This lists the aggregate signature as produced in <xre f target="frost-aggregation"/>.</li> | <li>Final output. This lists the aggregate signature as produced in <xre f target="frost-aggregation"/>.</li> | |||
</ul> | </ul> | |||
<section anchor="frosted25519-sha-512-1"> | <section anchor="frosted25519-sha-512-1"> | |||
<name>FROST(Ed25519, SHA-512)</name> | <name>FROST(Ed25519, SHA-512)</name> | |||
<artwork><![CDATA[ | ||||
<sourcecode type="test-vectors"><![CDATA[ | ||||
// Configuration information | // Configuration information | |||
MAX_PARTICIPANTS: 3 | MAX_PARTICIPANTS: 3 | |||
MIN_PARTICIPANTS: 2 | MIN_PARTICIPANTS: 2 | |||
NUM_PARTICIPANTS: 2 | NUM_PARTICIPANTS: 2 | |||
// Group input parameters | // Group input parameters | |||
participant_list: 1,3 | participant_list: 1,3 | |||
group_secret_key: 7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a7 | group_secret_key: 7b1c33d3f5291d85de664833beb1ad469f7fb6025a0ec78b3a7 | |||
90c6e13a98304 | 90c6e13a98304 | |||
group_public_key: 15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040 | group_public_key: 15d21ccd7ee42959562fc8aa63224c8851fb3ec85a3faf66040 | |||
skipping to change at line 2052 ¶ | skipping to change at line 1841 ¶ | |||
573d71d8d7890f | 573d71d8d7890f | |||
// Signer round two outputs | // Signer round two outputs | |||
P1 sig_share: 001719ab5a53ee1a12095cd088fd149702c0720ce5fd2f29dbecf24 | P1 sig_share: 001719ab5a53ee1a12095cd088fd149702c0720ce5fd2f29dbecf24 | |||
b7281b603 | b7281b603 | |||
P3 sig_share: bd86125de990acc5e1f13781d8e32c03a9bbd4c53539bbc106058bf | P3 sig_share: bd86125de990acc5e1f13781d8e32c03a9bbd4c53539bbc106058bf | |||
d14326007 | d14326007 | |||
sig: 36282629c383bb820a88b71cae937d41f2f2adfcc3d02e55507e2fb9e2dd3cbe | sig: 36282629c383bb820a88b71cae937d41f2f2adfcc3d02e55507e2fb9e2dd3cbe | |||
bd9d2b0844e49ae0f3fa935161e1419aab7b47d21a37ebeae1f17d4987b3160b | bd9d2b0844e49ae0f3fa935161e1419aab7b47d21a37ebeae1f17d4987b3160b | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="frosted448-shake256-1"> | <section anchor="frosted448-shake256-1"> | |||
<name>FROST(Ed448, SHAKE256)</name> | <name>FROST(Ed448, SHAKE256)</name> | |||
<artwork><![CDATA[ | <sourcecode type="test-vectors"><![CDATA[ | |||
// Configuration information | // Configuration information | |||
MAX_PARTICIPANTS: 3 | MAX_PARTICIPANTS: 3 | |||
MIN_PARTICIPANTS: 2 | MIN_PARTICIPANTS: 2 | |||
NUM_PARTICIPANTS: 2 | NUM_PARTICIPANTS: 2 | |||
// Group input parameters | // Group input parameters | |||
participant_list: 1,3 | participant_list: 1,3 | |||
group_secret_key: 6298e1eef3c379392caaed061ed8a31033c9e9e3420726f23b4 | group_secret_key: 6298e1eef3c379392caaed061ed8a31033c9e9e3420726f23b4 | |||
04158a401cd9df24632adfe6b418dc942d8a091817dd8bd70e1c72ba52f3c00 | 04158a401cd9df24632adfe6b418dc942d8a091817dd8bd70e1c72ba52f3c00 | |||
group_public_key: 3832f82fda00ff5365b0376df705675b63d2a93c24c6e81d408 | group_public_key: 3832f82fda00ff5365b0376df705675b63d2a93c24c6e81d408 | |||
skipping to change at line 2147 ¶ | skipping to change at line 1936 ¶ | |||
// Signer round two outputs | // Signer round two outputs | |||
P1 sig_share: e1eb9bfbef792776b7103891032788406c070c5c315e3bf5d64acd4 | P1 sig_share: e1eb9bfbef792776b7103891032788406c070c5c315e3bf5d64acd4 | |||
6ea8855e85b53146150a09149665cbfec71626810b575e6f4dbe9ba3700 | 6ea8855e85b53146150a09149665cbfec71626810b575e6f4dbe9ba3700 | |||
P3 sig_share: 815434eb0b9f9242d54b8baf2141fe28976cabe5f441ccfcd5ee7cd | P3 sig_share: 815434eb0b9f9242d54b8baf2141fe28976cabe5f441ccfcd5ee7cd | |||
b4b52185b02b99e6de28e2ab086c7764068c5a01b5300986b9f084f3e00 | b4b52185b02b99e6de28e2ab086c7764068c5a01b5300986b9f084f3e00 | |||
sig: cd642cba59c449dad8e896a78a60e8edfcbd9040df524370891ff8077d47ce72 | sig: cd642cba59c449dad8e896a78a60e8edfcbd9040df524370891ff8077d47ce72 | |||
1d683874483795f0d85efcbd642c4510614328605a19c6ed806ffb773b6956419537c | 1d683874483795f0d85efcbd642c4510614328605a19c6ed806ffb773b6956419537c | |||
dfdb2b2a51948733de192dcc4b82dc31580a536db6d435e0cb3ce322fbcf9ec23362d | dfdb2b2a51948733de192dcc4b82dc31580a536db6d435e0cb3ce322fbcf9ec23362d | |||
da27092c08767e607bf2093600 | da27092c08767e607bf2093600 | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="frostristretto255-sha-512"> | <section anchor="frostristretto255-sha-512"> | |||
<name>FROST(ristretto255, SHA-512)</name> | <name>FROST(ristretto255, SHA-512)</name> | |||
<artwork><![CDATA[ | <sourcecode type="test-vectors"><![CDATA[ | |||
// Configuration information | // Configuration information | |||
MAX_PARTICIPANTS: 3 | MAX_PARTICIPANTS: 3 | |||
MIN_PARTICIPANTS: 2 | MIN_PARTICIPANTS: 2 | |||
NUM_PARTICIPANTS: 2 | NUM_PARTICIPANTS: 2 | |||
// Group input parameters | // Group input parameters | |||
participant_list: 1,3 | participant_list: 1,3 | |||
group_secret_key: 1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab2 | group_secret_key: 1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab2 | |||
65f2ebc4f970b | 65f2ebc4f970b | |||
group_public_key: e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d | group_public_key: e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d | |||
skipping to change at line 2225 ¶ | skipping to change at line 2014 ¶ | |||
3128277cc31006 | 3128277cc31006 | |||
// Signer round two outputs | // Signer round two outputs | |||
P1 sig_share: 9285f875923ce7e0c491a592e9ea1865ec1b823ead4854b48c8a462 | P1 sig_share: 9285f875923ce7e0c491a592e9ea1865ec1b823ead4854b48c8a462 | |||
87749ee09 | 87749ee09 | |||
P3 sig_share: 7cb211fe0e3d59d25db6e36b3fb32344794139602a7b24f1ae0dc4e | P3 sig_share: 7cb211fe0e3d59d25db6e36b3fb32344794139602a7b24f1ae0dc4e | |||
26ad7b908 | 26ad7b908 | |||
sig: fc45655fbc66bbffad654ea4ce5fdae253a49a64ace25d9adb62010dd9fb2555 | sig: fc45655fbc66bbffad654ea4ce5fdae253a49a64ace25d9adb62010dd9fb2555 | |||
2164141787162e5b4cab915b4aa45d94655dbb9ed7c378a53b980a0be220a802 | 2164141787162e5b4cab915b4aa45d94655dbb9ed7c378a53b980a0be220a802 | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="frostp-256-sha-256-1"> | <section anchor="frostp-256-sha-256-1"> | |||
<name>FROST(P-256, SHA-256)</name> | <name>FROST(P-256, SHA-256)</name> | |||
<artwork><![CDATA[ | <sourcecode type="test-vectors"><![CDATA[ | |||
// Configuration information | // Configuration information | |||
MAX_PARTICIPANTS: 3 | MAX_PARTICIPANTS: 3 | |||
MIN_PARTICIPANTS: 2 | MIN_PARTICIPANTS: 2 | |||
NUM_PARTICIPANTS: 2 | NUM_PARTICIPANTS: 2 | |||
// Group input parameters | // Group input parameters | |||
participant_list: 1,3 | participant_list: 1,3 | |||
group_secret_key: 8ba9bba2e0fd8c4767154d35a0b7562244a4aaf6f36c8fb8735 | group_secret_key: 8ba9bba2e0fd8c4767154d35a0b7562244a4aaf6f36c8fb8735 | |||
fa48b301bd8de | fa48b301bd8de | |||
group_public_key: 023a309ad94e9fe8a7ba45dfc58f38bf091959d3c99cfbd02b4 | group_public_key: 023a309ad94e9fe8a7ba45dfc58f38bf091959d3c99cfbd02b4 | |||
skipping to change at line 2301 ¶ | skipping to change at line 2090 ¶ | |||
6630dde11822c4 | 6630dde11822c4 | |||
// Signer round two outputs | // Signer round two outputs | |||
P1 sig_share: 400308eaed7a2ddee02a265abe6a1cfe04d946ee8720768899619cf | P1 sig_share: 400308eaed7a2ddee02a265abe6a1cfe04d946ee8720768899619cf | |||
abe7a3aeb | abe7a3aeb | |||
P3 sig_share: 561da3c179edbb0502d941bb3e3ace3c37d122aaa46fb54499f15f3 | P3 sig_share: 561da3c179edbb0502d941bb3e3ace3c37d122aaa46fb54499f15f3 | |||
a3331de44 | a3331de44 | |||
sig: 026d8d434874f87bdb7bc0dfd239b2c00639044f9dcb195e9a04426f70bfa4b7 | sig: 026d8d434874f87bdb7bc0dfd239b2c00639044f9dcb195e9a04426f70bfa4b7 | |||
0d9620acac6767e8e3e3036815fca4eb3a3caa69992b902bcd3352fc34f1ac192f | 0d9620acac6767e8e3e3036815fca4eb3a3caa69992b902bcd3352fc34f1ac192f | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
<section anchor="frostsecp256k1-sha-256-1"> | <section anchor="frostsecp256k1-sha-256-1"> | |||
<name>FROST(secp256k1, SHA-256)</name> | <name>FROST(secp256k1, SHA-256)</name> | |||
<artwork><![CDATA[ | <sourcecode type="test-vectors"><![CDATA[ | |||
// Configuration information | // Configuration information | |||
MAX_PARTICIPANTS: 3 | MAX_PARTICIPANTS: 3 | |||
MIN_PARTICIPANTS: 2 | MIN_PARTICIPANTS: 2 | |||
NUM_PARTICIPANTS: 2 | NUM_PARTICIPANTS: 2 | |||
// Group input parameters | // Group input parameters | |||
participant_list: 1,3 | participant_list: 1,3 | |||
group_secret_key: 0d004150d27c3bf2a42f312683d35fac7394b1e9e318249c1bf | group_secret_key: 0d004150d27c3bf2a42f312683d35fac7394b1e9e318249c1bf | |||
e7f0795a83114 | e7f0795a83114 | |||
group_public_key: 02f37c34b66ced1fb51c34a90bdae006901f10625cc06c4f646 | group_public_key: 02f37c34b66ced1fb51c34a90bdae006901f10625cc06c4f646 | |||
skipping to change at line 2377 ¶ | skipping to change at line 2166 ¶ | |||
0becea48ddbfd7 | 0becea48ddbfd7 | |||
// Signer round two outputs | // Signer round two outputs | |||
P1 sig_share: c4fce1775a1e141fb579944166eab0d65eefe7b98d480a569bbbfcb | P1 sig_share: c4fce1775a1e141fb579944166eab0d65eefe7b98d480a569bbbfcb | |||
14f91c197 | 14f91c197 | |||
P3 sig_share: 0160fd0d388932f4826d2ebcd6b9eaba734f7c71cf25b4279a4ca25 | P3 sig_share: 0160fd0d388932f4826d2ebcd6b9eaba734f7c71cf25b4279a4ca25 | |||
81e47b18d | 81e47b18d | |||
sig: 0205b6d04d3774c8929413e3c76024d54149c372d57aae62574ed74319b5ea14 | sig: 0205b6d04d3774c8929413e3c76024d54149c372d57aae62574ed74319b5ea14 | |||
d0c65dde8492a7471437e6c2fe3da49b90d23f642b5c6dbe7e36089f096dd97324 | d0c65dde8492a7471437e6c2fe3da49b90d23f642b5c6dbe7e36089f096dd97324 | |||
]]></artwork> | ]]></sourcecode> | |||
</section> | </section> | |||
</section> | </section> | |||
<section anchor="acknowledgments" numbered="false"> | ||||
<name>Acknowledgments</name> | ||||
<t>This document was improved based on input and contributions by the | ||||
Zcash Foundation engineering team. In addition, the authors of this | ||||
document would like to thank <contact fullname="Isis Lovecruft"/>, | ||||
<contact fullname="Alden Torres"/>, <contact | ||||
fullname="T. Wilson-Brown"/>, and <contact fullname="Conrado Gouvea"/> | ||||
for their input and contributions.</t> | ||||
</section> | ||||
</back> | </back> | |||
<!-- ##markdown-source: | ||||
H4sIAAAAAAAAA+y96WIbR5Iu+r+eosb+0WQbgFALNrnVfWjtp63liHL3zLh9 | ||||
iFoSZLVAFAcFiKKXeZb7FPcB7n2x+0VEZlbWAkrydj1zrJmmSaAql8hYvoiM | ||||
jBwOh96u2K3VXf+T19fl8FW53+T+64utqi7Kde6fZhebcrv1T4vzTbLb42P/ | ||||
uthd+I9evTh9/YmXpOlWvcW7+u+8zDbJJRrLt8lqNyy2u9UwW23Ph6ttWe2G | ||||
wcTLkp06L7c3d/1isyq9ap9eFlVVlJvdzRXee/rq9SPPK662d/3ddl/twvF4 | ||||
MQ69ZKuSu/5jtVHbZO1dl9s359tyf3XXv//o1WPvjbrBRzne3uzUdqN2wwfU | ||||
vedVu2STnyXrcoOmb1TlVZfJdnf2H/typ6q7/qb0roq7/te7Mhv4VbndbdWq | ||||
wm83l/TLN56X7HcX5fau5w99DBdvPBj598vNplyvbzwf/2SyD1Sxzbeq+VW5 | ||||
PU82xbfJDnO76/97llSgGlGXP+FH1GVSrEGr/XZ/mdFs9+v95f84p09HWXlZ | ||||
d3t/5P+1vFyXTp/3L9S6UonzebPDrzbFW7Wtit2NX678v4Pq23VZDm4dSPaG | ||||
Gvsf+2v99ChL6jE8HfmPwRGp2p47w3iabJoff8go3D6LZHN+oEfM+mTk/70s | ||||
88a8t0W1K68u1LbxbbPf++tyn6/WYJvG/JLr/3Ghkqtic54Wu2oETvE8sPcl | ||||
3nqrsMz+u8VoGt7ld4xUvNyn6yLz/6pu/Pvbm6tdeb5Nri5u/FW59XcXyn9U | ||||
bJJNViRr/1Rt3xYZJOTpJsdiEo/TAw/X6+Jqhybu77dvlf+gOC929LSRKP9k | ||||
DYGAUF36Rw/vPzg9Of6EB4D1Qf/Py7cDH1Iw4c8qtS1URZIjg/T9T06en35y | ||||
1/9XGvjQPmcZl/8N9X+ZSnd9vIEPTh/eD5ozbQ3Une3APyVRSrZ5xRN/uFoV | ||||
WaE2uyZNHpNQDnws+cgPZRa7ZHuudnf9i93uqrp7506lsvMRhkG/BMO34egq | ||||
XznTJXmXwbWW4ZWCRFyqTa7yDkVLLO/Gf5lswSHgo+qXGW3YN9pg7NFqOCzE | ||||
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 | ||||
</rfc> | </rfc> | |||
End of changes. 239 change blocks. | ||||
1839 lines changed or deleted | 865 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |