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 "&#160;"> <!ENTITY nbsp "&#160;">
<!ENTITY zwsp "&#8203;"> <!ENTITY zwsp "&#8203;">
<!ENTITY nbhy "&#8209;"> <!ENTITY nbhy "&#8209;">
<!ENTITY wj "&#8288;"> <!ENTITY wj "&#8288;">
]> ]>
<?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&nbsp;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 &lt;=
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
mjAc3+1tT11ti81uVCTZlpsNx+H4znxSt3urLu7XwT3rfVBH1N91BNfMKBwP
A3BSSKuw25abc7U9xeTD/gllTNDGhMI7V8kVVuHOJJrPx9Oz4Ozh5iyYn92/
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
aSvZ/7MfmIPZtzSFJzjUxd72vTq0hc/JdFzqxNPmN7290wf37tFE7vKKFZu9
HJuv2/8jff1POeruNC4f+7z6NCDh4HvOi3fc52vlyQ9aHfklsdqLGlaInrQg
qqMlBY70bCuxfpRjhZs6YqUjYeYclScnDeUIJHtNVnn6TQRkBZiHolz94Vgu
z82z4oy8pLFjSzRn07rp67ItfXVjZ9zXPf9ryjC4KIgUZ2LgnGcKijBo8Njz
LZTTaDT6ZuCMvDFaOTnPG83tRD2j1vhzJ4RldQN1momiwesNwdZRBDrl5hei
/69LF8ma2JQsDV4/OjzB26angRGNh0ouUH4OnVgutzqropVlQBikHlpT/cga
52cMqZ1e9EFxAwfybmAGPbdWbdBkAa1SpIdOB/zGUetv1i6HhkQSVqy1OB/V
EzrIJgNTRegQKflAemsIoh/MGBq9H9mqRF2gVA/nGJio70ETWDsw2Pe9dnAO
x40B9xCtHvbBh5yuuzN30N+hBkSnHVAjNgdKZ27AO6+ppfNkEldMaBl+1xC/
FQ3hrJVLrua8ZLxa4t0E8jNa3g8Se5cnsLjf9An6Gf7/sNA6LYwoiW+Tu2JZ
c7Hz3McybmKDGTrzU3OvoUrz26rDxWbJ5PsGJze/MgxKkfRDrUu26QewJ8el
exn0fewpn9eipLseNfhi0EwUdj6/Ffk2J/wBENh08QnPcaMP3ojjrfLmIEh2
CJ++2ZTXG82XLeKDemfOO0c9azNwZsNMKhzZWSwib8/rFms6dAXkLCzOFX5s
vun14V87dYsev9AL8kjzwn030vVpT3DtIJ6U1I4UKn1HCa3m7PmeN0DbLMeB
Uc/4iA7FW/p7YA8aSrIuHyvLJcjaPp7dkRIxL/LAGR7QPnB9WKKVwu1m+ugg
C6jILyZ2R3D0uxH5dY3I0L+szmXp+njhNmVg4aSh61GDAiZx4FgiEhWr9lYm
Q1cTkwrQYbmzZnfVUZfjOtgWk2EV0H60GzszkK39JJmgO3d4O0usis4bGspe
Hm27oZMzjone85/ER9Tl+9/pIjbdhNYyTyZHH4XBdZdkFJUN9rspAW5hhTr5
SW9IUliZixa5Oye0QBflGcdlzrBQeAMz7KXk99/XRMDvBybnOYLZsqW9wOHn
9xDsfCiu2p4bBn6ri+C5fWokgRUPjmxLfY9w7wbZNKbXMkcO1ulpwZoQ2Wm5
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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.