/** * CSPRNG Fisher-Yates shuffle. * * Only works on lists up to 255 elements. */ function cryptoShuffle(l) { let out = []; for (let i = l.length - 1; i > 0; i--) { let value = new Uint8Array([0]); crypto.getRandomValues(value); while (value[0] > i) { crypto.getRandomValues(value); } let v = l.splice(value[0], 1); out.push(v[0]); } out.push(l[0]); return out; } window.cryptoShuffle = cryptoShuffle; const ROUNDS = 24; function proveRegions(regions) { // Construct prover coins let coins = []; let regionNames = Object.keys(regions); for (let x = 0; x < ROUNDS; x++) { let psi = cryptoShuffle(structuredClone(regionNames)).join(""); let newRegions = structuredClone(regions); // rearrange keys for (let index = 0; index < regionNames.length; index++) { let c = regions[psi[index]].clone(); // re-blind c.update(c.pubKey.encrypt(0n)); newRegions[regionNames[index]] = c; } coins.push(newRegions); } // Construct verifier coins let hasher = new jsSHA("SHA3-256", "TEXT"); hasher.update(JSON.stringify(coins)); let hash = hasher.getHash("UINT8ARRAY"); let verifierCoins = []; for (let i = 0; i < ROUNDS / 8; i++) { let v = hash[i]; for (let j = 0; j < 8; j++) { verifierCoins.push(v & 1); v >>= 1; } } // Construct prover proofs for (let coin of verifierCoins) { if (coin === 1) { // Reveal bijection and proof for zero } else { // Reveal proof for plaintext } } } window.proveRegions = proveRegions;