fancy_garbling/
classic.rs1use crate::{
5 Fancy, WireLabel,
6 circuit::CircuitExecutor,
7 garble::{Evaluator, Garbler},
8 util::output_tweak,
9};
10use rand::{CryptoRng, RngCore};
11use std::collections::HashMap;
12use swanky_channel::Channel;
13use swanky_error::ErrorKind;
14use vectoreyes::U8x16;
15
16#[derive(Debug)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct GarbledCircuit {
23 blocks: Vec<U8x16>,
24}
25
26impl GarbledCircuit {
27 pub fn new(blocks: Vec<U8x16>) -> Self {
30 GarbledCircuit { blocks }
31 }
32
33 pub fn size(&self) -> usize {
35 self.blocks.len()
36 }
37
38 pub fn garble<
46 Wire: WireLabel,
47 Ex: CircuitExecutor<Garbler<RNG, Wire>>,
48 RNG: CryptoRng + RngCore,
49 >(
50 c: &Ex,
51 rng: RNG,
52 ) -> swanky_error::Result<(Encoder<Wire>, Self, OutputMapping)> {
53 let mut channel = GarbledChannel::new_writer(None);
54 let mut garbler = Channel::with(&mut channel, |channel| Garbler::new(rng, channel))?;
55
56 let inputs = (0..c.ninputs())
58 .map(|i| {
59 let q = c.modulus(i);
60 garbler.encode_zero(q)
61 })
62 .collect::<Vec<_>>();
63
64 let zeros = Channel::with(&mut channel, |channel| {
65 let zeros = c.execute(&mut garbler, &inputs, channel)?;
68 garbler.outputs(&zeros, channel)?;
73 Ok(zeros)
74 })?;
75
76 let deltas = garbler.get_deltas();
77 let en = Encoder::new(inputs, deltas.clone());
78 let gc = GarbledCircuit::new(channel.finish_writing());
79 let output_mapping = OutputMapping::new(&zeros, &deltas);
80
81 Ok((en, gc, output_mapping))
82 }
83
84 pub fn eval<Wire: WireLabel, Ex: CircuitExecutor<Evaluator<Wire>>>(
87 &self,
88 c: &Ex,
89 inputs: &[Wire],
90 output_mapping: &OutputMapping,
91 ) -> swanky_error::Result<Vec<u16>> {
92 let wirelabels = self.eval_to_wirelabels(c, inputs)?;
93 output_mapping.to_outputs(&wirelabels)
94 }
95
96 pub fn eval_to_wirelabels<Wire: WireLabel, Ex: CircuitExecutor<Evaluator<Wire>>>(
99 &self,
100 c: &Ex,
101 inputs: &[Wire],
102 ) -> swanky_error::Result<Vec<Wire>> {
103 let wirelabels = Channel::with(GarbledChannel::from(self), |channel| {
104 let mut evaluator = Evaluator::new(channel)?;
105 let wirelabels = c.execute(&mut evaluator, inputs, channel)?;
106 Ok(wirelabels)
107 })?;
108 Ok(wirelabels)
109 }
110}
111
112#[derive(Debug)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118pub struct Encoder<Wire> {
119 inputs: Vec<Wire>,
120 deltas: HashMap<u16, Wire>,
121}
122
123impl<Wire: WireLabel> Encoder<Wire> {
124 pub fn new(inputs: Vec<Wire>, deltas: HashMap<u16, Wire>) -> Self {
127 Encoder { inputs, deltas }
128 }
129
130 pub fn encode_inputs(&self, inputs: &[u16]) -> Vec<Wire> {
136 assert_eq!(inputs.len(), self.inputs.len());
137 self.inputs
138 .iter()
139 .zip(inputs)
140 .map(|(zero, x)| {
141 let q = zero.modulus();
142 zero.clone() + self.deltas[&q].clone() * *x
143 })
144 .collect()
145 }
146}
147
148#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150pub struct OutputMapping(Vec<Vec<U8x16>>);
151
152impl OutputMapping {
153 pub fn new<Wire: WireLabel>(zeros: &[Wire], deltas: &HashMap<u16, Wire>) -> Self {
156 let mut outputs = Vec::with_capacity(zeros.len());
157 for (i, zero) in zeros.iter().enumerate() {
158 let q = zero.modulus();
159 let mut wirelabels = Vec::with_capacity(q as usize);
160 for k in 0..q {
161 let wirelabel = zero.clone() + deltas[&q].clone() * k;
162 let hashed = wirelabel.hash(output_tweak(i, k));
163 wirelabels.push(hashed);
164 }
165 outputs.push(wirelabels);
166 }
167 Self(outputs)
168 }
169
170 pub fn to_outputs<Wire: WireLabel>(
176 &self,
177 wirelabels: &[Wire],
178 ) -> swanky_error::Result<Vec<u16>> {
179 let mut outputs = Vec::new();
180 for (i, wirelabel) in wirelabels.iter().enumerate() {
181 let q = wirelabel.modulus();
182 let mut decoded = None;
183 for k in 0..q {
184 let hashed = wirelabel.hash(output_tweak(i, k));
185 if hashed == self.0[i][k as usize] {
186 decoded = Some(k);
187 break;
188 }
189 }
190 if let Some(output) = decoded {
191 outputs.push(output);
192 } else {
193 swanky_error::bail!(ErrorKind::OtherError, "Decoding failed");
194 }
195 }
196 Ok(outputs)
197 }
198}
199
200pub struct GarbledChannel {
215 reader: Option<GarbledReader>,
216 writer: Option<GarbledWriter>,
217}
218
219impl GarbledChannel {
220 pub fn new_writer(ngates: Option<usize>) -> Self {
222 Self {
223 reader: None,
224 writer: Some(GarbledWriter::new(ngates)),
225 }
226 }
227
228 pub fn finish_writing(self) -> Vec<U8x16> {
233 self.writer.unwrap().finish()
234 }
235}
236
237impl std::io::Read for GarbledChannel {
238 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
239 let reader = self.reader.as_mut().unwrap();
240 reader.read(buf)
241 }
242}
243
244impl std::io::Write for GarbledChannel {
245 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
246 let writer = self.writer.as_mut().unwrap();
247 writer.write(buf)
248 }
249
250 fn flush(&mut self) -> std::io::Result<()> {
251 let writer = self.writer.as_mut().unwrap();
252 writer.flush()
253 }
254}
255
256impl From<&GarbledCircuit> for GarbledChannel {
257 fn from(value: &GarbledCircuit) -> Self {
258 Self {
259 reader: Some(GarbledReader::new(&value.blocks)),
260 writer: None,
261 }
262 }
263}
264
265#[derive(Debug)]
267struct GarbledReader {
268 blocks: Vec<U8x16>,
269 index: usize,
270}
271
272impl GarbledReader {
273 fn new(blocks: &[U8x16]) -> Self {
274 Self {
275 blocks: blocks.to_vec(),
276 index: 0,
277 }
278 }
279}
280
281impl std::io::Read for GarbledReader {
282 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
283 assert_eq!(buf.len() % 16, 0);
284 let start = self.index;
285 for data in buf.chunks_mut(16) {
286 let block: [u8; 16] = self.blocks[self.index].into();
287 for (a, b) in data.iter_mut().zip(block.iter()) {
288 *a = *b;
289 }
290 self.index += 1;
291 if self.index == self.blocks.len() {
292 return Ok(16 * (self.index - start));
296 }
297 }
298 Ok(buf.len())
299 }
300}
301
302#[derive(Debug)]
304struct GarbledWriter {
305 blocks: Vec<U8x16>,
306}
307
308impl GarbledWriter {
309 fn new(ngates: Option<usize>) -> Self {
311 let blocks = if let Some(n) = ngates {
312 Vec::with_capacity(2 * n)
313 } else {
314 Vec::new()
315 };
316 Self { blocks }
317 }
318
319 fn finish(self) -> Vec<U8x16> {
321 self.blocks
322 }
323}
324
325impl std::io::Write for GarbledWriter {
326 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
327 for item in buf.chunks(16) {
328 let bytes: [u8; 16] = match item.try_into() {
329 Ok(bytes) => bytes,
330 Err(_) => {
331 return Err(std::io::Error::new(
332 std::io::ErrorKind::InvalidData,
333 "unable to map bytes to block",
334 ));
335 }
336 };
337 self.blocks.push(bytes.into());
338 }
339 Ok(buf.len())
340 }
341 fn flush(&mut self) -> std::io::Result<()> {
342 Ok(())
343 }
344}