ZIP 312
FROST for Spend Authorization Multisignatures
- Draft
Contents
Preamble
- ZIP
- 312
- Title
- FROST for Spend Authorization Multisignatures
- Status
- Draft
- Category
- Wallet
- Created
- 2022-08-dd
- License
- MIT
- Discussions-To
- https://github.com/zcash/zips/issues/382
- Pull-Request
- https://github.com/zcash/zips/pull/662
Terminology
{Edit this to reflect the key words that are actually used.} The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in RFC 2119.1
The terms below are to be interpreted as follows:
- Unlinkability
-
The property of statistical independence of signatures from the signers' long-term keys, ensuring that (for perfectly uniform generation of Randomizers and no leakage of metadata) it is impossible to determine whether two transactions were generated by the same party.
Abstract
This proposal adapts FROST2, a threshold signature scheme, to make it unlinkable, which is a requirement for its use in the Zcash protocol. The adapted scheme generates signatures compatible with spend authorization signatures in the Sapling and Orchard shielded protocols as deployed in Zcash.
Motivation
In the Zcash protocol, Spend Authorization Signatures are employed to authorize a transaction. The ability to generate these signatures with the user's private key is what effectively allows the user to spend funds.
This is a security-critical step, since anyone who obtains access to the private key will be able to spend the user's funds. For this reason, one interesting possibility is to require multiple parties to allow the transaction to go through. This can be accomplished with threshold signatures, where the private key is split between parties (or generated already split using a distributed protocol) in a way that a threshold (e.g. 2 out of 3) of them must sign the transaction in order to create the final signature. This enables scenarios such as users and third-party services sharing custody of a wallet, or a group of people managing shared funds, for example.
FROST is one of such threshold signature protocols. However, it can't be used as-is since the Zcash protocol also requires re-randomizing public and private keys to ensure unlinkability between transactions. This ZIP specifies a variant of FROST with re-randomization support. This variant is named "Re-Randomized FROST" and has been described in3.
Requirements
- All signatures generated by following this ZIP must be verified successfully as Sapling or Orchard spend authorization signatures using the appropriate validating key.
- The signatures generated by following this ZIP should meet the security criteria for Signature with Re-Randomizable Keys as specified in the Zcash protocol4.
- The threat model described below must be taken into account.
Threat Model
In normal usage, a Zcash user follows multiple steps in order to generate a shielded transaction:
- The transaction is created.
- The transaction is signed with a re-randomized version of the user's spend authorization private key.
- The zero-knowledge proof for the transaction is created with the randomizer as an auxiliary (secret) input, among others.
When employing re-randomizable FROST as specified in this ZIP, the goal is to split the spend authorization private key among multiple possible signers. This means that the proof generation will still be performed by a single participant, likely the one that created the transaction in the first place. Note that this user already controls the privacy of the transaction since they are responsible for creating the proof.
This fits well into the "Coordinator" role from the FROST specification 5. The Coordinator is responsible for sending the message to be signed to all participants, and to aggregate the signature shares.
With those considerations in mind, the threat model considered in this ZIP is:
- The Coordinator is trusted with the privacy of the transaction (which includes the unlinkability property). A rogue Coordinator will be able to break unlinkability and privacy, but should not be able to create signed transactions without the approval of
MIN_PARTICIPANTSparticipants, as specified in FROST. - All key share holders are also trusted with the privacy of the transaction, thus a rogue key share holder will be able to break its privacy and unlinkability.
Non-requirements
- This ZIP does not support removing the Coordinator role, as described in 6.
- This ZIP does not prevent key share holders from linking the signing operation to a transaction in the blockchain.
- Like the FROST specification7, this ZIP does not specify a key generation procedure; but refer to that specification for guidelines.
- Network privacy is not in scope for this ZIP, and must be obtained with other tools if desired.
Specification
Algorithms in this section are specified using Python pseudo-code, in the same fashion as the FROST specification8.
The types Scalar, Element, and G are defined in9, as well as the notation for elliptic-curve arithmetic, which uses the additive notation. Note that this notation differs from that used in the Zcash Protocol Specification. For example, G.ScalarMult(P, k) is used for scalar multiplication, where the protocol spec would use with the group implied by .
An additional per-ciphersuite hash function is used, denote HR(m), which receives an arbitrary-sized byte string and returns a Scalar. It is defined concretely in the Ciphersuites section.
Key Generation
While key generation is out of scope for this ZIP and the FROST spec10, it needs to be consistent with FROST, see11 for guidance. The spend authorization private key 12 is the particular key that must be used in the context of this ZIP. Note that the is usually derived from the spending key , though that is not required. Not doing so allows using distributed key generation, since the key it generates is unpredictable. Note however that not deriving from prevents using seed phrases to recover the original secret (which may be something desirable in the context of FROST).
Re-randomizable FROST
To add re-randomization to FROST, follow the specification13 with the following modifications.
Randomizer Generation
A new helper function is defined, which generates a randomizer. The encode_signing_package is defined as the byte serialization of the msg, commitment_list values as described in14. Implementations MAY choose another encoding as long as all values (the message, and the identifier, binding nonce and hiding nonce for each participant) are unambiguously encoded.
The function random_bytes(n) is defined in15 and it returns a buffer with n bytes sampled uniformly at random. The constant Ns is also specified in16 and is the size of a serialized scalar.
randomizer_generate():
Inputs:
- msg, the message being signed in the current FROST signing run
- commitment_list = [(i, hiding_nonce_commitment_i,
binding_nonce_commitment_i), ...], a list of commitments issued by
each participant, where each element in the list indicates a
NonZeroScalar identifier i and two commitment Element values
(hiding_nonce_commitment_i, binding_nonce_commitment_i). This list
MUST be sorted in ascending order by identifier.
Outputs: randomizer, a Scalar
def randomizer_generate(msg, commitment_list):
# Generate a random byte buffer with the size of a serialized scalar
rng_randomizer = random_bytes(Ns)
signing_package_enc = encode_signing_package(commitment_list, msg)
randomizer_input = rng_randomizer || signing_package_enc
return HR(randomizer_input)
Round One - Commitment
Roune One is exactly the same as specified17. But for context, it involves these steps:
- Each signer generates nonces and their corresponding public commitments. A nonce is a pair of Scalar values, and a commitment is a pair of Element values.
- The nonces are stored locally by the signer and kept private for use in the second round.
- The commitments are sent to the Coordinator.
Round Two - Signature Share Generation
In Round Two, the Coordinator generates a random scalar randomizer by calling randomizer_generate and sends it to each signer, over a confidential and authenticated channel, along with the message and the set of signing commitments. (Note that this differs from regular FROST which just requires an authenticated channel.)
In Zcash, the message that needs to be signed is actually the SIGHASH transaction hash, which does not convey enough information for the signers to decide if they want to authorize the transaction or not. Therefore, in practice, more data is needed to be sent (over the same encrypted, authenticated channel) from the Coordinator to the signers, possibly the transaction itself, openings of value commitments, decryption of note ciphertexts, etc.; and the signers MUST check that the given SIGHASH matches the data sent from the Coordinator, or compute the SIGHASH themselves from that data. However, the specific mechanism for that process is outside the scope of this ZIP.
The randomized sign function is defined as the regular FROST sign function, but with its inputs modified relative to the randomizer as following:
sk_i = sk_i + randomizergroup_public_key = group_public_key + G.ScalarBaseMult(randomizer)
Signature Share Verification and Aggregation
The randomized aggregate function is defined as the regular FROST aggregate function, but with its inputs modified relative to the randomizer as following:
group_public_key = group_public_key + G.ScalarBaseMult(randomizer)
The randomized verify_signature_share function is defined as the regular FROST verify_signature_share function, but with its inputs modified relative to the randomizer as following:
PK_i = PK_i + G.ScalarBaseMult(randomizer)group_public_key = group_public_key + G.ScalarBaseMult(randomizer)
Ciphersuites
FROST(Jubjub, BLAKE2b-512)
This ciphersuite uses Jubjub for the Group and BLAKE2b-512 for the Hash function H meant to produce signatures indistinguishable from RedJubjub Sapling Spend Authorization Signatures as specified in18.
- Group: Jubjub19 with base point as defined in20.
- Order: as defined in21.
- Identity: as defined in22.
- RandomScalar(): Implemented by returning a uniformly random Scalar in the range [0,
G.Order()- 1]. Refer to {{frost-randomscalar}} for implementation guidance. - SerializeElement(P): Implemented as as defined in23
- DeserializeElement(P): Implemented as as defined in24, returning an error if is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails.
- SerializeScalar: Implemented by outputting the little-endian 32-byte encoding of the Scalar value.
- DeserializeScalar: Implemented by attempting to deserialize a Scalar from a little-endian 32-byte string. This function can fail if the input does not represent a Scalar in the range [0,
G.Order()- 1].
- Hash (
H): BLAKE2b-51225 (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.- H1(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). - H2(m): Implemented by computing BLAKE2b-512("Zcash_RedJubjubH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). (This is equivalent to , as defined by the scheme instantiated in26.) - H3(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). - H4(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubM", m).
- H5(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubC", m).
- HR(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubA", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order().
- H1(m): Implemented by computing BLAKE2b-512("FROST_RedJubjubR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
Signature verification is as specified in27 for RedJubjub.
FROST(Pallas, BLAKE2b-512)
This ciphersuite uses Pallas for the Group and BLAKE2b-512 for the Hash function H meant to produce signatures indistinguishable from RedPallas Orchard Spend Authorization Signatures as specified in28.
- Group: Pallas29 with base point as defined in30.
- Order: as defined in31.
- Identity: as defined in32.
- RandomScalar(): Implemented by returning a uniformly random Scalar in the range [0,
G.Order()- 1]. Refer to {{frost-randomscalar}} for implementation guidance. - SerializeElement(P): Implemented as as defined in33.
- DeserializeElement(P): Implemented as as defined in34, failing if is returned. Additionally, this function validates that the resulting element is not the group identity element, returning an error if the check fails.
- SerializeScalar: Implemented by outputting the little-endian 32-byte encoding of the Scalar value.
- DeserializeScalar: Implemented by attempting to deserialize a Scalar from a little-endian 32-byte string. This function can fail if the input does not represent a Scalar in the range [0,
G.Order()- 1].
- Hash (
H): BLAKE2b-51235 (BLAKE2b with 512-bit output and 16-byte personalization string), and Nh = 64.- H1(m): Implemented by computing BLAKE2b-512("FROST_RedPallasR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). - H2(m): Implemented by computing BLAKE2b-512("Zcash_RedPallasH", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). (This is equivalent to , as defined by the scheme instantiated in36.) - H3(m): Implemented by computing BLAKE2b-512("FROST_RedPallasN", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order(). - H4(m): Implemented by computing BLAKE2b-512("FROST_RedPallasM", m).
- H5(m): Implemented by computing BLAKE2b-512("FROST_RedPallasC", m).
- HR(m): Implemented by computing BLAKE2b-512("FROST_RedPallasA", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
G.Order().
- H1(m): Implemented by computing BLAKE2b-512("FROST_RedPallasR", m), interpreting the 64 bytes as a little-endian integer, and reducing the resulting integer modulo
Signature verification is as specified in37 for RedPallas.
Rationale
FROST is a threshold Schnorr signature scheme, and Zcash Spend Authorization are also Schnorr signatures, which allows the usage of FROST with Zcash. However, since there is no widespread standard for Schnorr signatures, it must be ensured that the signatures generated by the FROST variant specified in this ZIP can be verified successfully by a Zcash implementation following its specification. In practice this entails making sure that the generated signature can be verified by the function specified in 38:
- The FROST signature, when split into R and S in the first step of , must yield the values expected by the function. This is ensured by defining SerializeElement and SerializeScalar in each ciphersuite to yield those values.
- The challenge c used during FROST signing must be equal to the challenge c computed during . This requires defining the ciphersuite H2 function as the Zcash function in the ciphersuites, and making sure its input will be the same. Fortunately FROST and Zcash use the same input order (R, public key, message) so we just need to make sure that SerializeElement (used to compute the encoded public key before passing to the hash function) matches what expects; which is possible since both R and vk (the public key) are encoded in the same way as in Zcash.
- Note that
r(and thusR) will not be generated as specified in RedDSA.Sign. This is not an issue however, since with Schnorr signatures it does not matter for the verifier how thervalue was chosen, it just needs to be generated uniformly at random, which is true for FROST. - The above will ensure that the verification equation in will pass, since FROST ensures the exact same equation will be valid as described in39.
The second step is adding the re-randomization functionality so that each FROST signing generates a re-randomized signature:
- Anywhere the public key is used, the randomized public key must be used instead. This is exactly what is done in the functions defined above.
- The re-randomization must be done in each signature share generation, such that the aggregated signature must be valid under verification with the randomized public key. The
Rvalue from the signature is not influenced by the randomizer so we just need to focus on thezvalue (using FROST notation). Recall thatzmust equal tor + (c * sk), and that each signature share isz_i = (hiding_nonce + (binding_nonce * binding_factor)) + (lambda_i * c * sk_i). The first terms are not influenced by the randomizer so we can only look into the second term of each top-level addition, i.e.c * skmust be equal tosum(lambda_i * c * sk_i)for each participanti. Under re-randomization these becomec * (sk + randomizer)(see , which refers to the randomizer as ) andsum(lambda_i * c * (sk_i + randomizer)). The latter can be rewritten asc * (sum(lambda_i * sk_i) + randomizer * sum(lambda_i). Sincesum(lambda_i * sk_i) == skper the Shamir secret sharing mechanism used by FROST, and sincesum(lambda_i) == 140, we arrive atc * (sk + randomizer)as required. - The re-randomization procedure must be exactly the same as in 41 to ensure that re-randomized keys are uniformly distributed and signatures are unlinkable. This is also true; observe that
randomizer_generategenerates randomizer uniformly at random as required by ; and signature generation is compatible with , , and as explained in the previous item.
The security of Re-Randomized FROST with respect to the security assumptions of regular FROST is shown in42.
Reference implementation
The reddsa crate43 contains a re-randomized FROST implementation of both ciphersuites.
References
RFC 2119: Key words for use in RFCs to Indicate Requirement Levels↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures. Section 5: Two-Round FROST Signing Protocol↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures. Section 7.3: Removing the Coordinator Role↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures. Section 3.1: Prime-Order Group↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures. Appendix B: Trusted Dealer Key Generation↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 4.15: Spend Authorization Signature (Sapling and Orchard)↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.3: Jubjub↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.9.6: Pallas and Vesta↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7.1: Spend Authorization Signature (Sapling and Orchard)↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas↩︎
RFC 9591: The Flexible Round-Optimized Schnorr Threshold (FROST) Protocol for Two-Round Schnorr Signatures. Appendix B: Schnorr Signature Generation and Verification for Prime-Order Groups↩︎
Prove that the sum of the Lagrange (interpolation) coefficients is equal to 1↩︎
Zcash Protocol Specification, Version 2022.3.4 [NU5]. Section 5.4.7: RedDSA, RedJubjub, and RedPallas↩︎
Citation graph
Cites
None