fancy_garbling/wire/
mod2.rs1use crate::{HasModulus, WireLabel};
2use rand::{CryptoRng, Rng, RngCore};
3use subtle::ConditionallySelectable;
4use vectoreyes::{SimdBase, U8x16};
5
6impl HasModulus for WireMod2 {
7 fn modulus(&self) -> u16 {
8 2
9 }
10}
11
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14#[derive(Debug, Clone, Copy, PartialEq, Default)]
15pub struct WireMod2 {
16 pub(crate) val: U8x16,
18}
19
20impl core::ops::Add for WireMod2 {
21 type Output = Self;
22
23 #[allow(clippy::suspicious_arithmetic_impl)]
24 fn add(self, rhs: Self) -> Self::Output {
25 Self {
26 val: self.val ^ rhs.val,
27 }
28 }
29}
30
31impl core::ops::AddAssign for WireMod2 {
32 #[allow(clippy::suspicious_op_assign_impl)]
33 fn add_assign(&mut self, rhs: Self) {
34 self.val ^= rhs.val;
35 }
36}
37
38impl core::ops::Sub for WireMod2 {
39 type Output = Self;
40
41 fn sub(self, rhs: Self) -> Self::Output {
42 self + -rhs
43 }
44}
45
46impl core::ops::SubAssign for WireMod2 {
47 fn sub_assign(&mut self, rhs: Self) {
48 *self = *self - rhs;
49 }
50}
51
52impl core::ops::Neg for WireMod2 {
53 type Output = Self;
54
55 fn neg(self) -> Self::Output {
56 self
58 }
59}
60
61impl core::ops::Mul<u16> for WireMod2 {
62 type Output = Self;
63
64 fn mul(self, rhs: u16) -> Self::Output {
65 if rhs & 1 == 0 {
66 Self {
67 val: Default::default(),
68 }
69 } else {
70 self
71 }
72 }
73}
74
75impl core::ops::MulAssign<u16> for WireMod2 {
76 fn mul_assign(&mut self, rhs: u16) {
77 if rhs & 1 == 0 {
78 self.val = Default::default();
79 }
80 }
81}
82
83impl ConditionallySelectable for WireMod2 {
84 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
85 WireMod2::from_repr(
86 U8x16::conditional_select(&a.to_repr(), &b.to_repr(), choice),
87 2,
88 )
89 }
90}
91
92impl WireLabel for WireMod2 {
93 fn rand_delta<R: CryptoRng + RngCore>(rng: &mut R, q: u16) -> Self {
94 if q != 2 {
95 panic!("[WireMod2::rand_delta] Expected modulo 2. Got {}", q);
96 }
97 let mut w = Self::rand(rng, q);
98 w.val |= U8x16::set_lo(1);
99 w
100 }
101
102 fn digits(&self) -> Vec<u16> {
103 (0..128)
104 .map(|i| ((u128::from(self.val) >> i) as u16) & 1)
105 .collect()
106 }
107
108 fn to_repr(&self) -> U8x16 {
109 self.val
113 }
114
115 fn color(&self) -> u16 {
116 (self.val.extract::<0>() & 1) as u16
118 }
119
120 fn from_repr(inp: U8x16, q: u16) -> Self {
121 if q != 2 {
125 panic!("[WireMod2::from_block] Expected modulo 2. Got {}", q);
126 }
127 Self { val: inp }
128 }
129
130 fn zero(q: u16) -> Self {
131 if q != 2 {
132 panic!("[WireMod2::zero] Expected modulo 2. Got {}", q);
133 }
134 Self::default()
135 }
136
137 fn rand<R: CryptoRng + RngCore>(rng: &mut R, q: u16) -> Self {
138 if q != 2 {
139 panic!("[WireMod2::rand] Expected modulo 2. Got {}", q);
140 }
141
142 Self { val: rng.r#gen() }
143 }
144
145 fn hash_to_mod(hash: U8x16, q: u16) -> Self {
146 if q != 2 {
147 panic!("[WireMod2::hash_to_mod] Expected modulo 2. Got {}", q);
148 }
149 Self::from_repr(hash, q)
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 #[cfg(feature = "serde")]
156 #[test]
157 fn test_serialize_mod2() {
158 use crate::{WireLabel, WireMod2};
159 use rand::thread_rng;
160
161 let mut rng = thread_rng();
162 let w = WireMod2::rand(&mut rng, 2);
163 let serialized = serde_json::to_string(&w).unwrap();
164
165 let deserialized: WireMod2 = serde_json::from_str(&serialized).unwrap();
166
167 assert_eq!(w, deserialized);
168 }
169}