diff --git a/static/js/modules/crypto/random_primes.js b/static/js/modules/crypto/random_primes.js index 7a205b4..f0e799a 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 = 512; +export const KEY_SIZE = 2048; export function cryptoRandom(bits) { if (bits === undefined) { diff --git a/static/js/modules/interface/player.js b/static/js/modules/interface/player.js index 46fe980..8d210ff 100644 --- a/static/js/modules/interface/player.js +++ b/static/js/modules/interface/player.js @@ -8,6 +8,7 @@ import { proveFortify, proveRange, proveRegions, + verifyBitLength, verifyFortify, verifyRegions, } from "./proofs.js"; @@ -208,12 +209,24 @@ export class Player { for (let regionName of Object.keys(data.fortify.fortify)) { let region = Region.getRegion(regionName); - region.reinforce( - new ReadOnlyCiphertext( - this.paillierPubKey, - BigInt(data.fortify.fortify[regionName]) - ) + let c1 = region.strength.cipherText.clone(); + let c2 = new ReadOnlyCiphertext( + this.paillierPubKey, + BigInt(data.fortify.fortify[regionName]) ); + + c1.update(c2); + + let v = verifyBitLength({ + ...data.fortify.rangeProofs[regionName], + cipherText: c1, + }); + + if (v !== null && v <= 8) { + region.reinforce(c2); + } else { + return false; + } } // request proofs diff --git a/static/js/modules/interface/proofs.js b/static/js/modules/interface/proofs.js index 3f0809b..c21eceb 100644 --- a/static/js/modules/interface/proofs.js +++ b/static/js/modules/interface/proofs.js @@ -45,6 +45,11 @@ function cryptoShuffle(l) { const ROUNDS = 24; +/** + * R-S transform. + * + * Uses the hash of the proof content to produce verifier coins + */ function getCoins(text) { // Construct verifier coins let hasher = new jsSHA("SHA3-256", "TEXT"); @@ -186,6 +191,9 @@ window.verifyRegions = verifyRegions; // verifyRegions(proveRegions({A:paillier.pubKey.encrypt(0n),B:paillier.pubKey.encrypt(1n),C:paillier.pubKey.encrypt(0n),D:paillier.pubKey.encrypt(0n),E:paillier.pubKey.encrypt(0n)}), paillier.pubKey) +/** + * BCDG Range proof + */ export function proveRange(cipherText, rangeUpper) { if (cipherText.readOnly) { throw "Cannot prove range of ReadOnlyCiphertext"; @@ -322,6 +330,18 @@ export function proveBitLength(cipherText) { m >>= 1n; } + // Pad out + while (bitCommitments.length < 8) { + let c = key.encrypt(0n); + bitCommitments.push(c); + + let c2 = c.clone(); + c2.mul(e); + prod.update(c2); + + e <<= 1n; + } + let bitProofs = []; for (let bitCommitment of bitCommitments) { @@ -394,7 +414,13 @@ function proveOneOfTwo(cipherText) { cProofs: proof.cs.map((p) => p.proveNI()), }); } else { - let c1Index = proof.cs.findIndex((c) => c.plainText === 1n); + let c1Index; + if (cipherText.plainText === paillier.pubKey.n2 - 1n) { + c1Index = proof.cs.findIndex((c) => c.plainText === 1n); + } else { + c1Index = proof.cs.findIndex((c) => c.plainText === 0n); + } + let c1 = proof.cs[c1Index].clone(); c1.update(cipherText); @@ -699,8 +725,6 @@ export function verifyFortify(obj, key) { } } - // TODO verify range proofs - return true; } diff --git a/templates/index.html b/templates/index.html index b28a7ac..e9067c2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -325,43 +325,43 @@ console.log(`Bench done. Time per verification: ${performance.measure("pv-duration", "pv-start", "pv-end").duration / ROUNDS}`) } - function RangeProofBench() { + function BitLengthProofBench() { console.log("Warming up") const ct = paillier.pubKey.encrypt(5n) const ROUNDS = 20; for (let i = 0; i < 5; i++) { - proveRange(ct, 10n) + proveBitLength(ct) } console.log("Benching") performance.mark("rp-start") for (let i = 0; i < ROUNDS; i++) { - proveRange(ct, 10n) + proveBitLength(ct) } performance.mark("rp-end") console.log(`Bench done. Time per proof: ${performance.measure("rp-duration", "rp-start", "rp-end").duration / ROUNDS}`) } - function RangeVerifierBench() { + function BitLengthVerifierBench() { console.log("Warming up") const ROUNDS = 20; const ct = paillier.pubKey.encrypt(5n) - let proof = proveRange(ct, 10n) + let proof = proveBitLength(ct) for (let i = 0; i < 5; i++) { - verifyRange(proof, paillier.pubKey) + verifyBitLength(proof, paillier.pubKey) } console.log("Benching") performance.mark("rv-start") for (let i = 0; i < ROUNDS; i++) { - verifyRange(proof, paillier.pubKey) + verifyBitLength(proof, paillier.pubKey) } performance.mark("rv-end") @@ -400,7 +400,7 @@ }; } - function RangeSize() { + function BitLengthSize() { const ct = paillier.pubKey.encrypt(5n) let ROUNDS = 10; @@ -408,7 +408,7 @@ let compressedSize = 0; for (let x = 0; x < ROUNDS; x++) { - let s = JSON.stringify(proveRange(ct, 10n)); + let s = JSON.stringify(proveBitLength(ct)); size += string_to_buffer(s).byteLength; compressedSize += LZString.compressToUint8Array(s).length; } diff --git a/whitepaper/Dissertation.pdf b/whitepaper/Dissertation.pdf index 6b9d516..a1e033e 100644 Binary files a/whitepaper/Dissertation.pdf and b/whitepaper/Dissertation.pdf differ diff --git a/whitepaper/Dissertation.tex b/whitepaper/Dissertation.tex index f969d82..b2285aa 100644 --- a/whitepaper/Dissertation.tex +++ b/whitepaper/Dissertation.tex @@ -1030,6 +1030,8 @@ The other proofs do not translate so trivially to this structure however. In fac \textbf{Optimising language.} An optimising language may be able to reduce the time taken to encrypt. On the browser, this could involve using WASM as a way to execute compiled code within the browser, although WASM does not always outperform JavaScript \cite{wasm}. +Another approach is to use a web extension to communicate with a system daemon providing the relevant functionality. This is language-agnostic (except that the extension itself must be JavaScript), and the daemon could take advantage of other system features such as multiple cores. The multi-round proofs in particular are embarrassingly parallel, as each round is independent of the other rounds. + \subsection{Complexity results} All measurements were taken on Brave 1.50.114 (Chromium 112.0.5615.49) 64-bit, using a Ryzen 5 3600 CPU: a consumer CPU from 2019. Absolute timings are extremely dependent on the browser engine: for example Firefox 111.0.1 was typically 4 times slower than the results shown. @@ -1042,9 +1044,9 @@ All measurements were taken on Brave 1.50.114 (Chromium 112.0.5615.49) 64-bit, u \label{table1} \begin{tabularx}{\hsize}{c *4{>{\Centering}X}} \toprule - Modulus size & Na\"ive encrypt & Jacobi encrypt & Jacobi encrypt with pre-computation & RSA encrypt \\ + Modulus size & Paillier encrypt & Jurik encrypt & Jurik encrypt with pre-computation & RSA encrypt \\ \midrule - $|n| = 1024$ & 6.0ms & 4ms & 1.4ms & 0.015ms \\ + $|n| = 1024$ & 6.0ms & 4.0ms & 1.4ms & 0.015ms \\ $|n| = 2048$ & 34ms & 22ms & 7.6ms & 0.040ms \\ $|n| = 4096$ & 189ms & 128ms & -- & 0.093ms \\ \bottomrule @@ -1053,20 +1055,21 @@ All measurements were taken on Brave 1.50.114 (Chromium 112.0.5615.49) 64-bit, u \begin{table} \fontsize{10pt}{10pt}\selectfont - \caption{Time\parnote{$|n| = 4096$ uses a less-optimised encryption method, as the browser frequently timed out attempting to pre-compute for the more-optimised version.} to process proofs} - \begin{tabularx}{\hsize}{c *6{>{\Centering}X}} + \caption{Time\parnote{$|n| = 4096$ uses a less-optimised encryption method, as the browser frequently timed out attempting to pre-compute for the more-optimised version.} to process non-interactive proofs} + \begin{tabularx}{\hsize}{c *8{>{\Centering}X}} \toprule \multirow{2}{*}{Modulus size} & - \multicolumn{2}{c}{Proof-of-zero non-interactive} & + \multicolumn{2}{c}{Proof-of-zero} & \multicolumn{2}{c}{\hyperref[protocol1]{Protocol~\ref*{protocol1}} with $t = 24$} & - \multicolumn{2}{c}{BCDG Range with $t = 24$} + \multicolumn{2}{c}{BCDG Range with $t = 24$} & + \multicolumn{2}{c}{\hyperref[protocol1]{Protocol~\ref*{protocol4}} with $t = 24$} \tabularnewline - \cmidrule(l){2-3}\cmidrule(l){4-5}\cmidrule(l){6-7} - & Prover & Verifier & Prover & Verifier & Prover & Verifier \\ + \cmidrule(l){2-3}\cmidrule(l){4-5}\cmidrule(l){6-7}\cmidrule(l){8-9} + & Prover & Verifier & Prover & Verifier & Prover & Verifier & Prover & Verifier \\ \midrule - $|n| = 1024$ & 10ms & 18ms & 1,420ms & 2,140ms & 443ms & 655ms \\ - $|n| = 2048$ & 44ms & 68ms & 6,390ms & 8,140ms & 1,980ms & 2,400ms \\ - $|n| = 4096$ & 225ms & 292ms & 41,500ms & 34,400ms & 14,300ms & 11,400ms \\ + $|n| = 1024$ & 10ms & 18ms & 1,420ms & 2,140ms & 443ms & 655ms & 3,530ms & 5,310ms \\ + $|n| = 2048$ & 44ms & 68ms & 6,390ms & 8,140ms & 1,980ms & 2,400ms & 15,800ms & 19,000ms \\ + $|n| = 4096$ & 225ms & 292ms & 41,500ms & 34,400ms & 14,300ms & 11,400ms & & \\ \bottomrule \end{tabularx} \parnotes @@ -1074,18 +1077,18 @@ All measurements were taken on Brave 1.50.114 (Chromium 112.0.5615.49) 64-bit, u \begin{table} \fontsize{10pt}{10pt}\selectfont - \caption{Byte size\parnote{1 UTF-16 character, as used by ECMAScript \cite[Section~6.1.4]{ecma2024262}, is 2 or more bytes.} of encoded proofs} + \caption{Byte size\parnote{1 UTF-16 character, as used by ECMAScript \cite[Section~6.1.4]{ecma2024262}, is 2 or more bytes.} of encoded non-interactive proofs} \label{table3} - \begin{tabularx}{\hsize}{c *6{>{\Centering}X}} + \begin{tabularx}{\hsize}{c *8{>{\Centering}X}} \toprule - \multirow{2}{*}{Modulus size} & \multicolumn{2}{c}{Proof-of-zero non-interactive} & \multicolumn{2}{c}{\hyperref[protocol1]{Protocol~\ref*{protocol1}} with $t = 24$} & \multicolumn{2}{c}{BCDG Range with $t = 24$} + \multirow{2}{*}{Modulus size} & \multicolumn{2}{c}{Proof-of-zero non-interactive} & \multicolumn{2}{c}{\hyperref[protocol1]{Protocol~\ref*{protocol1}} with $t = 24$} & \multicolumn{2}{c}{BCDG Range with $t = 24$} & \multicolumn{2}{c}{\hyperref[protocol1]{Protocol~\ref*{protocol4}} with $t = 24$} \tabularnewline - \cmidrule(l){2-3}\cmidrule(l){4-5}\cmidrule(l){6-7} - & JSON & with LZ-String & JSON & with LZ-String & JSON & with LZ-String \\ + \cmidrule(l){2-3}\cmidrule(l){4-5}\cmidrule(l){6-7}\cmidrule(l){8-9} + & JSON & with LZ-String & JSON & with LZ-String & JSON & with LZ-String & JSON & with LZ-String \\ \midrule - $|n| = 1024$ & 1,617B & 576B & 338,902B & 95,738B & 123,354B & 34,857B \\ - $|n| = 2048$ & 3,153B & 1,050B & 662,233B & 187,333B & 252,230B & 70,868B \\ - $|n| = 4096$ & 6,226B & 1,999B & 1,315,027B & 368,646B & 484,117B & 135,990B \\ + $|n| = 1024$ & 1,617B & 576B & 338,902B & 95,738B & 123,354B & 34,857B & 895,474B & 248,420B \\ + $|n| = 2048$ & 3,153B & 1,050B & 662,233B & 187,333B & 252,230B & 70,868B & 1,746,017B & 485,787B \\ + $|n| = 4096$ & 6,226B & 1,999B & 1,315,027B & 368,646B & 484,117B & 135,990B & & \\ \bottomrule \end{tabularx} \parnotes