Skip to main content

paillier_crypto/
lib.rs

1mod utils;
2use num_bigint::{BigInt, RandBigInt, ToBigInt};
3use num_traits::{One, Zero};
4
5use utils::{generate_prime, l, lcm, mod_inverse, mod_pow};
6
7#[derive(Debug, Clone)]
8pub struct PaillierPublicKey {
9    n: BigInt,
10    g: BigInt,
11}
12
13#[derive(Debug, Clone)]
14pub struct PaillierPrivateKey {
15    lambda: BigInt,
16    mu: BigInt,
17    public_key: PaillierPublicKey,
18}
19
20pub fn generate_keypair(bit_length: usize) -> (PaillierPublicKey, PaillierPrivateKey) {
21    let p = generate_prime(bit_length / 2);
22    let q = generate_prime(bit_length / 2);
23
24    let n = &p * &q;
25    let n_squared = &n * &n;
26
27    let lambda = lcm(&(p - 1), &(q - 1));
28    let g: BigInt = &n + 1;
29
30    let mu = mod_inverse(&l(&g.modpow(&lambda, &n_squared), &n), &n);
31
32    let public_key = PaillierPublicKey {
33        n: n.clone(),
34        g: g.clone(),
35    };
36    let private_key = PaillierPrivateKey {
37        lambda,
38        mu,
39        public_key: public_key.clone(),
40    };
41
42    dbg!(&private_key);
43
44    (public_key, private_key)
45}
46
47pub fn encrypt(public_key: &PaillierPublicKey, m: &BigInt) -> BigInt {
48    let mut rng = rand::thread_rng();
49    let r: BigInt = rng.gen_bigint_range(&BigInt::one(), &public_key.n);
50    let n_squared = &public_key.n * &public_key.n;
51
52    (public_key.g.modpow(m, &n_squared) * r.modpow(&public_key.n, &n_squared)) % &n_squared
53}
54
55pub fn decrypt(private_key: &PaillierPrivateKey, c: &BigInt) -> BigInt {
56    let n_squared = &private_key.public_key.n * &private_key.public_key.n;
57    (l(
58        &c.modpow(&private_key.lambda, &n_squared),
59        &private_key.public_key.n,
60    ) * &private_key.mu)
61        % &private_key.public_key.n
62}
63
64// Homomorphic addition of encrypted values
65pub fn add_encrypted(public_key: &PaillierPublicKey, c1: &BigInt, c2: &BigInt) -> BigInt {
66    let n_squared = &public_key.n * &public_key.n;
67    (c1 * c2) % &n_squared
68}
69
70pub fn additive_inverse(public_key: &PaillierPublicKey, c: &BigInt) -> BigInt {
71    let n_squared = &public_key.n * &public_key.n;
72    mod_pow(c, &(&public_key.n - BigInt::one()), &n_squared)
73}
74
75// Homomorphic subtraction of encrypted values
76pub fn subtract_encrypted(public_key: &PaillierPublicKey, c1: &BigInt, c2: &BigInt) -> BigInt {
77    let inverse_c2 = additive_inverse(public_key, c2);
78    add_encrypted(public_key, c1, &inverse_c2)
79}