arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
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}