From 8eb68d3fe050cdba06546e29fc18547c1cee7ae9 Mon Sep 17 00:00:00 2001 From: jude Date: Fri, 21 Apr 2023 20:39:58 +0100 Subject: [PATCH] Add proof of fortification --- static/js/modules/crypto/random_primes.js | 5 +- static/js/modules/interface/proofs.js | 125 +++++++++++++++++++++- 2 files changed, 123 insertions(+), 7 deletions(-) diff --git a/static/js/modules/crypto/random_primes.js b/static/js/modules/crypto/random_primes.js index 04ec236..46fe7cf 100644 --- a/static/js/modules/crypto/random_primes.js +++ b/static/js/modules/crypto/random_primes.js @@ -1,6 +1,6 @@ import { mod_exp } from "./math.js"; -export const KEY_SIZE = 2048; +export const KEY_SIZE = 512; export function cryptoRandom(bits) { if (bits === undefined) { @@ -100,8 +100,7 @@ export function generate_prime() { export function generate_safe_prime() { while (true) { let n = generate_prime(); - // This does not generate safe primes! But it takes forever to find safe primes of size 1024, so this will do. - if (small_prime_test((n - 1n) / 2n) /* && miller_rabin((n - 1n) / 2n, 40) */) { + if (small_prime_test((n - 1n) / 2n) && miller_rabin((n - 1n) / 2n, 40)) { return n; } } diff --git a/static/js/modules/interface/proofs.js b/static/js/modules/interface/proofs.js index cc79428..21eeb38 100644 --- a/static/js/modules/interface/proofs.js +++ b/static/js/modules/interface/proofs.js @@ -1,4 +1,5 @@ import { cryptoRandom } from "../crypto/random_primes.js"; +import { Region } from "./map.js"; function cryptoRange(upper) { // This is ridiculous: why implement a BigInt primitive, have it behave like a number, and then _not_ offer @@ -294,8 +295,124 @@ export function verifyRange(obj, key) { window.verifyRange = verifyRange; /** - * - We prove that the set contains |S| - 2 zeros, with the final pair summing to zero - * - We also attach some form of adjacency guarantee: that is, we prove the sums on all adjacent pairs are zero - * - We also attach a range proof for the new region values + * - We prove that the set contains |S| - 2 zeros, with the final pair summing to zero + * - We also attach some form of adjacency guarantee: that is, we prove the sums on all adjacent pairs are zero + * - We also attach a range proof for the new region values */ -export function proveFortify() {} +export function proveFortify(fortify) { + let proofs = []; + let privateInputs = []; + + let regionNames = Object.keys(fortify).sort(); + for (let x = 0; x < ROUNDS; x++) { + let psi = cryptoShuffle(structuredClone(regionNames)).join(""); + let psiMap = {}; + for (let i = 0; i < regionNames.length; i++) { + psiMap[regionNames[i]] = psi[i]; + } + + let newRegions = structuredClone(fortify); + + // Rearrange keys + for (let r of regionNames) { + newRegions[psiMap[r]] = fortify[r].pubKey.encrypt(fortify[r].plainText); + } + + let edges = []; + let proofEdges = []; + + // Attach edges + for (let i = 0; i < regionNames.length; i++) { + let region = regionNames[i]; + let psiRegion = psi[i]; + + for (let n of Region.getRegion(region).neighbours) { + if (regionNames.includes(n.name)) { + let psiNeighbour = psiMap[n.name]; + + if (psiNeighbour > psiRegion) { + let salt = cryptoRandom(128); + let hasher = new jsSHA("SHA3-256", "TEXT"); + hasher.update(psiRegion); + hasher.update(psiNeighbour); + hasher.update(salt.toString(16)); + let hash = hasher.getHash("HEX"); + + edges.push({ + hash: hash, + salt: salt, + edge: [psiRegion, psiNeighbour], + }); + proofEdges.push(hash); + } + } + } + } + + newRegions.edges = cryptoShuffle(proofEdges); + + proofs.push(newRegions); + privateInputs.push({ + psi: psi, + edges: edges, + }); + } + + let coins = getCoins(JSON.stringify(proofs)); + let verifications = []; + + for (let i = 0; i < ROUNDS; i++) { + let coin = coins[i]; + let proof = proofs[i]; + let input = privateInputs[i]; + + if (coin === 1) { + // Show |S| - 2 zeroes + let verification = { + regions: {}, + }; + let pairCipherText = null; + let pair = []; + + for (let r of regionNames) { + if (proof[r].plainText === 0n) { + verification.regions[r] = proof[r].proveNI(); + } else if (pairCipherText === null) { + pairCipherText = proof[r].clone(); + pair.push(r); + } else { + pairCipherText.update(proof[r]); + verification.pairCipherText = pairCipherText.proveNI(); + pair.push(r); + } + } + + // Show pair is joined by edge + let pairName = pair.sort(); + console.log(input); + verification.pairEdgeSalt = input.edges.find( + (e) => e.edge[0] === pairName[0] && e.edge[1] === pairName[1] + ); + + verifications.push(verification); + } else { + // Show isomorphism + verifications.push({ + psi: input.psi, + salts: input.edges.map((e) => e.salt), + }); + } + } + + return { + fortify: fortify, + proofs: proofs, + verifications: verifications, + }; +} + +window.proveFortify = proveFortify; + +function verifyFortify(obj, key) {} + +// proveRegions({A:paillier.pubKey.encrypt(0n),B:paillier.pubKey.encrypt(3n),C:paillier.pubKey.encrypt(-3n),D:paillier.pubKey.encrypt(0n),E:paillier.pubKey.encrypt(0n)})