in crypto/src/paillier.rs [70:110]
fn gen_decryption_key(key: MinimalDecryptionKey) -> DecryptionKey {
assert!(key.p > BigUint::one());
assert!(key.q > BigUint::one());
let l_n = &key.p * &key.q;
let l_pp = &key.p * &key.p;
let l_qq = &key.q * &key.q;
let l_nn = &l_n * &l_n;
let l_p_1 = &key.p - BigUint::one();
let l_q_1 = &key.q - BigUint::one();
let l_p_inv = mod_inverse(&key.p, &key.q).unwrap().to_biguint().unwrap();
let g = &l_n + BigUint::one();
let l_p = l(&(g.modpow(&l_p_1, &l_pp)), &key.p);
let l_q = l(&(g.modpow(&l_q_1, &l_qq)), &key.q);
let l_h_p = mod_inverse(&l_p, &key.p).unwrap().to_biguint().unwrap();
let l_h_q = mod_inverse(&l_q, &key.q).unwrap().to_biguint().unwrap();
// let l = (&key.p - BigUint::one()) * (&key.q - BigUint::one());
let l = &l_p_1 * &l_q_1;
let m = mod_inverse(&l, &l_n).unwrap().to_biguint().unwrap();
assert!(((&l * &m) % &l_n) == BigUint::one());
DecryptionKey {
p: key.p,
q: key.q,
p_1: l_p_1,
q_1: l_q_1,
p_inv: l_p_inv,
n: l_n,
pp: l_pp,
qq: l_qq,
nn: l_nn,
h_p: l_h_p,
h_q: l_h_q,
lambda: l,
mu: m,
}
}