-
Notifications
You must be signed in to change notification settings - Fork 1
PyFrost Documentation
Seyed Ali YaghoubNejad edited this page Jan 4, 2024
·
1 revision
The FROST cryptographic functions and classes that support DKG (Distributed Key Generation) and represent keys can be found in pyfrost.frost
. Below is a detailed discussion of each:
pyfrost.KeyGen(self, dkg_id, threshold, n, node_id, partners, coefficient0=None)
-
Description: This class generates a distributed key using the FROST algorithm. After generating the key, you should save
KeyGen.dkg_key_pair
and can then dispose of this object. -
Inputs:
-
dkg_id
str: Identifier for the key to be generated. -
threshold
int: The key's threshold, denoted as$t$ . -
n
int: Total number of nodes involved in key generation. -
node_id
str: Identifier of the current node. -
partners
List[str]: List of IDs for all nodes participating in key generation. -
coefficient0
int, default=None: Coefficient of$x^0$ (i.e.,$a_0$ ) in the polynomial fromround1()
.
-
-
Example:
>>> dkg_id = # Example data >>> threshold = # Example data >>> n = # Example data >>> node_id = # Example data >>> partners = # Example data >>> key_gen = KeyGen(dkg_id, threshold, n, node_id, partners)
-
Functions:
pyfrost.KeyGen.round1(self)
-
Description: Begins the distributed key generation (DKG) process. It generates a key pair for secure communication and a
$t$ -degree polynomial for the distributed key. It then returns the information that needs to be broadcast to other nodes in the next DKG round. - Inputs: None
-
Outputs:
- A dictionary of data to be broadcast to all nodes in the party.
-
Example:
>>> key_gen.round1() { 'coefficient0_signature': { 'nonce': 368942311427213970711406313762610833921296939621501937670638697118598845895953, 'signature': '0x52ca633d6e48489339ebe80bf1489d36c99c68ed1f5c61b8db09ecfc917557007812ebeee6dece5c0e1aded3ea573c8e6af7eaad4cd96113668da6ffa0736a22' }, 'public_fx': [ 296640523581457280785321718557273115703301708752107592117643511688805891761985, 319296799114006137153383306229340950225807211995602402243547077190257497474828 ], 'public_key': 307729343603318599981084289508680930914727331224976629990450023311552521321408, 'secret_signature': { 'nonce': 367543012542554800983038202897799609990958678036817100887904340714911085163518, 'signature': '0x22b4921be19840bc3c944498f15bca02ad491795b4e55fa4eb3429b6ecca66b55526dc8425f6d49b72ee5370332368251f776d85f49f7cd89a1cda7000c25821' }, 'sender_id': '1' }
pyfrost.KeyGen.round2(self, round1_broadcasted_data)
-
Description: Handles the second DKG round by processing
round1_broadcasted_data
from other nodes. It generates data for inter-node sharing, encrypted with the sender's private key and the receiver's public key fromround1
. -
Inputs:
-
round1_broadcasted_data
dict: Data broadcast inround1
by all other party nodes.
-
-
Outputs:
- A dictionary of data to be sent to each node.
-
Example:
>>> broadcasted_data = [ { 'coefficient0_signature': { 'nonce': 368942311427213970711406313762610833921296939621501937670638697118598845895953, 'signature': '0x52ca633d6e48489339ebe80bf1489d36c99c68ed1f5c61b8db09ecfc917557007812ebeee6dece5c0e1aded3ea573c8e6af7eaad4cd96113668da6ffa0736a22' }, 'public_fx': [ 296640523581457280785321718557273115703301708752107592117643511688805891761985, 319296799114006137153383306229340950225807211995602402243547077190257497474828 ], 'public_key': 307729343603318599981084289508680930914727331224976629990450023311552521321408, 'secret_signature': { 'nonce': 367543012542554800983038202897799609990958678036817100887904340714911085163518, 'signature': '0x22b4921be19840bc3c944498f15bca02ad491795b4e55fa4eb3429b6ecca66b55526dc8425f6d49b72ee5370332368251f776d85f49f7cd89a1cda7000c25821' }, 'sender_id': '1' }, { 'coefficient0_signature': { 'nonce': 359282259074835379588366874028459345193077877777157055998768953650753776127657, 'signature': '0x949dcaa392ed3b5eaace5bc0eca84149e377886bcfe70044e773d2b22b44e827c9f48274de0393f2a5160eb34f47bc71b53126559ee49aa3aaa47a5fe1e6f81a' }, 'public_fx': [ 315333036490095729854689446035420143622165005650260428363337601379831192199151, 380936697578552696715385406651703109495058306480643748360338356258272131197597 ], 'public_key': 402675427562676615467995045686975527154837997106518064654470189954486747681481, 'secret_signature': { 'nonce': 383615891867749631411403307342088317807707823769149008762193706230308867138628, 'signature': '0xf531cdf1e708fa8b8d3887eb8698230e99062ad59d204793b84aa4b82678e035399d0205ba340c6457ffe0552bd42f101a553e7082ee6043b31110bdc40bbe6c' }, 'sender_id': '2' } ] >>> key_gen.round2(broadcasted_data) [ { 'data': 'gAAAAABliu7Eb9BTXwCmwWD3lX6el4ubygJ0SmyZpWNAMHR3-GEedQ5GuZshqy6VyuuRBrAfnET1iN1y9qeqK21NW-GuIEeNn5YQwVrf4_CTmZdxYjQXXpPAFHkRhJQk4nCCeOj5nRF5mllvpKp88-h_sGCQbaGERBiPjQUfmZNYX93puo1T6h3Yve7__uSuElgyU_WNsEWsKNR04utLEpQI0fCrAUy70A==', 'receiver_id': '2', 'sender_id': '1' } ]
pyfrost.KeyGen.round3(self, round2_encrypted_data)
- Description: Computes the node's share of the distributed key. Reports the share and corresponding key, signed with the node's permanent secret for verification. If it detects dishonesty from other nodes, it reports the malicious activity.
-
Inputs:
-
round2_encrypted_data
dict: Data fromround2
where this node is the receiver.
-
-
Outputs:
- A dictionary containing
status
anddata
. OnSUCCESSFUL
status,data
includes the distributed key, the node's share, and a signature. OnCOMPLAINT
status, it includes evidence of dishonesty.
- A dictionary containing
-
Example:
>>> secret_data = [ { 'data': 'gAAAAABliu7E9tMtv2EQeobFyDqXfnP024HnQLzWr_NeGKXB0aQhAiuyGOI490sZ031vMYm0yjRYOFcWvcxMXTPEDC9vMzB426NwzIGFWcfdB4KlC2KXctDqltF22v7N1ZbhpXNUpZqHc-iUL0_i7sOx5KYOoTO72Z_v08WzAPI7D6S8hAo2W_WD9l0ThrDqKUjTk1D1Lb1OXJ9XUOxYva9VDMFM67tWcw==', 'receiver_id': '1', 'sender_id': '2' } ] >>> key_gen.round3(secret_data) { 'data': { 'dkg_public_key': 254503007646527296878921173802219136565731252590780601714649547124390052407428, 'public_share': 434857518911403231281957735014346859455075805194991608153904732048854704562605 }, 'dkg_key_pair': { 'dkg_public_key': 254503007646527296878921173802219136565731252590780601714649547124390052407428, 'share': 188845194665176481294923561223805344235489278818067835766967751779434009802288 }, 'status': 'SUCCESSFUL' }
-
Description: Begins the distributed key generation (DKG) process. It generates a key pair for secure communication and a
pyfrost.Key(self, dkg_key, node_id)
-
Description: Represents a FROST key used for signing. It encapsulates the functionality related to the node's share of the distributed key.
-
Inputs:
-
dkg_key
Dict: Contains the node's share of the key and the corresponding distributed public key. -
node_id
str: Identifier of the current node.
-
-
Example:
>>> key_pair = # Example data >>> peer_id = # Example data >>> key = Key(key_pair, peer_id)
-
Functions:
pyfrost.Key.sign(self, commitments_dict, message, nonces)
- Description: Generates a part of the signature using the node's share of the distributed key.
-
Inputs:
-
commitments_dict
Dict: Contains nonces from all nodes involved in signature generation (should be at least$t$ ). -
message
str: The message to be signed. -
nonces
Dict: All nonces generated by this node.
-
-
Outputs:
- Returns a tuple
(signature, used_nonce)
.signature
is a dictionary with the signature part generated by this node.used_nonce
indicates which nonce was used and should be discarded.
- Returns a tuple
-
Example:
>>> nonces_list = { '1': { 'id': 1, 'public_nonce_d': 349042186269687657903918029097021035946240790024363563457247123869466727724904, 'public_nonce_e': 248237425400201679908511118467475923008578021798639515998329304887202095480425 }, '2': { 'id': 2, 'public_nonce_d': 232003305522782618192381500560408473570697895814518143723528305421500512412148, 'public_nonce_e': 317715046800072131083613892686194614787279733126861218939601214450999918821174 } } >>> message_hash = '651ecdfb1cbc7917644f5c3e16f014ac416470b990793e0ed5c2d2eb892d8c7f' >>> nonces = [ { 'nonce_d_pair': { 300218555050360092639063393209864207073501829680650048817838305094710368296737: 50204928300747094776366629272534245963307256198160244371740708017884005477910 }, 'nonce_e_pair': { 409714228498631570327782540584825593750693294519645628405851081581014656246735: 40463726040983254619472478804244838052786844837455652103326243989755717359788 } }, { 'nonce_d_pair': { 349042186269687657903918029097021035946240790024363563457247123869466727724904: 16993156636626924328333038649772197657544489298745516775023187369640192487374 }, 'nonce_e_pair': { 248237425400201679908511118467475923008578021798639515998329304887202095480425: 100635936258925530229391130527915553787668889110040645976804851747656014449457 } } ] >>> key.sign(nonces_list, message_hash, nonces) ( { 'aggregated_public_nonce': 402344336404068161625970842224046931385487524799112280264088906225521846642963, 'id': 1, 'public_key': 434857518911403231281957735014346859455075805194991608153904732048854704562605, 'signature': 102694053038190246370608485838590127748578269475777603993528845385451820908381 }, { 'nonce_d_pair': { 349042186269687657903918029097021035946240790024363563457247123869466727724904: 16993156636626924328333038649772197657544489298745516775023187369640192487374 }, 'nonce_e_pair': { 248237425400201679908511118467475923008578021798639515998329304887202095480425: 100635936258925530229391130527915553787668889110040645976804851747656014449457 } } )
pyfrost.create_nonces(node_id, number_of_nonces)
- Description: Generates a set of nonces for use in signature issuance.
-
Inputs:
-
node_id
int: Identifier of the current node. -
number_of_nonces
int, default=10: Number of nonces to be generated.
-
-
Outputs:
- Returns a tuple
(nonce_publics, nonce_privates)
.nonce_publics
is a dictionary with the public part of the nonce to be sent to the Signature Aggregator (SA
).nonce_privates
contains the private part of the nonce, which should be stored in theNode
.
- Returns a tuple
-
Example:
>>> node_id = 1 >>> number_of_nonces = 2 >>> pyfrost.create_nonces(node_id, number_of_nonces) ( [ { 'id': 1, 'public_nonce_d': 300218555050360092639063393209864207073501829680650048817838305094710368296737, 'public_nonce_e': 409714228498631570327782540584825593750693294519645628405851081581014656246735 }, { 'id': 1, 'public_nonce_d': 349042186269687657903918029097021035946240790024363563457247123869466727724904, 'public_nonce_e': 248237425400201679908511118467475923008578021798639515998329304887202095480425 } ], [ { 'nonce_d_pair': { 300218555050360092639063393209864207073501829680650048817838305094710368296737: 50204928300747094776366629272534245963307256198160244371740708017884005477910 }, 'nonce_e_pair': { 409714228498631570327782540584825593750693294519645628405851081581014656246735: 40463726040983254619472478804244838052786844837455652103326243989755717359788 } }, { 'nonce_d_pair': { 349042186269687657903918029097021035946240790024363563457247123869466727724904: 16993156636626924328333038649772197657544489298745516775023187369640192487374 }, 'nonce_e_pair': { 248237425400201679908511118467475923008578021798639515998329304887202095480425: 100635936258925530229391130527915553787668889110040645976804851747656014449457 } } ] )
pyfrost.aggregate_nonce(message, commitments_dict, group_key)
- Description: Aggregates nonces and calculates the aggregated nonce for verifying the aggregated signature.
-
Inputs:
-
message
str: The message that was signed. -
commitments_dict
Dict: Nonces from all nodes contributing to the signature. -
group_key
Point: The distributed key generated usingKeyGen
.
-
-
Outputs:
- Returns a Point representing the aggregated nonce.
-
Example:
>>> str_message = '651ecdfb1cbc7917644f5c3e16f014ac416470b990793e0ed5c2d2eb892d8c7f' >>> nonces_list = { '1': { 'id': 1, 'public_nonce_d': 349042186269687657903918029097021035946240790024363563457247123869466727724904, 'public_nonce_e': 248237425400201679908511118467475923008578021798639515998329304887202095480425 }, '2': { 'id': 2, 'public_nonce_d': 232003305522782618192381500560408473570697895814518143723528305421500512412148, 'public_nonce_e': 317715046800072131083613892686194614787279733126861218939601214450999918821174 } } >>> dkg_public_key = 254503007646527296878921173802219136565731252590780601714649547124390052407428 >>> pyfrost.aggregate_nonce(str_message, nonces_list, dkg_public_key) X: 0x7986d308d799825889680f6424a9e82141c2c70433ff832466425032036fe913 Y: 0xfd598e318ca0a073f2a067a51aaca79b13264be5b9c23c8132a5e3f7d16ab71d (On curve <secp256k1>)
pyfrost.aggregate_signatures(message, single_signatures, aggregated_public_nonce, group_key)
- Description: Aggregates individual signatures into a single verifiable signature.
-
Inputs:
-
message
str: The message that was signed. -
single_signatures
List[Dict[str, int]]: Shares of the signature from each node. -
aggregated_public_nonce
Point: The aggregated nonce. -
group_key
int: The distributed key fromKeyGen
.
-
-
Outputs:
- Returns a dictionary with data necessary to verify the aggregated signature.
-
Example:
>>> str_message = '651ecdfb1cbc7917644f5c3e16f014ac416470b990793e0ed5c2d2eb892d8c7f' >>> signs = [ { 'id': 1, 'signature': 102694053038190246370608485838590127748578269475777603993528845385451820908381, 'public_key': 434857518911403231281957735014346859455075805194991608153904732048854704562605, 'aggregated_public_nonce': 402344336404068161625970842224046931385487524799112280264088906225521846642963 }, { 'id': 2, 'signature': 46567393939448326584842681154363617834812892542107946395797044035032337911003, 'public_key': 245652561208681254624868566825006163495824337574238825910552301225881840535843, 'aggregated_public_nonce': 402344336404068161625970842224046931385487524799112280264088906225521846642963 } ] >>> aggregated_public_nonce = X: 0x7986d308d799825889680f6424a9e82141c2c70433ff832466425032036fe913 Y: 0xfd598e318ca0a073f2a067a51aaca79b13264be5b9c23c8132a5e3f7d16ab71d (On curve <secp256k1>) >>> dkg_public_key = 254503007646527296878921173802219136565731252590780601714649547124390052407428 >>> pyfrost.aggregate_signatures(str_message, signs, aggregated_public_nonce, dkg_public_key) { 'nonce': '0x4002743DBbB944415e22F987B1B0c1b57F3F01c5', 'public_key': { 'x': '0x32ab98fd4f3959e532d73d93a9611edaf60ea456166ef8f333fe7c6784caa884', 'y_parity': 0 }, 'signature': 33469357740322377531880181984265837730553597738810646006720726278965997325047, 'message_hash': HexBytes('0x260f59626b383fe31873d9bef3f6a5262af6206e8eb50088da9e41fb9e87dc41') }
pyfrost.verify_group_signature(aggregated_signature)
- Description: Verifies the aggregated signature.
-
Inputs:
-
aggregated_signature
Dict: Containsnonce
,public_key
,aggregated_signature
, andmessage_hash
.
-
-
Outputs:
- Returns a boolean indicating the verification status of the signature.
-
Example:
>>> aggregated_sign = { 'nonce': '0x4002743DBbB944415e22F987B1B0c1b57F3F01c5', 'public_key': { 'x': '0x32ab98fd4f3959e532d73d93a9611edaf60ea456166ef8f333fe7c6784caa884', 'y_parity': 0 }, 'signature': 33469357740322377531880181984265837730553597738810646006720726278965997325047, 'message_hash': HexBytes('0x260f59626b383fe31873d9bef3f6a5262af6206e8eb50088da9e41fb9e87dc41') } >>> pyfrost.frost.verify_group_signature(aggregated_sign) True
pyfrost.verify_single_signature(id, message, commitments, aggregated_nonce, public_key_share, signature, group_key)
- Description: Verifies each node's share of the signature.
-
Inputs:
-
id
int: The node's ID. -
message
str: The signed message. -
commitments
Dict: Nonces from all nodes involved in signature generation. -
aggregated_nonce
Point: The aggregated nonce. -
public_key_share
int: The node's share of the distributed key. -
signature
Dict: The node's signature share. -
group_key
Point: The distributed key fromKeyGen
.
-
-
Outputs:
- Returns a boolean indicating the verification status of the signature share.
-
Example:
>>> id = 1 >>> str_message = '651ecdfb1cbc7917644f5c3e16f014ac416470b990793e0ed5c2d2eb892d8c7f' >>> nonces_list = { '1': { 'id': 1, 'public_nonce_d': 349042186269687657903918029097021035946240790024363563457247123869466727724904, 'public_nonce_e': 248237425400201679908511118467475923008578021798639515998329304887202095480425 }, '2': { 'id': 2, 'public_nonce_d': 232003305522782618192381500560408473570697895814518143723528305421500512412148, 'public_nonce_e': 317715046800072131083613892686194614787279733126861218939601214450999918821174 } } >>> aggregated_public_nonce = X: 0x7986d308d799825889680f6424a9e82141c2c70433ff832466425032036fe913 Y: 0xfd598e318ca0a073f2a067a51aaca79b13264be5b9c23c8132a5e3f7d16ab71d (On curve <secp256k1>) >>> public_share = 434857518911403231281957735014346859455075805194991608153904732048854704562605 >>> sign = { 'id': 1, 'signature': 102694053038190246370608485838590127748578269475777603993528845385451820908381, 'public_key': 434857518911403231281957735014346859455075805194991608153904732048854704562605, 'aggregated_public_nonce': 402344336404068161625970842224046931385487524799112280264088906225521846642963 } >>> dkg_public_key = 254503007646527296878921173802219136565731252590780601714649547124390052407428 >>> pyfrost.pyfrost.verify_single_signature(id, str_message, nonces_list, aggregated_public_nonce, public_share, sign, dkg_public_key) True