crypto_paillier/pk/
encrypt.rs

1use crate::pk::PublicKey;
2use crate::traits::{EncryptionKey, Key};
3use crate::utils::{nz_mul_mod, nz_pow_mod, nz_resize};
4use crypto_bigint::modular::SafeGcdInverter;
5use crypto_bigint::{Concat, NonZero, Odd, PrecomputeInverter, Split, Uint};
6use rand_core::CryptoRng;
7use subtle::{Choice, ConstantTimeEq, ConstantTimeLess};
8
9impl<const S: usize, const S_UNSAT: usize, const D: usize, const D_UNSAT: usize> Key<Uint<S>> for PublicKey<S, D>
10where
11    Uint<S>: Concat<Output = Uint<D>>,
12    Odd<Uint<S>>: PrecomputeInverter<Inverter = SafeGcdInverter<S, S_UNSAT>>,
13    Uint<D>: Split<Output = Uint<S>>,
14    Odd<Uint<D>>: PrecomputeInverter<Inverter = SafeGcdInverter<D, D_UNSAT>>,
15{
16    type Ciphertext = NonZero<Uint<D>>;
17    type Nonce = NonZero<Uint<S>>;
18
19    fn plaintext_is_valid(&self, m: &Uint<S>) -> Choice {
20        m.ct_lt(&self.n)
21    }
22
23    fn plaintext_eq(&self, ml: &Uint<S>, mr: &Uint<S>) -> Choice {
24        self.plaintext_is_valid(ml) & self.plaintext_is_valid(mr) & ml.ct_eq(mr)
25    }
26
27    fn ciphertext_is_valid(&self, c: &Self::Ciphertext) -> Choice {
28        c.ct_lt(self.precomputation.nn_monty_params.modulus())
29            & c.gcd(self.precomputation.nn_monty_params.modulus()).ct_eq(&Uint::ONE)
30    }
31
32    fn ciphertext_eq(&self, cl: &Self::Ciphertext, cr: &Self::Ciphertext) -> Choice {
33        self.ciphertext_is_valid(cl) & self.ciphertext_is_valid(cr) & cl.ct_eq(cr)
34    }
35
36    fn nonce_is_valid(&self, r: &Self::Nonce) -> Choice {
37        r.ct_lt(&self.n) & r.gcd(&self.n).ct_eq(&Uint::ONE)
38    }
39
40    fn nonce_eq(&self, rl: &Self::Nonce, rr: &Self::Nonce) -> Choice {
41        self.nonce_is_valid(rr) & self.nonce_is_valid(rl) & rl.ct_eq(rr)
42    }
43}
44
45impl<const S: usize, const S_UNSAT: usize, const D: usize, const D_UNSAT: usize, const Q: usize> EncryptionKey<Uint<S>>
46    for PublicKey<S, D>
47where
48    Uint<S>: Concat<Output = Uint<D>>,
49    Odd<Uint<S>>: PrecomputeInverter<Inverter = SafeGcdInverter<S, S_UNSAT>>,
50    Uint<D>: Split<Output = Uint<S>> + Concat<Output = Uint<Q>>,
51    Odd<Uint<D>>: PrecomputeInverter<Inverter = SafeGcdInverter<D, D_UNSAT>>,
52    Uint<Q>: Split<Output = Uint<D>>,
53{
54    fn encrypt_with_nonce(&self, m: &Uint<S>, r: &Self::Nonce) -> Self::Ciphertext {
55        let g_to_m = NonZero::new(self.n.widening_mul(m) + Uint::ONE).unwrap();
56        let r_to_n = nz_pow_mod(&nz_resize(r), self.n.as_nz_ref(), &self.precomputation.nn_monty_params);
57
58        nz_mul_mod(
59            &g_to_m,
60            &r_to_n,
61            self.precomputation.nn_monty_params.modulus().as_nz_ref(),
62        )
63    }
64
65    fn encrypt<R: CryptoRng + ?Sized>(&self, m: &Uint<S>, rng: &mut R) -> (Self::Ciphertext, Self::Nonce) {
66        let r = self.random_nonce(rng);
67        let c = self.encrypt_with_nonce(m, &r);
68        (c, r)
69    }
70}