iden3 / snarkjs

zkSNARK implementation in JavaScript & WASM
GNU General Public License v3.0
1.7k stars 412 forks source link

Troubleshooting Discrepancies: Validating Pre-Image Hashes in SnarkJS #474

Open vvc-git opened 3 months ago

vvc-git commented 3 months ago

While practicing my first snarkjs exercises, I aimed to verify if the proof I possess regarding the pre-image hash of a person's birth date aligns with the hash of this specific date. My approach involved comparing the contents of the 'public.json' file with the hash I computed in Python. However, the values do not match. Could I be making a mistake in my approach? Is it accurate to assume that the computed hash should also be present in the 'public.json' file?

circom circuit

pragma circom 2.0.0;
include "../../circomlib/circuits/sha256/sha256.circom";

// Prove tha that we know a birthday of sha256(birthday) 
template Birthday(){
  component SHA = Sha256(6);
  signal input date[6];
  SHA.in <== date;

  signal output date_out[256];
  date_out <== SHA.out;
}

component main = Birthday();

Python code

import hashlib
import json

def calculate_hash(filename):
    # Read the entire JSON file
    with open(filename, 'r') as file:
        json_data = file.read()

    # Create a SHA-256 hash object
    hash_object = hashlib.sha256()

    # Update the hash object with the entire JSON (string needs to be encoded to bytes)
    hash_object.update(json_data.encode())

    # Get the hash in hexadecimal
    hash_hex = hash_object.hexdigest()

    # Convert the hexadecimal hash to bits
    hash_bits = ''.join(format(int(c, 16), '04b') for c in hash_hex)

    return hash_bits

def concatenate_public_json(filename):
    # Read the JSON file
    with open(filename, 'r') as file:
        bits = json.load(file)

    # Concatenate the bits into a single string
    concatenated_bits = ''.join(bits)

    return concatenated_bits

# JSON file name to read data from
filename = 'input.json'
public = 'public.json'
hash1 = calculate_hash(filename)
hash2 = concatenate_public_json(public)

# Compare the two bit sequences
if hash1 == hash2:
    print("The bit sequences are equal.")
else:
    print("The bit sequences are different.")
    print("Proof Hash: ", hash1)
    print("Calculated Hash: ", hash2)

input.json

{ "date": ["1", "3", "0", "3", "0", "1"] }

public.json

[
 "1",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "1",
 "1",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "0",
 "0",
 "1",
 "1",
 "0",
 "1",
 "1",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "1",
 "1",
 "0",
 "0",
 "1",
 "0",
 "0",
 "0",
 "1",
 "1",
 "0",
 "1",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "0",
 "0",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "0",
 "0",
 "1",
 "1",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "0",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "1",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "0",
 "0",
 "1",
 "1",
 "0",
 "1",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "0",
 "1",
 "1",
 "0",
 "0",
 "0",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "1",
 "1",
 "1",
 "0",
 "1",
 "0",
 "1",
 "1",
 "0",
 "1",
 "1",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "1",
 "1",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "0",
 "1",
 "1",
 "1",
 "0",
 "0",
 "0",
 "1",
 "0",
 "1",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "1",
 "0",
 "0",
 "0",
 "0",
 "1"
]
zkbitcoin commented 3 weeks ago

@vvc-git had exact problem solved it by recognizing sha256.circom works on bit array

convert date to binary array, in typescript following will do

function buffer2bitArray(b: string | any[]) { const res = []; for (let i=0; i<b.length; i++) { for (let j=0; j<8; j++) { res.push((b[i] >> (7-j) &1)); } } return res; } put date in and get bit array out

put array bit in input.json for witness

{ "in":[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] }

simplify circuit a bit

pragma circom 2.0.0; include "../../node_modules/circomlib/circuits/sha256/sha256.circom";

component main = Sha256(48);

recompile circuit, rebuild proof

this is also useful is where I got idea from (test suite for circuit)

https://github.com/iden3/circomlib/blob/master/test/sha256.js