diff --git a/static/js/modules/crypto/paillier.js b/static/js/modules/crypto/paillier.js index caa317b..f8fe410 100644 --- a/static/js/modules/crypto/paillier.js +++ b/static/js/modules/crypto/paillier.js @@ -97,6 +97,20 @@ class Ciphertext { } } + mul(e) { + this.cipherText = mod_exp(this.cipherText, e, this.pubKey.n2); + this.r = mod_exp(this.r, e, this.pubKey.n2); + this.plainText = (this.plainText * e) % this.pubKey.n2; + + // Force into range + while (this.cipherText < 0n) { + this.cipherText += this.pubKey.n2; + } + while (this.plainText < 0n) { + this.plainText += this.pubKey.n2; + } + } + toString() { return "0x" + this.cipherText.toString(16); } @@ -202,6 +216,15 @@ export class ReadOnlyCiphertext { } } + mul(e) { + this.cipherText = mod_exp(this.cipherText, e, this.pubKey.n2); + + // Force into range + while (this.cipherText < 0n) { + this.cipherText += this.pubKey.n2; + } + } + prove(plainText, a) { return new ValueProofSessionVerifier(this, plainText, a); } diff --git a/static/js/modules/interface/proofs.js b/static/js/modules/interface/proofs.js index 4694a12..70e2045 100644 --- a/static/js/modules/interface/proofs.js +++ b/static/js/modules/interface/proofs.js @@ -1,5 +1,6 @@ import { cryptoRandom } from "../crypto/random_primes.js"; import { Region } from "./map.js"; +import { mod_exp } from "../crypto/math.js"; function cryptoRange(upper) { // This is ridiculous: why implement a BigInt primitive, have it behave like a number, and then _not_ offer @@ -294,6 +295,43 @@ export function verifyRange(obj, key) { window.verifyRange = verifyRange; +export function proveBitLength(cipherText) { + if (cipherText.readOnly) { + throw "Cannot prove readonly ciphertext"; + } + + let key = cipherText.pubKey; + + // Compute decomposition + let bitCommitments = []; + + let m = cipherText.plainText; + let prod = cipherText.clone(); + let e = 1n; + + while (m !== 0n) { + let bit = m & 0b1n; + let cBit = key.encrypt(-bit); + bitCommitments.push(cBit); + + let cBit2 = cBit.clone(); + cBit2.mul(e); + prod.update(cBit2); + + e <<= 1n; + m >>= 1n; + } + + // TODO finish this + + return { + bitCommitments: bitCommitments, + bitProof: prod.proveNI(), + }; +} + +window.proveBitLength = proveBitLength; + /** * - We prove that the set contains |S| - 2 zeros, with the final pair summing to zero and sums with the original * set are zero.