mirror of
https://github.com/vacp2p/research.git
synced 2025-02-23 11:48:22 +00:00
more semaphore wip
This commit is contained in:
parent
7b3607b6df
commit
f96edfab71
@ -1,8 +1,30 @@
|
|||||||
|
const crypto = require('crypto');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
const zkSnark = require('snarkjs');
|
const zkSnark = require('snarkjs');
|
||||||
|
const circomlib = require('circomlib');
|
||||||
|
|
||||||
|
const web3Utils = require('web3-utils');
|
||||||
|
|
||||||
|
const ethers = require('ethers');
|
||||||
|
|
||||||
|
const asciiToHex = web3Utils.asciiToHex;
|
||||||
|
|
||||||
|
const bigInt = zkSnark.bigInt;
|
||||||
|
|
||||||
|
const eddsa = circomlib.eddsa;
|
||||||
|
const mimcsponge = circomlib.mimcsponge;
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
|
||||||
|
beBuff2int = function(buff) {
|
||||||
|
let res = bigInt.zero;
|
||||||
|
for (let i=0; i<buff.length; i++) {
|
||||||
|
const n = bigInt(buff[buff.length - i - 1]);
|
||||||
|
res = res.add(n.shl(i*8));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
// Dealing with JSON BigInt serialization/deserialization
|
// Dealing with JSON BigInt serialization/deserialization
|
||||||
function stringifyReplacer(key, value) {
|
function stringifyReplacer(key, value) {
|
||||||
if (typeof value === 'bigint') {
|
if (typeof value === 'bigint') {
|
||||||
@ -27,6 +49,29 @@ function deserialize(json_str) {
|
|||||||
return JSON.parse(json_str, parseReviver);
|
return JSON.parse(json_str, parseReviver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generate_identity() {
|
||||||
|
const private_key = crypto.randomBytes(32).toString('hex');
|
||||||
|
const prvKey = Buffer.from(private_key, 'hex');
|
||||||
|
const pubKey = eddsa.prv2pub(prvKey);
|
||||||
|
|
||||||
|
// XXX: Right, so just some random bytes?
|
||||||
|
const identity_nullifier = '0x' + crypto.randomBytes(31).toString('hex');
|
||||||
|
const identity_trapdoor = '0x' + crypto.randomBytes(31).toString('hex');
|
||||||
|
console.log(`generate identity from (private_key, public_key[0], public_key[1], identity_nullifier): (${private_key}, ${pubKey[0]}, ${pubKey[1]}, ${identity_nullifier}, ${identity_trapdoor})`);
|
||||||
|
|
||||||
|
const identity_commitment = pedersenHash([bigInt(circomlib.babyJub.mulPointEscalar(pubKey, 8)[0]), bigInt(identity_nullifier), bigInt(identity_trapdoor)]);
|
||||||
|
|
||||||
|
console.log(`identity_commitment : ${identity_commitment}`);
|
||||||
|
const generated_identity = {
|
||||||
|
private_key,
|
||||||
|
identity_nullifier: identity_nullifier.toString(),
|
||||||
|
identity_trapdoor: identity_trapdoor.toString(),
|
||||||
|
identity_commitment: identity_commitment.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return generated_identity;
|
||||||
|
}
|
||||||
|
|
||||||
// Using Groth
|
// Using Groth
|
||||||
|
|
||||||
// 1. Compile circuit with circom:
|
// 1. Compile circuit with circom:
|
||||||
@ -47,25 +92,112 @@ function performSetup(circuit) {
|
|||||||
// TODO: Conditionally run if file exists
|
// TODO: Conditionally run if file exists
|
||||||
// performSetup(circuit);
|
// performSetup(circuit);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// XXX: Here at the moment, the inputs are wrong (obviously)
|
// XXX: Here at the moment, the inputs are wrong (obviously)
|
||||||
|
|
||||||
|
// XXX: Optionally persist this
|
||||||
|
let loaded_identity = generate_identity();
|
||||||
|
console.log("loaded_identity", loaded_identity);
|
||||||
|
|
||||||
// Calculate witness? I know roughly: client/semaphore.js, construct all inputs and to the checkWitness etc. Has logic for proofs and so on.
|
// Calculate witness? I know roughly: client/semaphore.js, construct all inputs and to the checkWitness etc. Has logic for proofs and so on.
|
||||||
|
|
||||||
// 4. Generate proof
|
//const prvKey = Buffer.from('0001020304050607080900010203040506070809000102030405060708090001', 'hex');
|
||||||
const input = {
|
|
||||||
"a": "3",
|
|
||||||
"b": "11"
|
|
||||||
}
|
|
||||||
const witness = circuit.calculateWitness(input);
|
|
||||||
const vk_proof = deserialize(fs.readFileSync("build/proving_key.json", "utf8"));
|
|
||||||
|
|
||||||
const {proof, publicSignals} = zkSnark.groth.genProof(vk_proof, witness);
|
let private_key = loaded_identity.private_key;
|
||||||
|
const prvKey = Buffer.from(private_key, 'hex');
|
||||||
|
|
||||||
// 5. Verify proof
|
// external nullifier, signal_hash
|
||||||
const vk_verifier = deserialize(fs.readFileSync("build/verification_key.json", "utf8"));
|
// what are the exactly? external nullifier must match the one in contract, ok. lets just set it to some arbitrary number for now.
|
||||||
|
|
||||||
if (zkSnark.groth.isValid(vk_verifier, proof, publicSignals)) {
|
let signal_str = "hello world";
|
||||||
console.log("The proof is valid");
|
let external_nullifier = bigInt(12312);
|
||||||
} else {
|
|
||||||
console.log("The proof is not valid");
|
console.log("signal_str", signal_str);
|
||||||
}
|
// Some signal conversion voodo, seems complex
|
||||||
|
// XXX: It'd be good to minimize this to whats actually minimally needed
|
||||||
|
const signal_to_contract = asciiToHex(signal_str);
|
||||||
|
const signal_to_contract_bytes = new Buffer(signal_to_contract.slice(2), 'hex');
|
||||||
|
|
||||||
|
const signal_hash_raw = ethers.utils.solidityKeccak256(
|
||||||
|
['bytes'],
|
||||||
|
[signal_to_contract_bytes],
|
||||||
|
);
|
||||||
|
// XXX: Buffer deprecated
|
||||||
|
const signal_hash_raw_bytes = new Buffer(signal_hash_raw.slice(2), 'hex');
|
||||||
|
const signal_hash = beBuff2int(signal_hash_raw_bytes.slice(0, 31));
|
||||||
|
console.log("signal_hash", signal_hash);
|
||||||
|
|
||||||
|
// what does this mean exactly?
|
||||||
|
// We are signing the external nullifer and signal hash
|
||||||
|
// https://github.com/iden3/circomlib/pull/13
|
||||||
|
// https://eprint.iacr.org/2016/492.pdf
|
||||||
|
// https://en.wikipedia.org/wiki/Sponge_function
|
||||||
|
// Why multihash?
|
||||||
|
const msg = mimcsponge.multiHash([external_nullifier, signal_hash]);
|
||||||
|
console.log("msg", msg);
|
||||||
|
// we are signing with MIM
|
||||||
|
// Whats interaction between EDDSA and MiMC?
|
||||||
|
const signature = eddsa.signMiMCSponge(prvKey, msg);
|
||||||
|
console.log("signature", signature);
|
||||||
|
|
||||||
|
const pubKey = eddsa.prv2pub(prvKey);
|
||||||
|
|
||||||
|
// XXX: What are these exactly?
|
||||||
|
let identity_nullifier = loaded_identity.identity_nullifier;
|
||||||
|
let identity_trapdoor = loaded_identity.identity_trapdoor;
|
||||||
|
|
||||||
|
// identity_path we await from server, glurgh.
|
||||||
|
// XXX: Not an easy place to leave, but that's where I am at
|
||||||
|
// server.js: path_for_element/:el
|
||||||
|
// semaphore.tree.element_index(leaf)
|
||||||
|
// identity tree index, MerkleTree
|
||||||
|
// HERE AM
|
||||||
|
const identity_path_elements = identity_path.path_elements;
|
||||||
|
const identity_path_index = identity_path.path_index;
|
||||||
|
|
||||||
|
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
|
||||||
|
// => true
|
||||||
|
|
||||||
|
// What are the different types of signature fields?
|
||||||
|
|
||||||
|
// loaded_identity.identity_nullifier?
|
||||||
|
|
||||||
|
const inputs = {
|
||||||
|
'identity_pk[0]': pubKey[0],
|
||||||
|
'identity_pk[1]': pubKey[1],
|
||||||
|
'auth_sig_r[0]': signature.R8[0],
|
||||||
|
'auth_sig_r[1]': signature.R8[1],
|
||||||
|
auth_sig_s: signature.S,
|
||||||
|
signal_hash,
|
||||||
|
external_nullifier,
|
||||||
|
identity_nullifier,
|
||||||
|
identity_trapdoor,
|
||||||
|
identity_path_elements,
|
||||||
|
identity_path_index,
|
||||||
|
fake_zero: bigInt(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// const w = circuit.calculateWitness(inputs);
|
||||||
|
// assert(circuit.checkWitness(w));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//// 4. Generate proof
|
||||||
|
// const input = {
|
||||||
|
// "a": "3",
|
||||||
|
// "b": "11"
|
||||||
|
// }
|
||||||
|
// const witness = circuit.calculateWitness(input);
|
||||||
|
// const vk_proof = deserialize(fs.readFileSync("build/proving_key.json", "utf8"));
|
||||||
|
|
||||||
|
// const {proof, publicSignals} = zkSnark.groth.genProof(vk_proof, witness);
|
||||||
|
|
||||||
|
// // 5. Verify proof
|
||||||
|
// const vk_verifier = deserialize(fs.readFileSync("build/verification_key.json", "utf8"));
|
||||||
|
|
||||||
|
// if (zkSnark.groth.isValid(vk_verifier, proof, publicSignals)) {
|
||||||
|
// console.log("The proof is valid");
|
||||||
|
// } else {
|
||||||
|
// console.log("The proof is not valid");
|
||||||
|
// }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user