jacobi based paillier

This commit is contained in:
2023-04-11 15:39:49 +01:00
parent 2700cb2792
commit 1d9ab1d601
4 changed files with 111 additions and 26 deletions

View File

@ -1,22 +1,17 @@
import { cryptoRandom, generate_prime } from "./random_primes.js";
import { mod_exp } from "./math.js";
import { gcd, mod_exp } from "./math.js";
class Ciphertext {
constructor(key, plainText, r) {
if (r === undefined) {
r = cryptoRandom(4096);
// Resample to avoid modulo bias.
while (r >= key.n) {
r = cryptoRandom(4096);
}
r = cryptoRandom(2048);
}
// Compute g^m by binomial theorem.
let gm = (1n + key.n * plainText) % key.n2;
// Compute g^m r^n from crt.
this.cipherText = (gm * mod_exp(r, key.n, key.n2)) % key.n2;
// Compute g^m h^r.
this.cipherText = (gm * mod_exp(key.hn, r, key.n2)) % key.n2;
// Force into range.
while (this.cipherText < 0n) {
@ -206,10 +201,25 @@ class ValueProofSessionVerifier {
window.ReadOnlyCiphertext = ReadOnlyCiphertext;
export class PaillierPubKey {
constructor(n) {
constructor(n, h) {
this.n = n;
this.n2 = this.n ** 2n;
if (h === undefined) {
let x = cryptoRandom(4096);
while (x >= this.n) {
x = cryptoRandom(4096);
}
this.h = ((-1n * x ** 2n) % this.n) + this.n;
} else {
this.h = h;
}
this.g = this.n + 1n;
this.n2 = this.n ** 2n;
this.hn = mod_exp(this.h, this.n, this.n2);
}
encrypt(m, r) {
@ -219,11 +229,12 @@ export class PaillierPubKey {
toJSON() {
return {
n: "0x" + this.n.toString(16),
h: "0x" + this.h.toString(16),
};
}
static fromJSON(data) {
return new PaillierPubKey(BigInt(data.n));
return new PaillierPubKey(BigInt(data.n), BigInt(data.h));
}
}
@ -241,22 +252,48 @@ class PaillierPrivKey {
}
}
function check_gcd(primes, new_prime) {
for (let prime of primes) {
if (gcd(prime - 1n, new_prime - 1n) === 2n) {
return prime;
}
}
return null;
}
export function generate_keypair() {
let p, q, pubKey, privKey;
if (window.sessionStorage.getItem("p") === null) {
p = generate_prime();
window.sessionStorage.setItem("p", p);
} else {
if (
window.sessionStorage.getItem("p") !== null &&
window.sessionStorage.getItem("q") !== null
) {
p = BigInt(window.sessionStorage.getItem("p"));
q = BigInt(window.sessionStorage.getItem("q"));
} else {
let p1 = generate_prime();
while (p1 % 4n !== 3n) {
p1 = generate_prime();
}
let primes = [p1];
while (
check_gcd(primes.slice(0, primes.length - 1), primes[primes.length - 1]) ===
null
) {
q = generate_prime();
while (q % 4n !== 3n) {
q = generate_prime();
}
primes.push(q);
}
p = check_gcd(primes.slice(0, primes.length - 1), primes[primes.length - 1]);
}
if (window.sessionStorage.getItem("q") === null) {
q = generate_prime();
window.sessionStorage.setItem("q", q);
} else {
q = BigInt(window.sessionStorage.getItem("q"));
}
window.sessionStorage.setItem("p", p);
window.sessionStorage.setItem("q", q);
pubKey = new PaillierPubKey(p * q);
privKey = new PaillierPrivKey(p, q);