Skip to main content

primitives/sharing/authenticated/
field_key.rs

1use std::{
2    ops::{Add, AddAssign, Deref, Mul, MulAssign, Neg, Sub, SubAssign},
3    sync::Arc,
4};
5
6use rand::{distributions::Standard, prelude::Distribution, Rng};
7use serde::{Deserialize, Serialize};
8use subtle::{Choice, ConstantTimeEq};
9
10use super::OpenFieldShare;
11use crate::{
12    algebra::field::{FieldElement, FieldExtension, SubfieldElement},
13    errors::PrimitiveError,
14    random::{CryptoRngCore, Random, RandomWith},
15    types::ConditionallySelectable,
16};
17
18/// α, a global authentication key for field shares. Each party holds a
19/// global key α for each peer, and uses that α to authenticate all its field shares
20/// (alongside a local key β).
21#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
22#[serde(bound = "F: FieldExtension")]
23pub struct GlobalFieldKey<F: FieldExtension>(pub Arc<FieldElement<F>>);
24
25impl<F: FieldExtension> GlobalFieldKey<F> {
26    #[inline]
27    pub fn new(value: FieldElement<F>) -> Self {
28        GlobalFieldKey(Arc::new(value))
29    }
30}
31
32impl<F: FieldExtension> ConditionallySelectable for GlobalFieldKey<F> {
33    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
34        GlobalFieldKey(Arc::new(FieldElement::conditional_select(
35            &a.0, &b.0, choice,
36        )))
37    }
38}
39
40impl<F: FieldExtension> Deref for GlobalFieldKey<F> {
41    type Target = FieldElement<F>;
42
43    #[inline]
44    fn deref(&self) -> &Self::Target {
45        self.0.deref()
46    }
47}
48
49impl<F: FieldExtension> From<Arc<FieldElement<F>>> for GlobalFieldKey<F> {
50    #[inline]
51    fn from(value: Arc<FieldElement<F>>) -> Self {
52        GlobalFieldKey(value)
53    }
54}
55
56impl<F: FieldExtension> From<FieldElement<F>> for GlobalFieldKey<F> {
57    #[inline]
58    fn from(value: FieldElement<F>) -> Self {
59        GlobalFieldKey(Arc::new(value))
60    }
61}
62
63// -------------------------
64// |   Random Generation   |
65// -------------------------
66
67impl<F: FieldExtension> Distribution<GlobalFieldKey<F>> for Standard {
68    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> GlobalFieldKey<F> {
69        GlobalFieldKey::new(Standard.sample(rng))
70    }
71}
72
73impl<F: FieldExtension> RandomWith<usize> for Vec<Vec<GlobalFieldKey<F>>> {
74    /// Generates `n_parties` vectors of `n_parties - 1` global keys each.
75    fn random_with(mut rng: impl CryptoRngCore, n_parties: usize) -> Self {
76        (0..n_parties)
77            .map(|_| GlobalFieldKey::<F>::random_n(&mut rng, n_parties - 1))
78            .collect()
79    }
80}
81
82// α and β, such that MAC(x) = α · x + β
83// In the context of VOLE, this corresponds to w = Δ · u + v
84#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
85#[serde(bound = "F: FieldExtension")]
86pub struct FieldShareKey<F>
87where
88    F: FieldExtension,
89{
90    pub(crate) alpha: GlobalFieldKey<F>, // α, global key
91    pub(crate) beta: FieldElement<F>,    // β, a local key per shared value.
92}
93
94impl<F: FieldExtension> FieldShareKey<F> {
95    #[inline]
96    pub fn new(alpha: GlobalFieldKey<F>, beta: FieldElement<F>) -> Self {
97        FieldShareKey { alpha, beta }
98    }
99
100    #[inline]
101    pub fn get_alpha(&self) -> GlobalFieldKey<F> {
102        self.alpha.clone()
103    }
104
105    #[inline]
106    pub fn get_alpha_value(&self) -> FieldElement<F> {
107        *self.alpha
108    }
109
110    #[inline]
111    pub fn get_beta(&self) -> &FieldElement<F> {
112        &self.beta
113    }
114
115    /* === Verification === */
116
117    #[inline]
118    pub fn compute_mac(&self, value: &SubfieldElement<F>) -> FieldElement<F> {
119        self.beta + *self.alpha * value
120    }
121
122    #[inline]
123    pub fn verify_mac(&self, open_share: &OpenFieldShare<F>) -> Result<(), PrimitiveError> {
124        let expected_mac = self.compute_mac(&open_share.value);
125        bool::from(FieldElement::ct_eq(&expected_mac, &open_share.mac))
126            .then_some(())
127            .ok_or_else(|| {
128                PrimitiveError::WrongMAC(
129                    serde_json::to_string(&expected_mac).unwrap(),
130                    serde_json::to_string(&open_share.mac).unwrap(),
131                )
132            })
133    }
134}
135
136// -------------------------
137// |   Random Generation   |
138// -------------------------
139
140impl<F: FieldExtension> Random for FieldShareKey<F> {
141    fn random(mut rng: impl CryptoRngCore) -> Self {
142        FieldShareKey {
143            alpha: GlobalFieldKey::random(&mut rng),
144            beta: FieldElement::random(&mut rng),
145        }
146    }
147}
148
149impl<F: FieldExtension> RandomWith<GlobalFieldKey<F>> for FieldShareKey<F> {
150    fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalFieldKey<F>) -> Self {
151        FieldShareKey {
152            alpha,
153            beta: FieldElement::random(&mut rng),
154        }
155    }
156}
157
158// --------------
159// | Arithmetic |
160// --------------
161
162// === Addition === //
163
164#[macros::op_variants(owned, borrowed, flipped_commutative)]
165impl<F: FieldExtension> Add<&FieldShareKey<F>> for FieldShareKey<F> {
166    type Output = FieldShareKey<F>;
167
168    #[inline]
169    fn add(mut self, other: &FieldShareKey<F>) -> Self::Output {
170        assert_eq!(self.alpha, other.alpha);
171        self.beta += &other.beta;
172        self
173    }
174}
175
176#[macros::op_variants(owned)]
177impl<'a, F: FieldExtension> AddAssign<&'a FieldShareKey<F>> for FieldShareKey<F> {
178    #[inline]
179    fn add_assign(&mut self, other: &'a FieldShareKey<F>) {
180        assert_eq!(self.alpha, other.alpha);
181        self.beta += &other.beta;
182    }
183}
184
185// === Subtraction === //
186
187#[macros::op_variants(owned, borrowed, flipped)]
188impl<F: FieldExtension> Sub<&FieldShareKey<F>> for FieldShareKey<F> {
189    type Output = FieldShareKey<F>;
190
191    #[inline]
192    fn sub(mut self, other: &FieldShareKey<F>) -> Self::Output {
193        assert_eq!(self.alpha, other.alpha);
194        self.beta -= other.beta;
195        self
196    }
197}
198
199#[macros::op_variants(owned)]
200impl<'a, F: FieldExtension> SubAssign<&'a FieldShareKey<F>> for FieldShareKey<F> {
201    #[inline]
202    fn sub_assign(&mut self, other: &'a FieldShareKey<F>) {
203        assert_eq!(self.alpha, other.alpha);
204        self.beta -= &other.beta;
205    }
206}
207
208// === One-to-many multiplication === //
209
210#[macros::op_variants(owned, borrowed, flipped)]
211impl<'a, F: FieldExtension> Mul<&'a FieldElement<F>> for FieldShareKey<F> {
212    type Output = FieldShareKey<F>;
213
214    #[inline]
215    fn mul(mut self, other: &'a FieldElement<F>) -> Self::Output {
216        self.beta *= other;
217        self
218    }
219}
220
221#[macros::op_variants(owned, borrowed, flipped)]
222impl<'a, F: FieldExtension> Mul<&'a SubfieldElement<F>> for FieldShareKey<F> {
223    type Output = FieldShareKey<F>;
224
225    #[inline]
226    fn mul(mut self, other: &'a SubfieldElement<F>) -> Self::Output {
227        self.beta *= other;
228        self
229    }
230}
231
232#[macros::op_variants(owned)]
233impl<'a, F: FieldExtension> MulAssign<&'a FieldElement<F>> for FieldShareKey<F> {
234    #[inline]
235    fn mul_assign(&mut self, other: &'a FieldElement<F>) {
236        self.beta *= other;
237    }
238}
239
240#[macros::op_variants(owned)]
241impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for FieldShareKey<F> {
242    #[inline]
243    fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
244        self.beta *= other;
245    }
246}
247
248// === Negation === //
249
250#[macros::op_variants(borrowed)]
251impl<F: FieldExtension> Neg for FieldShareKey<F> {
252    type Output = FieldShareKey<F>;
253
254    #[inline]
255    fn neg(self) -> Self::Output {
256        FieldShareKey {
257            alpha: self.alpha,
258            beta: -self.beta,
259        }
260    }
261}
262
263// === Constant Addition === //
264
265impl<F: FieldExtension> FieldShareKey<F> {
266    #[inline]
267    pub fn add_secret_owned(mut self, constant: FieldElement<F>) -> Result<Self, PrimitiveError> {
268        self.beta -= constant * *self.alpha;
269        Ok(self)
270    }
271
272    #[inline]
273    pub fn add_secret(&self, constant: FieldElement<F>) -> Result<Self, PrimitiveError> {
274        let mut result = self.clone();
275        result.beta -= constant * *result.alpha;
276        Ok(result)
277    }
278}
279
280// ---------------------------------------
281// |  Constant time Selection / Equality |
282// ---------------------------------------
283
284impl<F: FieldExtension> ConstantTimeEq for FieldShareKey<F> {
285    #[inline]
286    fn ct_eq(&self, other: &Self) -> Choice {
287        self.alpha.ct_eq(&other.alpha) & self.beta.ct_eq(&other.beta)
288    }
289}
290
291impl<F: FieldExtension> FieldShareKey<F> {
292    #[inline]
293    pub fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
294        FieldShareKey {
295            alpha: GlobalFieldKey::conditional_select(&a.alpha, &b.alpha, choice),
296            beta: FieldElement::conditional_select(&a.beta, &b.beta, choice),
297        }
298    }
299}
300
301#[cfg(test)]
302mod tests {
303
304    use super::*;
305    use crate::algebra::elliptic_curve::{Curve25519Ristretto, ScalarAsExtension};
306
307    pub type Fq = ScalarAsExtension<Curve25519Ristretto>;
308    #[test]
309    fn test_addition() {
310        let alpha = GlobalFieldKey::new(Fq::from(3u32));
311        let key1 = FieldShareKey {
312            alpha: alpha.clone(),
313            beta: Fq::from(10u32),
314        };
315        let key2 = FieldShareKey {
316            alpha: alpha.clone(),
317            beta: Fq::from(7u32),
318        };
319        let expected_result = FieldShareKey {
320            alpha,
321            beta: Fq::from(17u32),
322        };
323        assert_eq!(key1 + key2, expected_result);
324    }
325
326    #[test]
327    fn test_subtraction() {
328        let alpha = GlobalFieldKey::new(Fq::from(3u32));
329        let key1 = FieldShareKey {
330            alpha: alpha.clone(),
331            beta: Fq::from(10u32),
332        };
333        let key2 = FieldShareKey {
334            alpha: alpha.clone(),
335            beta: Fq::from(7u32),
336        };
337        let expected_result = FieldShareKey {
338            alpha,
339            beta: Fq::from(3u32),
340        };
341        assert_eq!(key1 - key2, expected_result);
342    }
343
344    #[test]
345    fn test_multiplication() {
346        let alpha = GlobalFieldKey::new(Fq::from(3u32));
347        let key = FieldShareKey {
348            alpha: alpha.clone(),
349            beta: Fq::from(10u32),
350        };
351        let scalar = Fq::from(3u32);
352        let expected_result = FieldShareKey {
353            alpha,
354            beta: Fq::from(30u32),
355        };
356        assert_eq!(key * scalar, expected_result);
357    }
358
359    #[test]
360    fn test_negation() {
361        let key = FieldShareKey {
362            alpha: GlobalFieldKey::new(Fq::from(5u32)),
363            beta: Fq::from(10u32),
364        };
365        let expected_result = FieldShareKey {
366            alpha: GlobalFieldKey::new(Fq::from(5u32)),
367            beta: -Fq::from(10u32),
368        };
369        assert_eq!(-key, expected_result);
370    }
371}