2022-12-06 22:46:02 +00:00
|
|
|
import sha256 from 'crypto-js/sha256.js';
|
|
|
|
import { initialize } from 'zokrates-js';
|
|
|
|
|
|
|
|
const ZEROSTR = '0';
|
|
|
|
|
|
|
|
/* Converts a string into a stringified hexadecimal number */
|
|
|
|
function str2hex(string) {
|
|
|
|
return string.split('')
|
|
|
|
.map(c => c.charCodeAt(0).toString(16).padStart(2, '0'))
|
|
|
|
.join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Converts a stringified hexadecimal number into a string */
|
|
|
|
function hex2str(hex) {
|
|
|
|
return hex.split(/(\w\w)/g)
|
|
|
|
.filter(p => !!p)
|
|
|
|
.map(c => String.fromCharCode(parseInt(c, 16)))
|
|
|
|
.join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prefix each element of a string a array with 0x */
|
|
|
|
function map_0xprefix(arr) {
|
|
|
|
return arr.map(s => '0x' + s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert a string to a byte array */
|
|
|
|
function str2asciiarr(s) {
|
|
|
|
let charCodeArr = [];
|
|
|
|
for (let i = 0; i < s.length; i++) {
|
|
|
|
let code = s.charCodeAt(i);
|
|
|
|
charCodeArr.push(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
return charCodeArr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert a byte array to a string */
|
|
|
|
function asciiarr2str(arr) {
|
|
|
|
return String.fromCharCode(...arr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Expand a simple number into a stringified u32[8] array for ZoKrates.
|
|
|
|
*/
|
|
|
|
function expand_number(number) {
|
|
|
|
const revstr = s => Array.from(s).reverse().join('');
|
|
|
|
const split8 = s => s.match(/.{1,8}/g);
|
|
|
|
const parts = split8(revstr(number.toString(16)))
|
|
|
|
.map(p => '0x' + revstr(p))
|
|
|
|
.map(p => parseInt(p, 16).toString())
|
|
|
|
.reverse();
|
|
|
|
|
|
|
|
return [...Array(8 - parts.length).fill(ZEROSTR), ...parts];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Hard coded zokrates program source code */
|
|
|
|
const zokSrc = `
|
|
|
|
import "hashes/sha256/sha256Padded.zok" as sha256;
|
|
|
|
from "utils/casts.zok" import cast;
|
|
|
|
|
|
|
|
def main(public u32[8] hash,public u32[5] address,private u8[64] flag){
|
|
|
|
u8[20] addr8 = cast(address);
|
|
|
|
u32[8] genHash = sha256(flag);
|
|
|
|
log("Hash: {} {} {} {} {} {} {} {}",genHash[0],genHash[1],genHash[2],genHash[3],genHash[4],genHash[5],genHash[6],genHash[7]);
|
|
|
|
assert(genHash == hash);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
|
|
/* Get the proving key from the local server */
|
2022-12-07 02:36:09 +00:00
|
|
|
const PROVING_KEY_URI = '/proving.key';
|
2022-12-06 22:46:02 +00:00
|
|
|
const proving_key = await (await fetch(PROVING_KEY_URI)).text();
|
|
|
|
|
|
|
|
function submitFlag(flag) {
|
|
|
|
initialize().then((defaultProvider) => {
|
|
|
|
const zokProvider = defaultProvider.withOptions({
|
|
|
|
backend: 'ark',
|
|
|
|
scheme: 'gm17',
|
|
|
|
});
|
|
|
|
|
|
|
|
const artefacts = zokProvider.compile(zokSrc);
|
|
|
|
|
|
|
|
const flag_ascii = str2asciiarr(flag);
|
|
|
|
const flag_ascii_padded = flag_ascii.concat(new Array(64 - flag_ascii.length).fill(0));
|
|
|
|
const flag_padded = asciiarr2str(flag_ascii_padded);
|
|
|
|
|
|
|
|
const hash = sha256(flag_padded).toString(); /* TODO get this from contract */
|
|
|
|
const addr = 'f6e3a49fca2eb57f286d516fa60154ebfd10d5ad'; /* TODO get this from metamask */
|
|
|
|
|
|
|
|
const flag_split = map_0xprefix(str2hex(flag).match(/.{1,2}/g));
|
|
|
|
const flag_split_padded = flag_split.concat(new Array(64 - flag_split.length).fill('0x0'));
|
|
|
|
const hash_split = map_0xprefix(hash.match(/.{1,8}/g));
|
|
|
|
const addr_split = map_0xprefix(addr.match(/.{1,8}/g));
|
|
|
|
|
|
|
|
// witness computation
|
|
|
|
const { witness, output } = zokProvider.computeWitness(artefacts, [hash_split, addr_split, flag_split_padded]);
|
|
|
|
|
|
|
|
// generate proof
|
|
|
|
const proof = zokProvider.generateProof(artefacts.program, witness, proving_key);
|
|
|
|
|
|
|
|
console.log(proof);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
document.getElementById('submitFlagBtn').addEventListener('click', () => {
|
|
|
|
submitFlag(document.getElementById('flagbox').value);
|
|
|
|
});
|