jacobi based paillier
This commit is contained in:
@ -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);
|
||||
|
Reference in New Issue
Block a user