crypto_paillier/pk/
encrypt.rs1use 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}