You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am working on a small proof of concept (code) and would appreciate any suggestions for further debugging. My goal is to use DKG to create a threshold signature whose shares can be refreshed. This ran successfully a few times (successful signature verification). Most of the time, signature verification fails. During round 3 of the signing process, when a party receives a message and calls UpdateFromBytes, this line from ecdsa/signing/round_3.go is throws an error:
iflen(culprits) >0 {
returnround.WrapError(errors.New("failed to calculate Alice_end or Alice_end_wc"), culprits...)
}
It seems that ProofBobWC.Verify() is returning false here:
// 4. runs only in the "with check" mode from Fig. 10ifX!=nil {
s1ModQ:=new(big.Int).Mod(pf.S1, ec.Params().N)
gS1:=crypto.ScalarBaseMult(ec, s1ModQ)
xEU, err:=X.ScalarMult(e).Add(pf.U)
iferr!=nil||!gS1.Equals(xEU) {
returnfalse
}
}
Logs and code:
2024/07/16 12:13:40 Starting Key Generation
2024/07/16 12:13:56 Received key share from party 1
...
2024/07/16 12:13:56 All key shares received
2024/07/16 12:13:56 Key generation completed successfully.
2024/07/16 12:13:56 All ECDSA public key components are verified and intact.
2024/07/16 12:13:56 Message to sign: 275416438502019691922108054646891190369
2024/07/16 12:13:56 Starting Signing Process
2024/07/16 12:13:56 Attempting to update party {0,party-1} with message from {2,party-3}
...
2024/07/16 12:13:56 Attempting to update party {0,party-1} with message from {2,party-3}
2024/07/16 12:13:56 Successfully updated signing party {0,party-1}
2024/07/16 12:13:56 Successfully updated signing party {1,party-2}
2024/07/16 12:13:56 Successfully updated signing party {1,party-2}
2024/07/16 12:13:56 Attempting to update party {0,party-1} with message from {1,party-2}
2024/07/16 12:13:56 Attempting to update party {2,party-3} with message from {1,party-2
2024/07/16 12:13:56 Failed to update signing party: task signing, party {0,party-1}, round 3, culprits [{1,party-2} {2,party-3}]: failed to calculate Alice_end or Alice_end_wc
// Note: The current implementation is encountering errors in the signing phase.// This could be due to issues with how the key shares are being used or how the// signing parties are communicating. Further investigation and debugging are needed./*TSS (Threshold Signature Scheme) TutorialThis tutorial demonstrates how to use the tss-lib to implement a threshold signature scheme.The process involves distributed key generation and collective signing, which are fundamentalto creating a system where multiple parties can jointly manage encrypted data without anysingle party having complete control.Flow of the program:1. Generate party IDs for participants2. Perform distributed key generation (DKG)3. Use the generated keys to create a threshold signatureThis implementation is a simplified version of a system where:- A group (e.g., a DAO) elects leaders- Leaders generate a shared public key and individual private key shares- Data can be encrypted with the public key- A threshold of leaders can collaborate to decrypt the data- Leaders can be replaced and shares can be refreshed for securityNote: This example doesn't include the encryption/decryption or share refresh processes, focusing instead on the key generation and signing aspects.Important: This is a proof of concept and should not be used in production without further security considerations and error handling.*/package main
import (
"crypto/ecdsa""crypto/rand""fmt""log""math/big""github.com/bnb-chain/tss-lib/v2/common""github.com/bnb-chain/tss-lib/v2/ecdsa/keygen""github.com/bnb-chain/tss-lib/v2/ecdsa/signing""github.com/bnb-chain/tss-lib/v2/tss"
)
// Constants for the number of participants and the threshold// In a real-world scenario, these might be configurable or determined by the DAOconst (
threshold=2// Number of parties required to signparticipants=3// Total number of parties
)
funcmain() {
log.Println("Starting TSS demonstration")
// Key Generationkeys, err:=runKeygen()
iferr!=nil {
log.Fatalf("Keygen failed: %v\n", err)
}
log.Println("Key generation completed successfully.")
// Signing// Generate a random message to signmessage:=common.GetRandomPrimeInt(rand.Reader, 128)
log.Printf("Message to sign: %s\n", message.String())
signature, err:=runSigning(message, keys)
iferr!=nil {
log.Fatalf("Signing failed: %v\n", err)
}
log.Printf("Signature generated: R=%x, S=%x\n", signature.R, signature.S)
// Verify signaturepublicKey:=&ecdsa.PublicKey{
Curve: tss.S256(), // We're using the secp256k1 curveX: keys[0].ECDSAPub.X(),
Y: keys[0].ECDSAPub.Y(),
}
R:=new(big.Int).SetBytes(signature.R)
S:=new(big.Int).SetBytes(signature.S)
verified:=ecdsa.Verify(publicKey, message.Bytes(), R, S)
log.Printf("Signature verified: %v\n", verified)
}
// generatePartyIDs creates a sorted list of party IDs for the TSS protocol// Each party needs a unique identifier for the protocol to work correctlyfuncgeneratePartyIDs(countint) tss.SortedPartyIDs {
varpartyIDs tss.UnSortedPartyIDsfori:=0; i<count; i++ {
id:=fmt.Sprintf("%d", i+1)
moniker:=fmt.Sprintf("party-%d", i+1)
key:=big.NewInt(int64(i+1))
// NewPartyID creates a new party ID with the given id, moniker, and keypartyIDs=append(partyIDs, tss.NewPartyID(id, moniker, key))
}
// SortPartyIDs sorts the party IDs, which is required for the protocolreturntss.SortPartyIDs(partyIDs)
}
// runKeygen performs the distributed key generation processfuncrunKeygen() ([]*keygen.LocalPartySaveData, error) {
log.Println("Starting Key Generation")
partyIDs:=generatePartyIDs(participants)
// Create a peer context, which holds information about all participantspeerCtx:=tss.NewPeerContext(partyIDs)
// Create parameters for the TSS protocolparams:=tss.NewParameters(tss.S256(), peerCtx, partyIDs[0], len(partyIDs), threshold)
// Channels for communication between partiesoutCh:=make(chan tss.Message, len(partyIDs))
endCh:=make(chan*keygen.LocalPartySaveData, len(partyIDs))
parties:=make([]*keygen.LocalParty, len(partyIDs))
fori:=0; i<len(partyIDs); i++ {
// Create new parameters for each party, ensuring they have the correct PartyIDparams:=tss.NewParameters(params.EC(), params.Parties(), partyIDs[i], params.PartyCount(), params.Threshold())
parties[i] =keygen.NewLocalParty(params, outCh, endCh).(*keygen.LocalParty)
}
// Start each party in a separate goroutinefor_, p:=rangeparties {
gofunc(p*keygen.LocalParty) {
iferr:=p.Start(); err!=nil {
log.Printf("Failed to start party: %v\n", err)
}
}(p)
}
keys:=make([]*keygen.LocalPartySaveData, len(partyIDs))
keyCount:=0// Main event loop for key generationfor {
select {
casemsg:=<-outCh:
// Handle outgoing messagesdest:=msg.GetTo()
ifdest==nil {
// Broadcast messagefor_, p:=rangeparties {
ifp.PartyID().Index!=msg.GetFrom().Index {
gohandleMessage(p, msg)
}
}
} else {
// Point-to-point messagegohandleMessage(parties[dest[0].Index], msg)
}
casekey:=<-endCh:
// Collect key shares from each partykeys[keyCount] =keykeyCount++log.Printf("Received key share from party %d\n", keyCount)
ifkeyCount==len(partyIDs) {
log.Println("All key shares received")
returnkeys, nil
}
}
}
}
// runSigning performs the distributed signing processfuncrunSigning(message*big.Int, keys []*keygen.LocalPartySaveData) (*common.SignatureData, error) {
log.Println("Starting Signing Process")
// For signing, we only need threshold + 1 partiessignPartyIDs:=generatePartyIDs(threshold+1)
peerCtx:=tss.NewPeerContext(signPartyIDs)
params:=tss.NewParameters(tss.S256(), peerCtx, signPartyIDs[0], len(signPartyIDs), threshold)
outCh:=make(chan tss.Message, len(signPartyIDs))
endCh:=make(chan*common.SignatureData, len(signPartyIDs))
parties:=make([]*signing.LocalParty, len(signPartyIDs))
fori:=0; i<len(signPartyIDs); i++ {
params:=tss.NewParameters(params.EC(), params.Parties(), signPartyIDs[i], params.PartyCount(), params.Threshold())
parties[i] =signing.NewLocalParty(message, params, *keys[i], outCh, endCh).(*signing.LocalParty)
}
// Start each signing party in a separate goroutinefor_, p:=rangeparties {
gofunc(p*signing.LocalParty) {
iferr:=p.Start(); err!=nil {
log.Printf("Failed to start signing party: %v\n", err)
}
}(p)
}
// Main event loop for signingfor {
select {
casemsg:=<-outCh:
// Handle outgoing messagesdest:=msg.GetTo()
ifdest==nil {
// Broadcast messagefor_, p:=rangeparties {
ifp.PartyID().Index!=msg.GetFrom().Index {
gohandleSigningMessage(p, msg)
}
}
} else {
// Point-to-point messagegohandleSigningMessage(parties[dest[0].Index], msg)
}
casesignature:=<-endCh:
// Signature is readylog.Println("Signature generated")
returnsignature, nil
}
}
}
// handleMessage processes incoming messages for key generationfunchandleMessage(p*keygen.LocalParty, msg tss.Message) {
bytes, _, err:=msg.WireBytes()
iferr!=nil {
log.Printf("Error getting wire bytes: %v\n", err)
return
}
if_, err:=p.UpdateFromBytes(bytes, msg.GetFrom(), msg.IsBroadcast()); err!=nil {
log.Printf("Failed to update party: %v\n", err)
}
}
// handleSigningMessage processes incoming messages for signingfunchandleSigningMessage(p*signing.LocalParty, msg tss.Message) {
bytes, _, err:=msg.WireBytes()
iferr!=nil {
log.Printf("Error getting wire bytes: %v\n", err)
return
}
if_, err:=p.UpdateFromBytes(bytes, msg.GetFrom(), msg.IsBroadcast()); err!=nil {
log.Printf("Failed to update signing party: %v\n", err)
}
}
The text was updated successfully, but these errors were encountered:
You know that your code works with 1-2 values, right? I am encountering a similar error in my own code, but mine says “failed to calculate Bob_mid or Bob_mid_wc”. I can’t figure out why it doesn’t work when I change the number of participants and the threshold. It might be related to the transmission of messages.
You know that your code works with 1-2 values, right? I am encountering a similar error in my own code, but mine says “failed to calculate Bob_mid or Bob_mid_wc”. I can’t figure out why it doesn’t work when I change the number of participants and the threshold. It might be related to the transmission of messages.
I am working on a small proof of concept (code) and would appreciate any suggestions for further debugging. My goal is to use DKG to create a threshold signature whose shares can be refreshed. This ran successfully a few times (successful signature verification). Most of the time, signature verification fails. During round 3 of the signing process, when a party receives a message and calls
UpdateFromBytes
, this line from ecdsa/signing/round_3.go is throws an error:It seems that
ProofBobWC.Verify()
is returning false here:Logs and code:
The text was updated successfully, but these errors were encountered: