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 1aa769397..fd581b308 100644 --- a/crypto/zk/prover/pubsignals.go +++ b/crypto/zk/prover/pubsignals.go @@ -42,20 +42,23 @@ func (p *Proof) ElectionID() ([]byte, error) { if err != nil { return nil, err } - return util.SplittedArboStrToBytes(electionID1str, electionID2str), nil + return util.SplittedArboStrToBytes(electionID1str, electionID2str, false, true), nil } // 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), nil + return util.SplittedArboStrToBytes(voteHash1str, voteHash2str, false, true), []string{ + voteHash1str, + voteHash2str, + }, nil } // CensusRoot returns the CensusRoot included into the current proof. diff --git a/util/zk.go b/util/zk.go index e797fdd4b..c6e7187ee 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([]byte{0}, b1...) + } + for len(b2) < 16 { + b2 = append([]byte{0}, b2...) + } } 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..c70a3aa0c 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,10 @@ func (*ProofVerifierZk) Verify(process *models.Process, envelope *models.VoteEnv } hashedPid := sha256.Sum256(process.ProcessId) if !bytes.Equal(hashedPid[:], 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 @@ -45,12 +51,17 @@ 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.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") } // get vote weight from proof publicSignals