phantom-zone/src/shortint/enc_dec.rs
src/shortint/enc_dec.rsRaw
1use itertools::Itertools;
2
3use crate::{
4 bool::BoolEvaluator,
5 random::{DefaultSecureRng, RandomFillUniformInModulus},
6 utils::{TryConvertFrom1, WithLocal},
7 Decryptor, Encryptor, KeySwitchWithId, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor,
8 RowMut,
9};
10
11#[derive(Clone)]
12pub struct FheUint8<C> {
13 pub(super) data: Vec<C>,
14}
15
16impl<C> FheUint8<C> {
17 pub(super) fn data(&self) -> &[C] {
18 &self.data
19 }
20
21 pub(super) fn data_mut(&mut self) -> &mut [C] {
22 &mut self.data
23 }
24}
25
26pub struct BatchedFheUint8<C> {
27 data: Vec<C>,
28}
29
30impl<M: MatrixEntity + MatrixMut<MatElement = u64>> From<&SeededBatchedFheUint8<M::R, [u8; 32]>>
31 for BatchedFheUint8<M>
32where
33 <M as Matrix>::R: RowMut,
34{
35 fn from(value: &SeededBatchedFheUint8<M::R, [u8; 32]>) -> Self {
36 BoolEvaluator::with_local(|e| {
37 let parameters = e.parameters();
38 let ring_size = parameters.rlwe_n().0;
39 let rlwe_q = parameters.rlwe_q();
40
41 let mut prng = DefaultSecureRng::new_seeded(value.seed);
42 let rlwes = value
43 .data
44 .iter()
45 .map(|partb| {
46 let mut rlwe = M::zeros(2, ring_size);
47
48 // sample A
49 RandomFillUniformInModulus::random_fill(&mut prng, rlwe_q, rlwe.get_row_mut(0));
50
51 // Copy over B
52 rlwe.get_row_mut(1).copy_from_slice(partb.as_ref());
53
54 rlwe
55 })
56 .collect_vec();
57 Self { data: rlwes }
58 })
59 }
60}
61
62pub struct SeededBatchedFheUint8<C, S> {
63 data: Vec<C>,
64 seed: S,
65}
66
67impl<C, S> SeededBatchedFheUint8<C, S> {
68 pub fn unseed<M>(&self) -> BatchedFheUint8<M>
69 where
70 BatchedFheUint8<M>: for<'a> From<&'a SeededBatchedFheUint8<C, S>>,
71 M: Matrix<R = C>,
72 {
73 BatchedFheUint8::from(self)
74 }
75}
76
77impl<K, C, S> Encryptor<[u8], SeededBatchedFheUint8<C, S>> for K
78where
79 K: Encryptor<[bool], (Vec<C>, S)>,
80{
81 fn encrypt(&self, m: &[u8]) -> SeededBatchedFheUint8<C, S> {
82 // convert vector of u8s to vector bools
83 let m = m
84 .iter()
85 .flat_map(|v| (0..8).into_iter().map(|i| (((*v) >> i) & 1) == 1))
86 .collect_vec();
87 let (cts, seed) = K::encrypt(&self, &m);
88 dbg!(cts.len());
89 SeededBatchedFheUint8 { data: cts, seed }
90 }
91}
92
93impl<K, C> Encryptor<[u8], BatchedFheUint8<C>> for K
94where
95 K: Encryptor<[bool], Vec<C>>,
96{
97 fn encrypt(&self, m: &[u8]) -> BatchedFheUint8<C> {
98 let m = m
99 .iter()
100 .flat_map(|v| {
101 (0..8)
102 .into_iter()
103 .map(|i| ((*v >> i) & 1) == 1)
104 .collect_vec()
105 })
106 .collect_vec();
107 let cts = K::encrypt(&self, &m);
108 BatchedFheUint8 { data: cts }
109 }
110}
111
112impl<C> KeySwitchWithId<BatchedFheUint8<C>> for BatchedFheUint8<C>
113where
114 C: KeySwitchWithId<C>,
115{
116 fn key_switch(&self, user_id: usize) -> BatchedFheUint8<C> {
117 let data = self
118 .data
119 .iter()
120 .map(|c| c.key_switch(user_id))
121 .collect_vec();
122 BatchedFheUint8 { data }
123 }
124}
125
126impl<C, K> MultiPartyDecryptor<u8, FheUint8<C>> for K
127where
128 K: MultiPartyDecryptor<bool, C>,
129 <Self as MultiPartyDecryptor<bool, C>>::DecryptionShare: Clone,
130{
131 type DecryptionShare = Vec<<Self as MultiPartyDecryptor<bool, C>>::DecryptionShare>;
132 fn gen_decryption_share(&self, c: &FheUint8<C>) -> Self::DecryptionShare {
133 assert!(c.data().len() == 8);
134 c.data()
135 .iter()
136 .map(|bit_c| {
137 let decryption_share =
138 MultiPartyDecryptor::<bool, C>::gen_decryption_share(self, bit_c);
139 decryption_share
140 })
141 .collect_vec()
142 }
143
144 fn aggregate_decryption_shares(&self, c: &FheUint8<C>, shares: &[Self::DecryptionShare]) -> u8 {
145 let mut out = 0u8;
146
147 (0..8).into_iter().for_each(|i| {
148 // Collect bit i^th decryption share of each party
149 let bit_i_decryption_shares = shares.iter().map(|s| s[i].clone()).collect_vec();
150 let bit_i = MultiPartyDecryptor::<bool, C>::aggregate_decryption_shares(
151 self,
152 &c.data()[i],
153 &bit_i_decryption_shares,
154 );
155
156 if bit_i {
157 out += 1 << i;
158 }
159 });
160
161 out
162 }
163}
164
165impl<C, K> Encryptor<u8, FheUint8<C>> for K
166where
167 K: Encryptor<bool, C>,
168{
169 fn encrypt(&self, m: &u8) -> FheUint8<C> {
170 let cts = (0..8)
171 .into_iter()
172 .map(|i| {
173 let bit = ((m >> i) & 1) == 1;
174 K::encrypt(self, &bit)
175 })
176 .collect_vec();
177 FheUint8 { data: cts }
178 }
179}
180
181impl<K, C> Decryptor<u8, FheUint8<C>> for K
182where
183 K: Decryptor<bool, C>,
184{
185 fn decrypt(&self, c: &FheUint8<C>) -> u8 {
186 assert!(c.data.len() == 8);
187 let mut out = 0u8;
188 c.data().iter().enumerate().for_each(|(index, bit_c)| {
189 let bool = K::decrypt(self, bit_c);
190 if bool {
191 out += 1 << index;
192 }
193 });
194 out
195 }
196}