From 87575a71f27c88172b71e99dfa19c40f17592a99 Mon Sep 17 00:00:00 2001 From: "Lucas\\ Menendez" Date: Mon, 11 Mar 2024 11:57:52 +0100 Subject: [PATCH 1/3] optional strict mode and swap on circom-arbo helpers --- crypto/zk/prover/pubsignals.go | 4 ++-- util/zk.go | 24 ++++++++++++------- util/zk_test.go | 8 ++----- vochain/transaction/proofs/zkproof/zkproof.go | 8 +++++++ 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/crypto/zk/prover/pubsignals.go b/crypto/zk/prover/pubsignals.go index 1aa769397..f169e5730 100644 --- a/crypto/zk/prover/pubsignals.go +++ b/crypto/zk/prover/pubsignals.go @@ -42,7 +42,7 @@ func (p *Proof) ElectionID() ([]byte, error) { if err != nil { return nil, err } - return util.SplittedArboStrToBytes(electionID1str, electionID2str), nil + return util.SplittedArboStrToBytes(electionID1str, electionID2str, false, false), nil } // VoteHash returns the VoteHash included into the current proof. @@ -55,7 +55,7 @@ func (p *Proof) VoteHash() ([]byte, error) { if err != nil { return nil, err } - return util.SplittedArboStrToBytes(voteHash1str, voteHash2str), nil + return util.SplittedArboStrToBytes(voteHash1str, voteHash2str, false, true), nil } // CensusRoot returns the CensusRoot included into the current proof. diff --git a/util/zk.go b/util/zk.go index e797fdd4b..21f1164e8 100644 --- a/util/zk.go +++ b/util/zk.go @@ -43,25 +43,31 @@ func BytesToArboSplitStr(input []byte) []string { } // SplittedArboToBytes function receives a slice of big.Int's and returns the -func SplittedArboToBytes(input1, input2 *big.Int) []byte { +func SplittedArboToBytes(input1, input2 *big.Int, swap, strict bool) []byte { // when the last bytes are 0, the SwapEndianness function removes them // so we need to add them back until we have 16 bytes in both parts - b1 := arbo.SwapEndianness(input1.Bytes()) - for len(b1) < 16 { - b1 = append(b1, 0) + b1 := input1.Bytes() + b2 := input2.Bytes() + if swap { + b1 = arbo.SwapEndianness(b1) + b2 = arbo.SwapEndianness(b2) } - b2 := arbo.SwapEndianness(input2.Bytes()) - for len(b2) < 16 { - b2 = append(b2, 0) + if strict { + for len(b1) < 16 { + b1 = append(b1, 0) + } + for len(b2) < 16 { + b2 = append(b2, 0) + } } return append(b1, b2...) } // SplittedArboStrToBytes function wraps SplittedArboToBytes to return the input as []byte -func SplittedArboStrToBytes(input1, input2 string) []byte { +func SplittedArboStrToBytes(input1, input2 string, swap, strict bool) []byte { b1 := new(big.Int) b1.SetString(input1, 10) b2 := new(big.Int) b2.SetString(input2, 10) - return SplittedArboToBytes(b1, b2) + return SplittedArboToBytes(b1, b2, swap, strict) } diff --git a/util/zk_test.go b/util/zk_test.go index b7a1e0360..08f501b53 100644 --- a/util/zk_test.go +++ b/util/zk_test.go @@ -22,17 +22,13 @@ func TestBytesToArboStr(t *testing.T) { } func TestConversionConsistency(t *testing.T) { - originalInput := []byte("test input") - + originalInput := RandomBytes(20) // Convert to strings strParts := BytesToArboSplitStr(originalInput) - // Convert strings back to bytes - reconstructedBytes := SplittedArboStrToBytes(strParts[0], strParts[1]) - + reconstructedBytes := SplittedArboStrToBytes(strParts[0], strParts[1], true, true) // Hash the original input to compare with reconstructed bytes expectedHash := sha256.Sum256(originalInput) - // Check if reconstructed bytes match the hash of the original input qt.Assert(t, bytes.Equal(reconstructedBytes, expectedHash[:]), qt.IsTrue) } diff --git a/vochain/transaction/proofs/zkproof/zkproof.go b/vochain/transaction/proofs/zkproof/zkproof.go index 6bc1e468d..5eb6729a6 100644 --- a/vochain/transaction/proofs/zkproof/zkproof.go +++ b/vochain/transaction/proofs/zkproof/zkproof.go @@ -3,12 +3,14 @@ package zkproof import ( "bytes" "crypto/sha256" + "encoding/hex" "fmt" "math/big" "go.vocdoni.io/dvote/crypto/zk" "go.vocdoni.io/dvote/crypto/zk/circuit" "go.vocdoni.io/dvote/crypto/zk/prover" + "go.vocdoni.io/dvote/log" "go.vocdoni.io/dvote/vochain/state" "go.vocdoni.io/proto/build/go/models" ) @@ -34,6 +36,9 @@ func (*ProofVerifierZk) Verify(process *models.Process, envelope *models.VoteEnv } hashedPid := sha256.Sum256(process.ProcessId) if !bytes.Equal(hashedPid[:], proofProcessID) { + log.Debugw("process id mismatch", + "processID", hex.EncodeToString(process.ProcessId), + "proofProcessID", hex.EncodeToString(proofProcessID)) return false, nil, fmt.Errorf("process id mismatch %x != %x", process.ProcessId, proofProcessID) } // verify the census root @@ -51,6 +56,9 @@ func (*ProofVerifierZk) Verify(process *models.Process, envelope *models.VoteEnv } hashedVotePackage := sha256.Sum256(envelope.VotePackage) if !bytes.Equal(hashedVotePackage[:], proofVoteHash) { + log.Debugw("process id mismatch", + "votPackage", hex.EncodeToString(envelope.VotePackage), + "proofVotePackage", hex.EncodeToString(proofVoteHash)) return false, nil, fmt.Errorf("vote hash mismatch") } // get vote weight from proof publicSignals From c143b7b04687d0463c579d0df6bc647da331bb59 Mon Sep 17 00:00:00 2001 From: "Lucas\\ Menendez" Date: Wed, 17 Apr 2024 13:01:16 +0200 Subject: [PATCH 2/3] dirty commit --- cmd/playground/main.go | 83 +++++++++++++++++++ crypto/zk/prover/pubsignals.go | 11 ++- vochain/transaction/proofs/zkproof/zkproof.go | 13 +-- 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 cmd/playground/main.go diff --git a/cmd/playground/main.go b/cmd/playground/main.go new file mode 100644 index 000000000..61c6aa474 --- /dev/null +++ b/cmd/playground/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "flag" + "fmt" + "log" + "strings" + + "go.vocdoni.io/dvote/util" +) + +func main() { + strInputList := flag.String("inputs", "", "inputs parts") + strExpected := flag.String("raw", "", "expected raw") + flag.Parse() + + if *strInputList == "" { + log.Fatal("inputs is required") + } + inputList := strings.Split(*strInputList, ",") + if len(inputList) != 2 { + log.Fatal("inputs is required, and must be a comma separated list of two big ints") + } + if *strExpected == "" { + log.Fatal("raw expected is required") + } + rawExpected, err := hex.DecodeString(*strExpected) + if err != nil { + log.Fatalf("error decoding vote package: %s", err) + } + expectedHash := sha256.Sum256(rawExpected) + + rebuildHash := util.SplittedArboStrToBytes(inputList[0], inputList[1], false, false) + fmt.Println("") + fmt.Println("Without swap endianess and lazy") + fmt.Println("") + fmt.Println("- Provided raw", hex.EncodeToString(rawExpected), len(rawExpected)) + fmt.Println("") + fmt.Println("- Rebuild hash", hex.EncodeToString(rebuildHash), len(rebuildHash)) + fmt.Println("") + fmt.Println("- Calculated hash", hex.EncodeToString(expectedHash[:]), len(expectedHash[:])) + fmt.Println("") + fmt.Println("- Match?", bytes.Equal(rebuildHash, expectedHash[:])) + fmt.Println("") + + rebuildHash = util.SplittedArboStrToBytes(inputList[0], inputList[1], true, false) + fmt.Println("With swap endianess and lazy") + fmt.Println("") + fmt.Println("- Provided raw", hex.EncodeToString(rawExpected), len(rawExpected)) + fmt.Println("") + fmt.Println("- Rebuild hash", hex.EncodeToString(rebuildHash), len(rebuildHash)) + fmt.Println("") + fmt.Println("- Calculated hash", hex.EncodeToString(expectedHash[:]), len(expectedHash[:])) + fmt.Println("") + fmt.Println("- Match?", bytes.Equal(rebuildHash, expectedHash[:])) + + rebuildHash = util.SplittedArboStrToBytes(inputList[0], inputList[1], false, true) + fmt.Println("") + fmt.Println("Without swap endianess and strict") + fmt.Println("") + fmt.Println("- Provided raw", hex.EncodeToString(rawExpected), len(rawExpected)) + fmt.Println("") + fmt.Println("- Rebuild hash", hex.EncodeToString(rebuildHash), len(rebuildHash)) + fmt.Println("") + fmt.Println("- Calculated hash", hex.EncodeToString(expectedHash[:]), len(expectedHash[:])) + fmt.Println("") + fmt.Println("- Match?", bytes.Equal(rebuildHash, expectedHash[:])) + fmt.Println("") + + rebuildHash = util.SplittedArboStrToBytes(inputList[0], inputList[1], true, true) + fmt.Println("With swap endianess and strict") + fmt.Println("") + fmt.Println("- Provided raw", hex.EncodeToString(rawExpected), len(rawExpected)) + fmt.Println("") + fmt.Println("- Rebuild hash", hex.EncodeToString(rebuildHash), len(rebuildHash)) + fmt.Println("") + fmt.Println("- Calculated hash", hex.EncodeToString(expectedHash[:]), len(expectedHash[:])) + fmt.Println("") + fmt.Println("- Match?", bytes.Equal(rebuildHash, expectedHash[:])) +} diff --git a/crypto/zk/prover/pubsignals.go b/crypto/zk/prover/pubsignals.go index f169e5730..14f07c7a4 100644 --- a/crypto/zk/prover/pubsignals.go +++ b/crypto/zk/prover/pubsignals.go @@ -46,16 +46,19 @@ func (p *Proof) ElectionID() ([]byte, error) { } // VoteHash returns the VoteHash included into the current proof. -func (p *Proof) VoteHash() ([]byte, error) { +func (p *Proof) VoteHash() ([]byte, []string, error) { voteHash1str, err := p.extractPubSignal("voteHash[0]") if err != nil { - return nil, err + return nil, nil, err } voteHash2str, err := p.extractPubSignal("voteHash[1]") if err != nil { - return nil, err + return nil, nil, err } - return util.SplittedArboStrToBytes(voteHash1str, voteHash2str, false, true), nil + return util.SplittedArboStrToBytes(voteHash1str, voteHash2str, false, true), []string{ + voteHash1str, + voteHash2str, + }, nil } // CensusRoot returns the CensusRoot included into the current proof. diff --git a/vochain/transaction/proofs/zkproof/zkproof.go b/vochain/transaction/proofs/zkproof/zkproof.go index 5eb6729a6..c70a3aa0c 100644 --- a/vochain/transaction/proofs/zkproof/zkproof.go +++ b/vochain/transaction/proofs/zkproof/zkproof.go @@ -36,9 +36,10 @@ func (*ProofVerifierZk) Verify(process *models.Process, envelope *models.VoteEnv } hashedPid := sha256.Sum256(process.ProcessId) if !bytes.Equal(hashedPid[:], proofProcessID) { - log.Debugw("process id mismatch", - "processID", hex.EncodeToString(process.ProcessId), - "proofProcessID", hex.EncodeToString(proofProcessID)) + log.Warnw("process id mismatch", + "processID", fmt.Sprintf("%x", process.ProcessId), + "hashedPID", fmt.Sprintf("%x", hashedPid), + "proofPID", fmt.Sprintf("%x", proofProcessID)) return false, nil, fmt.Errorf("process id mismatch %x != %x", process.ProcessId, proofProcessID) } // verify the census root @@ -50,14 +51,16 @@ func (*ProofVerifierZk) Verify(process *models.Process, envelope *models.VoteEnv return false, nil, fmt.Errorf("census root mismatch") } // verify the votePackage hash - proofVoteHash, err := proof.VoteHash() + proofVoteHash, strParts, err := proof.VoteHash() if err != nil { return false, nil, fmt.Errorf("failed on parsing vote hash from public inputs provided: %w", err) } hashedVotePackage := sha256.Sum256(envelope.VotePackage) if !bytes.Equal(hashedVotePackage[:], proofVoteHash) { - log.Debugw("process id mismatch", + log.Warnw("voteHash id mismatch", "votPackage", hex.EncodeToString(envelope.VotePackage), + "hashedVotePackage", hex.EncodeToString(hashedVotePackage[:]), + "proofParts", strParts, "proofVotePackage", hex.EncodeToString(proofVoteHash)) return false, nil, fmt.Errorf("vote hash mismatch") } From cf10ed5c1df50c46f7b1e77c3f86f50035074ce7 Mon Sep 17 00:00:00 2001 From: "Lucas\\ Menendez" Date: Thu, 6 Jun 2024 12:14:44 +0200 Subject: [PATCH 3/3] recover padding on elections ID, and fix padding position --- crypto/zk/prover/pubsignals.go | 2 +- util/zk.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto/zk/prover/pubsignals.go b/crypto/zk/prover/pubsignals.go index 14f07c7a4..fd581b308 100644 --- a/crypto/zk/prover/pubsignals.go +++ b/crypto/zk/prover/pubsignals.go @@ -42,7 +42,7 @@ func (p *Proof) ElectionID() ([]byte, error) { if err != nil { return nil, err } - return util.SplittedArboStrToBytes(electionID1str, electionID2str, false, false), nil + return util.SplittedArboStrToBytes(electionID1str, electionID2str, false, true), nil } // VoteHash returns the VoteHash included into the current proof. diff --git a/util/zk.go b/util/zk.go index 21f1164e8..c6e7187ee 100644 --- a/util/zk.go +++ b/util/zk.go @@ -54,10 +54,10 @@ func SplittedArboToBytes(input1, input2 *big.Int, swap, strict bool) []byte { } if strict { for len(b1) < 16 { - b1 = append(b1, 0) + b1 = append([]byte{0}, b1...) } for len(b2) < 16 { - b2 = append(b2, 0) + b2 = append([]byte{0}, b2...) } } return append(b1, b2...)