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 to_repr(&self) -> U8x16 {
103 self.val
107 }
108
109 fn color(&self) -> u16 {
110 (self.val.extract::<0>() & 1) as u16
112 }
113
114 fn from_repr(inp: U8x16, q: u16) -> Self {
115 if q != 2 {
119 panic!("[WireMod2::from_block] Expected modulo 2. Got {}", q);
120 }
121 Self { val: inp }
122 }
123
124 fn rand<R: CryptoRng + RngCore>(rng: &mut R, q: u16) -> Self {
125 if q != 2 {
126 panic!("[WireMod2::rand] Expected modulo 2. Got {}", q);
127 }
128
129 Self { val: rng.r#gen() }
130 }
131
132 fn hash_to_mod(hash: U8x16, q: u16) -> Self {
133 if q != 2 {
134 panic!("[WireMod2::hash_to_mod] Expected modulo 2. Got {}", q);
135 }
136 Self::from_repr(hash, q)
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 #[cfg(feature = "serde")]
143 #[test]
144 fn test_serialize_mod2() {
145 use crate::{WireLabel, WireMod2};
146 use rand::thread_rng;
147
148 let mut rng = thread_rng();
149 let w = WireMod2::rand(&mut rng, 2);
150 let serialized = serde_json::to_string(&w).unwrap();
151
152 let deserialized: WireMod2 = serde_json::from_str(&serialized).unwrap();
153
154 assert_eq!(w, deserialized);
155 }
156}