1pub mod bootstrap;
29pub mod gadget;
30pub mod lwe;
31pub mod modular;
32pub mod params;
33
34pub use bootstrap::{bootstrap, decrypt_linear_part_clear, gen_evaluation_key, EvaluationKey};
35pub use gadget::{bit_decomp, bit_decomp_inverse, flatten, flatten_matrix, powers_of_2};
36pub use gsw::{
37 decrypt, encrypt, gsw_keygen, homomorphic_add, homomorphic_mult, homomorphic_nand,
38 Ciphertext, GswPublicKey, GswSecretKey,
39};
40pub use lwe::{keygen, PublicKey, SecretKey};
41pub use params::{Params, SecurityLevel};
42
43mod gsw;
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::bootstrap::{bootstrap, gen_evaluation_key};
49 use rand::SeedableRng;
50 use rand::thread_rng;
51 use rand_chacha::ChaCha20Rng;
52
53 #[test]
54 fn test_encrypt_decrypt() {
55 let params = Params::toy();
56 let mut rng = ChaCha20Rng::seed_from_u64(42);
57 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
58 for bit in [0u8, 1u8] {
59 let ct = encrypt(&mut rng, &pk, bit);
60 assert_eq!(decrypt(&sk, &ct), bit);
61 }
62 }
63
64 #[test]
65 fn test_homomorphic_ops() {
66 let params = Params::toy();
67 let mut rng = ChaCha20Rng::seed_from_u64(42);
68 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
69 let ct0 = encrypt(&mut rng, &pk, 0);
70 let ct1 = encrypt(&mut rng, &pk, 1);
71
72 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct0, &ct0)), 0);
73 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct0, &ct1)), 1);
74 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct1, &ct1)), 0);
75 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct0, &ct0)), 0);
76 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct0, &ct1)), 0);
77 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct1, &ct1)), 1);
78 assert_eq!(decrypt(&sk, &homomorphic_nand(¶ms, &ct1, &ct1)), 0);
79 }
80
81 #[test]
82 fn test_homomorphic_ops_deterministic() {
83 let params = Params::toy();
84 for seed in 0..100u64 {
85 let mut rng = ChaCha20Rng::seed_from_u64(seed);
86 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
87 let ct0 = encrypt(&mut rng, &pk, 0);
88 let ct1 = encrypt(&mut rng, &pk, 1);
89
90 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct0, &ct1)), 1, "seed {}: 0 XOR 1", seed);
91 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct0, &ct1)), 0, "seed {}: 0 AND 1", seed);
92 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct1, &ct1)), 1, "seed {}: 1 AND 1", seed);
93 }
94 }
95
96 #[test]
97 fn test_homomorphic_ops_nondeterministic() {
98 let params = Params::toy();
99 let mut rng = thread_rng();
100 for _ in 0..50 {
101 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
102 let ct0 = encrypt(&mut rng, &pk, 0);
103 let ct1 = encrypt(&mut rng, &pk, 1);
104
105 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct0, &ct0)), 0);
106 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct0, &ct1)), 1);
107 assert_eq!(decrypt(&sk, &homomorphic_add(¶ms, &ct1, &ct1)), 0);
108 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct0, &ct0)), 0);
109 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct0, &ct1)), 0);
110 assert_eq!(decrypt(&sk, &homomorphic_mult(¶ms, &ct1, &ct1)), 1);
111 assert_eq!(decrypt(&sk, &homomorphic_nand(¶ms, &ct1, &ct1)), 0);
112 }
113 }
114
115 #[test]
116 fn test_bootstrap_nondeterministic() {
117 let params = Params::toy();
119 let mut rng = thread_rng();
120 let mut passed = 0;
121 for _ in 0..50 {
122 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
123 let ek = gen_evaluation_key(&mut rng, &sk, &pk);
124 let ct1 = encrypt(&mut rng, &pk, 1);
125 let ct_noisy = homomorphic_mult(¶ms, &ct1, &ct1);
126 let ct_bootstrapped = bootstrap(¶ms, &ct_noisy, &ek);
127 if decrypt(&sk, &ct_bootstrapped) == 1 {
128 passed += 1;
129 }
130 }
131 assert!(passed >= 10, "Bootstrap must succeed with non-deterministic RNG (got {}/50)", passed);
132 }
133
134 #[test]
135 fn test_bootstrap() {
136 let params = Params::toy();
137 let mut rng = ChaCha20Rng::seed_from_u64(42);
138 let (sk, pk) = gsw_keygen(&mut rng, ¶ms);
139 let ek = gen_evaluation_key(&mut rng, &sk, &pk);
140 let ct1 = encrypt(&mut rng, &pk, 1);
141 let ct_noisy = homomorphic_mult(¶ms, &ct1, &ct1);
142 let ct_bootstrapped = bootstrap(¶ms, &ct_noisy, &ek);
143 assert_eq!(decrypt(&sk, &ct_bootstrapped), 1, "Bootstrap must produce correct output");
144 }
145}