paillier_common/
core.rs

1//! Core Paillier encryption scheme supporting ciphertext addition and plaintext multiplication.
2
3use std::borrow::{Borrow, Cow};
4
5use rayon::join;
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::traits::*;
9use crate::{
10    BigInt, DecryptionKey, EncryptionKey, Keypair, MinimalDecryptionKey, MinimalEncryptionKey,
11    Paillier, RawCiphertext, RawPlaintext,
12};
13use rust_bigint::traits::*;
14#[cfg(feature = "num_bigint")]
15use num_traits::One;
16
17impl Keypair {
18    /// Generate default encryption and decryption keys.
19    pub fn keys(&self) -> (EncryptionKey, DecryptionKey) {
20        (EncryptionKey::from(self), DecryptionKey::from(self))
21    }
22}
23
24impl<'p, 'q> From<(&'p BigInt, &'q BigInt)> for Keypair {
25    fn from((p, q): (&'p BigInt, &'q BigInt)) -> Keypair {
26        Keypair {
27            p: p.clone(),
28            q: q.clone(),
29        }
30    }
31}
32
33impl<'kp> From<&'kp Keypair> for MinimalEncryptionKey {
34    fn from(keypair: &'kp Keypair) -> Self {
35        MinimalEncryptionKey {
36            n: &keypair.p * &keypair.q,
37        }
38    }
39}
40
41impl<'e> From<&'e EncryptionKey> for MinimalEncryptionKey {
42    fn from(ek: &'e EncryptionKey) -> Self {
43        MinimalEncryptionKey { n: ek.n.clone() }
44    }
45}
46
47impl<'e> From<MinimalEncryptionKey> for EncryptionKey {
48    fn from(ek: MinimalEncryptionKey) -> Self {
49        let nn = &ek.n * &ek.n;
50        let n = ek.n;
51        EncryptionKey { n, nn }
52    }
53}
54
55impl<'kp> From<&'kp Keypair> for EncryptionKey {
56    fn from(keypair: &'kp Keypair) -> Self {
57        let minimal = MinimalEncryptionKey::from(keypair);
58        EncryptionKey::from(minimal)
59    }
60}
61
62// TODO[Morten] where is this needed?
63impl<'n> From<&'n BigInt> for EncryptionKey {
64    fn from(n: &'n BigInt) -> Self {
65        let minimal = MinimalEncryptionKey { n: n.clone() };
66        EncryptionKey::from(minimal)
67    }
68}
69
70impl Serialize for EncryptionKey {
71    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
72        let minimal = MinimalEncryptionKey::from(self);
73        minimal.serialize(serializer)
74    }
75}
76
77impl<'de> Deserialize<'de> for EncryptionKey {
78    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
79        let minimal = MinimalEncryptionKey::deserialize(deserializer)?;
80        Ok(EncryptionKey::from(minimal))
81    }
82}
83
84impl<'kp> From<&'kp Keypair> for MinimalDecryptionKey {
85    fn from(keypair: &'kp Keypair) -> Self {
86        MinimalDecryptionKey {
87            p: keypair.p.clone(),
88            q: keypair.q.clone(),
89        }
90    }
91}
92
93impl<'e> From<&'e DecryptionKey> for MinimalDecryptionKey {
94    fn from(dk: &'e DecryptionKey) -> Self {
95        MinimalDecryptionKey {
96            p: dk.p.clone(),
97            q: dk.q.clone(),
98        }
99    }
100}
101
102impl<'e> From<MinimalDecryptionKey> for DecryptionKey {
103    fn from(dk: MinimalDecryptionKey) -> Self {
104        let p = dk.p;
105        let q = dk.q;
106
107        DecryptionKey { p, q }
108    }
109}
110
111impl<'kp> From<&'kp Keypair> for DecryptionKey {
112    fn from(keypair: &'kp Keypair) -> DecryptionKey {
113        let minimal = MinimalDecryptionKey::from(keypair);
114        DecryptionKey::from(minimal)
115    }
116}
117
118impl Serialize for DecryptionKey {
119    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
120        let minimal = MinimalDecryptionKey::from(self);
121        minimal.serialize(serializer)
122    }
123}
124
125impl<'de> Deserialize<'de> for DecryptionKey {
126    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
127        let minimal = MinimalDecryptionKey::deserialize(deserializer)?;
128        Ok(DecryptionKey::from(minimal))
129    }
130}
131
132#[derive(Debug, PartialEq)]
133pub struct Randomness(pub BigInt);
134
135#[derive(Debug, PartialEq)]
136pub struct PrecomputedRandomness(pub BigInt);
137
138impl Randomness {
139    pub fn sample(ek: &EncryptionKey) -> Randomness {
140        Randomness(BigInt::sample_below(&ek.n))
141    }
142}
143
144impl From<BigInt> for Randomness {
145    fn from(x: BigInt) -> Randomness {
146        Randomness(x)
147    }
148}
149
150impl<'b> From<&'b BigInt> for Randomness {
151    fn from(x: &'b BigInt) -> Randomness {
152        Randomness(x.clone())
153    }
154}
155
156impl<'b> From<BigInt> for RawPlaintext<'b> {
157    fn from(x: BigInt) -> Self {
158        RawPlaintext(Cow::Owned(x))
159    }
160}
161
162impl<'b> From<&'b BigInt> for RawPlaintext<'b> {
163    fn from(x: &'b BigInt) -> Self {
164        RawPlaintext(Cow::Borrowed(x))
165    }
166}
167
168impl<'b> From<RawPlaintext<'b>> for BigInt {
169    fn from(x: RawPlaintext<'b>) -> Self {
170        x.0.into_owned()
171    }
172}
173
174impl<'b> From<BigInt> for RawCiphertext<'b> {
175    fn from(x: BigInt) -> Self {
176        RawCiphertext(Cow::Owned(x))
177    }
178}
179
180impl<'b> From<&'b BigInt> for RawCiphertext<'b> {
181    fn from(x: &'b BigInt) -> Self {
182        RawCiphertext(Cow::Borrowed(x))
183    }
184}
185
186impl<'b> From<RawCiphertext<'b>> for BigInt {
187    fn from(x: RawCiphertext<'b>) -> Self {
188        x.0.into_owned()
189    }
190}
191
192impl<'m, 'd> Encrypt<EncryptionKey, RawPlaintext<'m>, RawCiphertext<'d>> for Paillier {
193    fn encrypt(ek: &EncryptionKey, m: RawPlaintext<'m>) -> RawCiphertext<'d> {
194        let r = Randomness::sample(&ek);
195        let rn = BigInt::mod_pow(&r.0, &ek.n, &ek.nn);
196        let gm: BigInt = (m.0.borrow() as &BigInt * &ek.n + 1) % &ek.nn;
197        let c = (gm * rn) % &ek.nn;
198        RawCiphertext(Cow::Owned(c))
199    }
200}
201
202impl<'m, 'r, 'd>
203    EncryptWithChosenRandomness<EncryptionKey, RawPlaintext<'m>, &'r Randomness, RawCiphertext<'d>>
204    for Paillier
205{
206    fn encrypt_with_chosen_randomness(
207        ek: &EncryptionKey,
208        m: RawPlaintext<'m>,
209        r: &'r Randomness,
210    ) -> RawCiphertext<'d> {
211        let rn = BigInt::mod_pow(&r.0, &ek.n, &ek.nn);
212        let gm: BigInt = (m.0.borrow() as &BigInt * &ek.n + 1) % &ek.nn;
213        let c = (gm * rn) % &ek.nn;
214        RawCiphertext(Cow::Owned(c))
215    }
216}
217
218impl<'m, 'r, 'd>
219    EncryptWithChosenRandomness<
220        EncryptionKey,
221        RawPlaintext<'m>,
222        &'r PrecomputedRandomness,
223        RawCiphertext<'d>,
224    > for Paillier
225{
226    fn encrypt_with_chosen_randomness(
227        ek: &EncryptionKey,
228        m: RawPlaintext<'m>,
229        rn: &'r PrecomputedRandomness,
230    ) -> RawCiphertext<'d> {
231        let gm: BigInt = (m.0.borrow() as &BigInt * &ek.n + 1) % &ek.nn;
232        let c = (gm * &rn.0) % &ek.nn;
233        RawCiphertext(Cow::Owned(c))
234    }
235}
236
237impl<'m, 'd> Encrypt<DecryptionKey, RawPlaintext<'m>, RawCiphertext<'d>> for Paillier {
238    fn encrypt(dk: &DecryptionKey, m: RawPlaintext<'m>) -> RawCiphertext<'d> {
239        let dk_pp = &dk.p * &dk.p;
240        let dk_qq = &dk.q * &dk.q;
241        let dk_n = &dk.q * &dk.p;
242        let dk_ppinv = BigInt::mod_inv(&dk_pp, &dk_qq);
243        let (mp, mq) = crt_decompose(m.0.borrow(), &dk_pp, &dk_qq);
244        let (cp, cq) = join(
245            || {
246                let rp = BigInt::sample_below(&dk.p);
247                let rnp = BigInt::mod_pow(&rp, &dk_n, &dk_pp);
248                let gmp = (1 + mp * &dk_n) % &dk_pp; // TODO[Morten] maybe there's more to get here
249                (gmp * rnp) % &dk_pp
250            },
251            || {
252                let rq = BigInt::sample_below(&dk.q);
253                let rnq = BigInt::mod_pow(&rq, &dk_n, &dk_qq);
254                let gmq = (1 + mq * &dk_n) % &dk_qq; // TODO[Morten] maybe there's more to get here
255                (gmq * rnq) % &dk_qq
256            },
257        );
258        let c = crt_recombine(cp, cq, &dk_pp, &dk_qq, &dk_ppinv);
259        RawCiphertext(Cow::Owned(c))
260    }
261}
262
263impl<'m, 'r, 'd>
264    EncryptWithChosenRandomness<DecryptionKey, RawPlaintext<'m>, &'r Randomness, RawCiphertext<'d>>
265    for Paillier
266{
267    fn encrypt_with_chosen_randomness(
268        dk: &DecryptionKey,
269        m: RawPlaintext<'m>,
270        r: &'r Randomness,
271    ) -> RawCiphertext<'d> {
272        let dk_pp = &dk.p * &dk.p;
273        let dk_qq = &dk.q * &dk.q;
274        let dk_n = &dk.q * &dk.p;
275        let dk_ppinv = BigInt::mod_inv(&dk_pp, &dk_qq);
276        let (mp, mq) = crt_decompose(m.0.borrow(), &dk_pp, &dk_qq);
277        let (rp, rq) = crt_decompose(&r.0, &dk_pp, &dk_qq);
278        let (cp, cq) = join(
279            || {
280                let rnp = BigInt::mod_pow(&rp, &dk_n, &dk_pp);
281                let gmp = (1 + mp * &dk_n) % &dk_pp; // TODO[Morten] maybe there's more to get here
282                (gmp * rnp) % &dk_pp
283            },
284            || {
285                let rnq = BigInt::mod_pow(&rq, &dk_n, &dk_qq);
286                let gmq = (1 + mq * &dk_n) % &dk_qq; // TODO[Morten] maybe there's more to get here
287                (gmq * rnq) % &dk_qq
288            },
289        );
290        let c = crt_recombine(cp, cq, &dk_pp, &dk_qq, &dk_ppinv);
291        RawCiphertext(Cow::Owned(c))
292    }
293}
294
295impl<'m, 'r, 'd>
296    EncryptWithChosenRandomness<
297        DecryptionKey,
298        RawPlaintext<'m>,
299        &'r PrecomputedRandomness,
300        RawCiphertext<'d>,
301    > for Paillier
302{
303    fn encrypt_with_chosen_randomness(
304        dk: &DecryptionKey,
305        m: RawPlaintext<'m>,
306        rn: &'r PrecomputedRandomness,
307    ) -> RawCiphertext<'d> {
308        let dk_n = &dk.q * &dk.p;
309        let dk_nn = &dk_n * &dk_n;
310        let gm = (1 + m.0.borrow() as &BigInt * &dk_n) % &dk_nn;
311        let c = (gm * &rn.0) % &dk_nn;
312        RawCiphertext(Cow::Owned(c))
313    }
314}
315
316impl<'ek, 'r> PrecomputeRandomness<&'ek EncryptionKey, &'r BigInt, PrecomputedRandomness>
317    for Paillier
318{
319    fn precompute(ek: &'ek EncryptionKey, r: &'r BigInt) -> PrecomputedRandomness {
320        let rn = BigInt::mod_pow(r, &ek.n, &ek.nn);
321        PrecomputedRandomness(rn)
322    }
323}
324
325impl<'c, 'd> Rerandomize<EncryptionKey, RawCiphertext<'c>, RawCiphertext<'d>> for Paillier {
326    fn rerandomize(ek: &EncryptionKey, c: RawCiphertext<'c>) -> RawCiphertext<'d> {
327        let r = BigInt::sample_below(&ek.n);
328        let rn = BigInt::mod_pow(&r, &ek.n, &ek.nn);
329        let d = (c.0.borrow() as &BigInt * rn) % &ek.nn;
330        RawCiphertext(Cow::Owned(d))
331    }
332}
333
334/// TODO
335///
336/// Efficient decryption using CRT based on [Paillier99, section 7](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.4035&rep=rep1&type=pdf)
337impl<'c, 'm> Decrypt<DecryptionKey, RawCiphertext<'c>, RawPlaintext<'m>> for Paillier {
338    fn decrypt(dk: &DecryptionKey, c: RawCiphertext<'c>) -> RawPlaintext<'m> {
339        Self::decrypt(dk, &c)
340    }
341}
342
343/// TODO
344///
345/// Efficient decryption using CRT based on [Paillier99, section 7](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.112.4035&rep=rep1&type=pdf)
346impl<'c, 'm> Decrypt<DecryptionKey, &'c RawCiphertext<'c>, RawPlaintext<'m>> for Paillier {
347    fn decrypt(dk: &DecryptionKey, c: &'c RawCiphertext<'c>) -> RawPlaintext<'m> {
348        let dk_qq = &dk.q * &dk.q;
349        let dk_pp = &dk.p * &dk.p;
350        let dk_n = &dk.p * &dk.q;
351        let dk_pinv = BigInt::mod_inv(&dk.p, &dk.q);
352        let dk_qminusone = &dk.q - BigInt::one();
353        let dk_pminusone = &dk.p - BigInt::one();
354        let dk_hp = h(&dk.p, &dk_pp, &dk_n);
355        let dk_hq = h(&dk.q, &dk_qq, &dk_n);
356        let (cp, cq) = crt_decompose(c.0.borrow(), &dk_pp, &dk_qq);
357        // decrypt in parallel with respectively p and q
358        let (mp, mq) = join(
359            || {
360                // process using p
361                let dp = BigInt::mod_pow(&cp, &dk_pminusone, &dk_pp);
362                let lp = l(&dp, &dk.p);
363                (&lp * &dk_hp) % &dk.p
364            },
365            || {
366                // process using q
367                let dq = BigInt::mod_pow(&cq, &dk_qminusone, &dk_qq);
368                let lq = l(&dq, &dk.q);
369                (&lq * &dk_hq) % &dk.q
370            },
371        );
372        // perform CRT
373        let m = crt_recombine(mp, mq, &dk.p, &dk.q, &dk_pinv);
374        RawPlaintext(Cow::Owned(m))
375    }
376}
377
378impl<'c, 'm> Open<DecryptionKey, RawCiphertext<'c>, RawPlaintext<'m>, Randomness> for Paillier {
379    fn open(dk: &DecryptionKey, c: RawCiphertext<'c>) -> (RawPlaintext<'m>, Randomness) {
380        Self::open(dk, &c)
381    }
382}
383
384impl<'c, 'm> Open<DecryptionKey, &'c RawCiphertext<'c>, RawPlaintext<'m>, Randomness> for Paillier {
385    fn open(dk: &DecryptionKey, c: &'c RawCiphertext<'c>) -> (RawPlaintext<'m>, Randomness) {
386        let dk_n = &dk.p * &dk.q;
387        let dk_nn = &dk_n * &dk_n;
388
389        let m = Self::decrypt(dk, c);
390        let gminv = (BigInt::one() - (m.0.borrow() as &BigInt) * &dk_n) % &dk_nn;
391        let rn = (c.0.borrow() as &BigInt * gminv) % &dk_nn;
392        let r = extract_nroot(dk, &rn);
393        (m, Randomness(r))
394    }
395}
396
397impl<'c1, 'c2, 'd> Add<EncryptionKey, RawCiphertext<'c1>, RawCiphertext<'c2>, RawCiphertext<'d>>
398    for Paillier
399{
400    fn add(
401        ek: &EncryptionKey,
402        c1: RawCiphertext<'c1>,
403        c2: RawCiphertext<'c2>,
404    ) -> RawCiphertext<'d> {
405        let d = (c1.0.borrow() as &BigInt * c2.0.borrow() as &BigInt) % &ek.nn;
406        RawCiphertext(Cow::Owned(d))
407    }
408}
409
410impl<'c, 'm, 'd> Add<EncryptionKey, RawCiphertext<'c>, RawPlaintext<'m>, RawCiphertext<'d>>
411    for Paillier
412{
413    fn add(ek: &EncryptionKey, c: RawCiphertext<'c>, m: RawPlaintext<'m>) -> RawCiphertext<'d> {
414        let c1 = c.0.borrow() as &BigInt;
415        let c2 = (m.0.borrow() as &BigInt * &ek.n + 1) % &ek.nn;
416        let d = (c1 * c2) % &ek.nn;
417        RawCiphertext(Cow::Owned(d))
418    }
419}
420
421impl<'c, 'm, 'd> Add<EncryptionKey, RawPlaintext<'m>, RawCiphertext<'c>, RawCiphertext<'d>>
422    for Paillier
423{
424    fn add(ek: &EncryptionKey, m: RawPlaintext<'m>, c: RawCiphertext<'c>) -> RawCiphertext<'d> {
425        let c1 = (m.0.borrow() as &BigInt * &ek.n + 1) % &ek.nn;
426        let c2 = c.0.borrow() as &BigInt;
427        let d = (c1 * c2) % &ek.nn;
428        RawCiphertext(Cow::Owned(d))
429    }
430}
431
432impl<'c, 'm, 'd> Mul<EncryptionKey, RawCiphertext<'c>, RawPlaintext<'m>, RawCiphertext<'d>>
433    for Paillier
434{
435    fn mul(ek: &EncryptionKey, c: RawCiphertext<'c>, m: RawPlaintext<'m>) -> RawCiphertext<'d> {
436        RawCiphertext(Cow::Owned(BigInt::mod_pow(
437            c.0.borrow(),
438            m.0.borrow(),
439            &ek.nn,
440        )))
441    }
442}
443
444impl<'c, 'm, 'd> Mul<EncryptionKey, RawPlaintext<'m>, RawCiphertext<'c>, RawCiphertext<'d>>
445    for Paillier
446{
447    fn mul(ek: &EncryptionKey, m: RawPlaintext<'m>, c: RawCiphertext<'c>) -> RawCiphertext<'d> {
448        RawCiphertext(Cow::Owned(BigInt::mod_pow(
449            c.0.borrow(),
450            m.0.borrow(),
451            &ek.nn,
452        )))
453    }
454}
455
456fn h(p: &BigInt, pp: &BigInt, n: &BigInt) -> BigInt {
457    // here we assume:
458    //  - p \in {P, Q}
459    //  - n = P * Q
460    //  - g = 1 + n
461
462    // compute g^{p-1} mod p^2
463    let gp = (1 - n) % pp;
464    // compute L_p(.)
465    let lp = l(&gp, p);
466    // compute L_p(.)^{-1}
467    BigInt::mod_inv(&lp, p)
468}
469
470fn l(u: &BigInt, n: &BigInt) -> BigInt {
471    (u - 1) / n
472}
473
474fn crt_decompose<X, M1, M2>(x: X, m1: M1, m2: M2) -> (BigInt, BigInt)
475where
476    X: Borrow<BigInt>,
477    M1: Borrow<BigInt>,
478    M2: Borrow<BigInt>,
479{
480    (x.borrow() % m1.borrow(), x.borrow() % m2.borrow())
481}
482
483fn crt_recombine<X1, X2, M1, M2, I>(x1: X1, x2: X2, m1: M1, m2: M2, m1inv: I) -> BigInt
484where
485    X1: Borrow<BigInt>,
486    X2: Borrow<BigInt>,
487    M1: Borrow<BigInt>,
488    M2: Borrow<BigInt>,
489    I: Borrow<BigInt>,
490{
491    let diff = BigInt::mod_sub(x2.borrow(), x1.borrow(), m2.borrow());
492    //  let mut diff = (x2.borrow() - x1.borrow()) % m2.borrow();
493    //  if NumberTests::is_negative(&diff) {
494    //      diff += m2.borrow();
495    //  }
496    let u = (diff * m1inv.borrow()) % m2.borrow();
497    x1.borrow() + (u * m1.borrow())
498}
499
500/// Extract randomness component of a zero ciphertext.
501pub fn extract_nroot(dk: &DecryptionKey, z: &BigInt) -> BigInt {
502    let dk_n = &dk.p * &dk.q;
503
504    let dk_pinv = BigInt::mod_inv(&dk.p, &dk.q);
505    let dk_qminusone = &dk.q - BigInt::one();
506    let dk_pminusone = &dk.p - BigInt::one();
507
508    let dk_phi = &dk_pminusone * &dk_qminusone;
509    let dk_dn = BigInt::mod_inv(&dk_n, &dk_phi);
510    let (dk_dp, dk_dq) = crt_decompose(dk_dn, &dk_pminusone, &dk_qminusone);
511    let (zp, zq) = crt_decompose(z, &dk.p, &dk.q);
512
513    let rp = BigInt::mod_pow(&zp, &dk_dp, &dk.p);
514    let rq = BigInt::mod_pow(&zq, &dk_dq, &dk.q);
515
516    crt_recombine(rp, rq, &dk.p, &dk.q, &dk_pinv)
517}
518
519#[cfg(test)]
520mod tests {
521
522    use super::*;
523
524    extern crate serde_json;
525
526    fn test_keypair() -> Keypair {
527        let p = str::parse("148677972634832330983979593310074301486537017973460461278300587514468301043894574906886127642530475786889672304776052879927627556769456140664043088700743909632312483413393134504352834240399191134336344285483935856491230340093391784574980688823380828143810804684752914935441384845195613674104960646037368551517").unwrap();
528        let q = str::parse("158741574437007245654463598139927898730476924736461654463975966787719309357536545869203069369466212089132653564188443272208127277664424448947476335413293018778018615899291704693105620242763173357203898195318179150836424196645745308205164116144020613415407736216097185962171301808761138424668335445923774195463").unwrap();
529        Keypair { p, q }
530    }
531
532    #[test]
533    fn test_correct_encryption_decryption() {
534        let (ek, dk) = test_keypair().keys();
535
536        let p = RawPlaintext::from(BigInt::from(10));
537        let c = Paillier::encrypt(&ek, p.clone());
538
539        let recovered_p = Paillier::decrypt(&dk, c);
540        assert_eq!(recovered_p, p);
541    }
542
543    #[test]
544    fn test_correct_opening() {
545        let (ek, dk) = test_keypair().keys();
546
547        let c = Paillier::encrypt(&ek, RawPlaintext::from(BigInt::from(10)));
548        let (m, r) = Paillier::open(&dk, &c);
549        let d = Paillier::encrypt_with_chosen_randomness(&ek, m, &r);
550        assert_eq!(c, d);
551    }
552
553    #[test]
554    fn test_correct_addition() {
555        let (ek, dk) = test_keypair().keys();
556
557        let m1 = RawPlaintext::from(BigInt::from(10));
558        let c1 = Paillier::encrypt(&ek, m1);
559        let m2 = RawPlaintext::from(BigInt::from(20));
560        let c2 = Paillier::encrypt(&ek, m2);
561
562        let c = Paillier::add(&ek, c1, c2);
563        let m = Paillier::decrypt(&dk, c);
564        assert_eq!(m, BigInt::from(30).into());
565    }
566
567    #[test]
568    fn correct_multiplication() {
569        let (ek, dk) = test_keypair().keys();
570
571        let m1 = RawPlaintext::from(BigInt::from(10));
572        let c1 = Paillier::encrypt(&ek, m1);
573        let m2 = RawPlaintext::from(BigInt::from(20));
574
575        let c = Paillier::mul(&ek, c1, m2);
576        let m = Paillier::decrypt(&dk, c);
577        assert_eq!(m, BigInt::from(200).into());
578    }
579
580    #[cfg(feature = "keygen")]
581    #[test]
582    fn test_correct_keygen() {
583        let (ek, dk): (EncryptionKey, _) = Paillier::keypair_with_modulus_size(2048).keys();
584
585        let m = RawPlaintext::from(BigInt::from(10));
586        let c = Paillier::encrypt(&ek, m.clone()); // TODO avoid clone
587
588        let recovered_m = Paillier::decrypt(&dk, c);
589        assert_eq!(recovered_m, m);
590    }
591
592    #[test]
593    fn test_key_serialization() {
594        let (ek, dk) = test_keypair().keys();
595
596        let ek_serialized = serde_json::to_string(&ek).unwrap();
597        let ek_recovered: EncryptionKey = serde_json::from_str(&ek_serialized).unwrap();
598        assert_eq!(ek, ek_recovered);
599
600        let dk_serialized = serde_json::to_string(&dk).unwrap();
601        let dk_recovered: DecryptionKey = serde_json::from_str(&dk_serialized).unwrap();
602        assert_eq!(dk, dk_recovered);
603    }
604
605    #[test]
606    fn test_failing_deserialize() {
607        let illformatted = "{\"n\":\"12345abcdefg\"}";
608
609        let result: Result<EncryptionKey, _> = serde_json::from_str(&illformatted);
610        assert!(result.is_err())
611    }
612}