phantom-zone/src/noise.rs
src/noise.rsRaw
1#[cfg(test)]
2mod tests {
3 use rand::{thread_rng, Rng};
4
5 use crate::{
6 backend::{ArithmeticOps, ModInit, ModularOpsU64},
7 decomposer::{gadget_vector, Decomposer, DefaultDecomposer},
8 ntt::{Ntt, NttBackendU64, NttInit},
9 random::{DefaultSecureRng, RandomGaussianDist, RandomUniformDist},
10 rgsw::{
11 less1_rlwe_by_rgsw, measure_noise, rgsw_by_rgsw_inplace, rlwe_by_rgsw,
12 secret_key_encrypt_rgsw, secret_key_encrypt_rlwe, RgswCiphertext,
13 RgswCiphertextEvaluationDomain, RlweCiphertext, RlweSecret, SeededRgswCiphertext,
14 SeededRlweCiphertext,
15 },
16 utils::{generate_prime, negacyclic_mul},
17 Matrix, Row, Secret,
18 };
19
20 // Test B part with limbd -1 when variance of m is 1
21 #[test]
22 fn trial() {
23 let logq = 28;
24 let ring_size = 1 << 10;
25 let q = generate_prime(logq, (ring_size as u64) << 1, 1 << logq).unwrap();
26 let logb = 7;
27 let d0 = 3;
28 let d1 = d0 - 1;
29
30 let sk = RlweSecret::random((ring_size >> 1) as usize, ring_size as usize);
31
32 let mut rng = DefaultSecureRng::new();
33 let gadget_vector = gadget_vector(logq, logb, d0);
34
35 for i in 0..100 {
36 // m should have norm 1
37 let mut m0 = vec![0u64; ring_size as usize];
38 m0[thread_rng().gen_range(0..ring_size)] = 1;
39
40 let modq_op = ModularOpsU64::new(q);
41 let nttq_op = NttBackendU64::new(q, ring_size);
42
43 // Encrypt RGSW(m0)
44 let mut rgsw_seed = [0u8; 32];
45 rng.fill_bytes(&mut rgsw_seed);
46 let mut seeded_rgsw =
47 SeededRgswCiphertext::<Vec<Vec<u64>>, _>::empty(ring_size, d0, rgsw_seed, q);
48 let mut p_rng = DefaultSecureRng::new_seeded(rgsw_seed);
49 secret_key_encrypt_rgsw(
50 &mut seeded_rgsw.data,
51 &m0,
52 &gadget_vector,
53 sk.values(),
54 &modq_op,
55 &nttq_op,
56 &mut p_rng,
57 &mut rng,
58 );
59
60 // Encrypt RLWE(m1)
61 let mut m1 = vec![0u64; ring_size];
62 RandomUniformDist::random_fill(&mut rng, &q, m1.as_mut_slice());
63 let mut rlwe_seed = [0u8; 32];
64 rng.fill_bytes(&mut rlwe_seed);
65 let mut seeded_rlwe: SeededRlweCiphertext<Vec<u64>, [u8; 32]> =
66 SeededRlweCiphertext::<Vec<u64>, _>::empty(ring_size, rlwe_seed, q);
67 let mut p_rng = DefaultSecureRng::new_seeded(rlwe_seed);
68 secret_key_encrypt_rlwe(
69 &m1,
70 &mut seeded_rlwe.data,
71 sk.values(),
72 &modq_op,
73 &nttq_op,
74 &mut p_rng,
75 &mut rng,
76 );
77
78 let mut rlwe = RlweCiphertext::<Vec<Vec<u64>>, DefaultSecureRng>::from(&seeded_rlwe);
79 let rgsw = RgswCiphertextEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from(
80 &seeded_rgsw,
81 );
82
83 // RLWE(m0m1) = RLWE(m1) x RGSW(m0)
84 let mut scratch = vec![vec![0u64; ring_size]; d0 + 2];
85 let decomposer = DefaultDecomposer::new(q, logb, d0);
86 less1_rlwe_by_rgsw(
87 &mut rlwe,
88 &rgsw.data,
89 &mut scratch,
90 &decomposer,
91 &nttq_op,
92 &modq_op,
93 0,
94 1,
95 );
96 // rlwe_by_rgsw(
97 // &mut rlwe,
98 // &rgsw.data,
99 // &mut scratch,
100 // &decomposer,
101 // &nttq_op,
102 // &modq_op,
103 // );
104
105 // measure noise
106 let mul_mod = |v0: &u64, v1: &u64| ((*v0 as u128 * *v1 as u128) % q as u128) as u64;
107 let m0m1 = negacyclic_mul(&m0, &m1, mul_mod, q);
108 let noise = measure_noise(&rlwe, &m0m1, &nttq_op, &modq_op, sk.values());
109 println!("Noise: {noise}");
110 }
111 }
112
113 // Test B part with limbd -1 when variance of m is 1
114 #[test]
115 fn rgsw_saver() {
116 let logq = 60;
117 let ring_size = 1 << 11;
118 let q = generate_prime(logq, (ring_size as u64) << 1, 1 << logq).unwrap();
119 let logb = 12;
120 let d0 = 4;
121
122 let sk = RlweSecret::random((ring_size >> 1) as usize, ring_size as usize);
123
124 let mut rng = DefaultSecureRng::new();
125 let gadget_vector = gadget_vector(logq, logb, d0);
126
127 let decomposer = DefaultDecomposer::new(q, logb, d0);
128
129 for i in 0..100 {
130 let modq_op = ModularOpsU64::new(q);
131 let nttq_op = NttBackendU64::new(q, ring_size);
132
133 // Encrypt RGSW(m0)
134 let mut m0 = vec![0u64; ring_size as usize];
135 m0[thread_rng().gen_range(0..ring_size)] = 1;
136 let mut rgsw_seed = [0u8; 32];
137 rng.fill_bytes(&mut rgsw_seed);
138 let mut seeded_rgsw0 =
139 SeededRgswCiphertext::<Vec<Vec<u64>>, _>::empty(ring_size, d0, rgsw_seed, q);
140 let mut p_rng = DefaultSecureRng::new_seeded(rgsw_seed);
141 secret_key_encrypt_rgsw(
142 &mut seeded_rgsw0.data,
143 &m0,
144 &gadget_vector,
145 sk.values(),
146 &modq_op,
147 &nttq_op,
148 &mut p_rng,
149 &mut rng,
150 );
151
152 // Encrypt RGSW(m1)
153 let mut m1 = vec![0u64; ring_size as usize];
154 m1[thread_rng().gen_range(0..ring_size)] = 1;
155 let mut rgsw_seed = [0u8; 32];
156 rng.fill_bytes(&mut rgsw_seed);
157 let mut seeded_rgsw1 =
158 SeededRgswCiphertext::<Vec<Vec<u64>>, _>::empty(ring_size, d0, rgsw_seed, q);
159 let mut p_rng = DefaultSecureRng::new_seeded(rgsw_seed);
160 secret_key_encrypt_rgsw(
161 &mut seeded_rgsw1.data,
162 &m1,
163 &gadget_vector,
164 sk.values(),
165 &modq_op,
166 &nttq_op,
167 &mut p_rng,
168 &mut rng,
169 );
170
171 // TODO(Jay): Why cant you create RgswCIphertext from SeededRgswCiphertext?
172 let mut rgsw0 = {
173 let mut evl_tmp =
174 RgswCiphertextEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from(
175 &seeded_rgsw0,
176 );
177 evl_tmp
178 .data
179 .iter_mut()
180 .for_each(|ri| nttq_op.backward(ri.as_mut()));
181 evl_tmp.data
182 };
183 let rgsw1 = RgswCiphertextEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from(
184 &seeded_rgsw1,
185 );
186 let mut scratch_matrix_d_plus_rgsw_by_ring = vec![vec![0u64; ring_size]; d0 + (d0 * 4)];
187
188 // RGSW(m0m1) = RGSW(m0)xRGSW(m1)
189 rgsw_by_rgsw_inplace(
190 &mut rgsw0,
191 &rgsw1.data,
192 &decomposer,
193 &mut scratch_matrix_d_plus_rgsw_by_ring,
194 &nttq_op,
195 &modq_op,
196 );
197
198 // send RGSW(m0m1) to Evaluation domain
199 let mut rgsw01 = rgsw0;
200 rgsw01
201 .iter_mut()
202 .for_each(|v| nttq_op.forward(v.as_mut_slice()));
203
204 // RLWE(m2)
205 let mut m2 = vec![0u64; ring_size as usize];
206 RandomUniformDist::random_fill(&mut rng, &q, m2.as_mut_slice());
207 let mut rlwe_seed = [0u8; 32];
208 rng.fill_bytes(&mut rlwe_seed);
209 let mut seeded_rlwe =
210 SeededRlweCiphertext::<Vec<u64>, _>::empty(ring_size, rlwe_seed, q);
211 let mut p_rng = DefaultSecureRng::new_seeded(rlwe_seed);
212 secret_key_encrypt_rlwe(
213 &m2,
214 &mut seeded_rlwe.data,
215 sk.values(),
216 &modq_op,
217 &nttq_op,
218 &mut p_rng,
219 &mut rng,
220 );
221
222 let mut rlwe = RlweCiphertext::<Vec<Vec<u64>>, DefaultSecureRng>::from(&seeded_rlwe);
223
224 // RLWE(m0m1m2) = RLWE(m2) x RGSW(m0m1)
225 let mut scratch_matrix_dplus2_ring = vec![vec![0u64; ring_size]; d0 + 2];
226 less1_rlwe_by_rgsw(
227 &mut rlwe,
228 &rgsw01,
229 &mut scratch_matrix_dplus2_ring,
230 &decomposer,
231 &nttq_op,
232 &modq_op,
233 1,
234 2,
235 );
236
237 let mul_mod = |v0: &u64, v1: &u64| ((*v0 as u128 * *v1 as u128) % q as u128) as u64;
238 let m0m1 = negacyclic_mul(&m0, &m1, mul_mod, q);
239 let m0m1m2 = negacyclic_mul(&m2, &m0m1, mul_mod, q);
240 let noise = measure_noise(&rlwe.data, &m0m1m2, &nttq_op, &modq_op, sk.values());
241
242 println!("Noise: {noise}");
243 }
244 }
245}