fancy_garbling/twopac/semihonest/
garbler.rs

1use crate::{
2    AllWire, ArithmeticWire, Fancy, FancyArithmetic, FancyBinary, FancyInput, FancyReveal,
3    Garbler as Gb, WireMod2, errors::TwopacError, wire::WireLabel,
4};
5use rand::{CryptoRng, Rng, SeedableRng};
6use swanky_adversary::SemiHonest;
7use swanky_block::Block;
8use swanky_channel_legacy::AbstractChannel;
9use swanky_ot_traits::Sender as OtSender;
10
11/// Semi-honest garbler.
12pub struct Garbler<C, RNG, OT, Wire> {
13    garbler: Gb<C, RNG, Wire>,
14    ot: OT,
15    rng: RNG,
16}
17
18impl<C, OT, RNG, Wire> std::ops::Deref for Garbler<C, RNG, OT, Wire> {
19    type Target = Gb<C, RNG, Wire>;
20    fn deref(&self) -> &Self::Target {
21        &self.garbler
22    }
23}
24
25impl<C, OT, RNG, Wire> std::ops::DerefMut for Garbler<C, RNG, OT, Wire> {
26    fn deref_mut(&mut self) -> &mut Gb<C, RNG, Wire> {
27        &mut self.garbler
28    }
29}
30
31impl<
32    C: AbstractChannel,
33    RNG: CryptoRng + Rng + SeedableRng<Seed = Block>,
34    OT: OtSender<Msg = Block> + SemiHonest,
35    Wire: WireLabel,
36> Garbler<C, RNG, OT, Wire>
37{
38    /// Make a new `Garbler`.
39    pub fn new(mut channel: C, mut rng: RNG) -> Result<Self, TwopacError> {
40        let ot = OT::init(&mut channel, &mut rng)?;
41
42        let garbler = Gb::new(channel, RNG::from_seed(rng.r#gen()));
43        Ok(Garbler { garbler, ot, rng })
44    }
45
46    /// Get a reference to the internal channel.
47    pub fn get_channel(&mut self) -> &mut C {
48        &mut self.garbler.channel
49    }
50
51    fn _evaluator_input(&mut self, delta: &Wire, q: u16) -> (Wire, Vec<(Block, Block)>) {
52        let len = f32::from(q).log(2.0).ceil() as u16;
53        let mut wire = Wire::zero(q);
54        let inputs = (0..len)
55            .map(|i| {
56                let zero = Wire::rand(&mut self.rng, q);
57                let one = zero.plus(delta);
58                wire = wire.plus(&zero.cmul(1 << i));
59                (zero.as_block(), one.as_block())
60            })
61            .collect::<Vec<(Block, Block)>>();
62        (wire, inputs)
63    }
64}
65
66impl<
67    C: AbstractChannel,
68    RNG: CryptoRng + Rng + SeedableRng<Seed = Block>,
69    OT: OtSender<Msg = Block> + SemiHonest,
70    Wire: WireLabel,
71> FancyInput for Garbler<C, RNG, OT, Wire>
72{
73    type Item = Wire;
74    type Error = TwopacError;
75
76    fn encode(&mut self, val: u16, modulus: u16) -> Result<Wire, TwopacError> {
77        let (mine, theirs) = self.garbler.encode_wire(val, modulus);
78        self.garbler.send_wire(&theirs)?;
79        self.channel.flush()?;
80        Ok(mine)
81    }
82
83    fn encode_many(&mut self, vals: &[u16], moduli: &[u16]) -> Result<Vec<Wire>, TwopacError> {
84        let ws = vals
85            .iter()
86            .zip(moduli.iter())
87            .map(|(x, q)| {
88                let (mine, theirs) = self.garbler.encode_wire(*x, *q);
89                self.garbler.send_wire(&theirs)?;
90                Ok(mine)
91            })
92            .collect();
93        self.channel.flush()?;
94        ws
95    }
96
97    fn receive_many(&mut self, qs: &[u16]) -> Result<Vec<Wire>, TwopacError> {
98        self.channel.flush()?;
99        let n = qs.len();
100        let lens = qs.iter().map(|q| f32::from(*q).log(2.0).ceil() as usize);
101        let mut wires = Vec::with_capacity(n);
102        let mut inputs = Vec::with_capacity(lens.sum());
103
104        for q in qs.iter() {
105            let delta = self.garbler.delta(*q);
106            let (wire, input) = self._evaluator_input(&delta, *q);
107            wires.push(wire);
108            for i in input.into_iter() {
109                inputs.push(i);
110            }
111        }
112        self.ot
113            .send(&mut self.garbler.channel, &inputs, &mut self.rng)?;
114        Ok(wires)
115    }
116}
117
118impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT> FancyBinary for Garbler<C, RNG, OT, WireMod2> {
119    fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
120        self.garbler.negate(x).map_err(Self::Error::from)
121    }
122
123    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
124        self.garbler.xor(x, y).map_err(Self::Error::from)
125    }
126
127    fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
128        self.garbler.and(x, y).map_err(Self::Error::from)
129    }
130}
131
132impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT> FancyBinary for Garbler<C, RNG, OT, AllWire> {
133    fn negate(&mut self, x: &Self::Item) -> Result<Self::Item, Self::Error> {
134        self.garbler.negate(x).map_err(Self::Error::from)
135    }
136
137    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
138        self.garbler.xor(x, y).map_err(Self::Error::from)
139    }
140
141    fn and(&mut self, x: &Self::Item, y: &Self::Item) -> Result<Self::Item, Self::Error> {
142        self.garbler.and(x, y).map_err(Self::Error::from)
143    }
144}
145
146impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT, Wire: WireLabel + ArithmeticWire> FancyArithmetic
147    for Garbler<C, RNG, OT, Wire>
148{
149    fn add(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
150        self.garbler.add(x, y).map_err(Self::Error::from)
151    }
152
153    fn sub(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
154        self.garbler.sub(x, y).map_err(Self::Error::from)
155    }
156
157    fn cmul(&mut self, x: &Wire, c: u16) -> Result<Self::Item, Self::Error> {
158        self.garbler.cmul(x, c).map_err(Self::Error::from)
159    }
160
161    fn mul(&mut self, x: &Wire, y: &Wire) -> Result<Self::Item, Self::Error> {
162        self.garbler.mul(x, y).map_err(Self::Error::from)
163    }
164
165    fn proj(&mut self, x: &Wire, q: u16, tt: Option<Vec<u16>>) -> Result<Self::Item, Self::Error> {
166        self.garbler.proj(x, q, tt).map_err(Self::Error::from)
167    }
168}
169
170impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT, Wire: WireLabel> Fancy
171    for Garbler<C, RNG, OT, Wire>
172{
173    type Item = Wire;
174    type Error = TwopacError;
175
176    fn constant(&mut self, x: u16, q: u16) -> Result<Self::Item, Self::Error> {
177        self.garbler.constant(x, q).map_err(Self::Error::from)
178    }
179
180    fn output(&mut self, x: &Self::Item) -> Result<Option<u16>, Self::Error> {
181        self.garbler.output(x).map_err(Self::Error::from)
182    }
183}
184
185impl<C: AbstractChannel, RNG: CryptoRng + Rng, OT, Wire: WireLabel> FancyReveal
186    for Garbler<C, RNG, OT, Wire>
187{
188    fn reveal(&mut self, x: &Self::Item) -> Result<u16, Self::Error> {
189        self.garbler.reveal(x).map_err(Self::Error::from)
190    }
191}
192
193impl<C, RNG, OT, Wire> SemiHonest for Garbler<C, RNG, OT, Wire> {}