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(PrimitiveError::WrongMAC(
128                serde_json::to_string(&expected_mac).unwrap(),
129                serde_json::to_string(&open_share.mac).unwrap(),
130            ))
131    }
132}
133
134// -------------------------
135// |   Random Generation   |
136// -------------------------
137
138impl<F: FieldExtension> Random for FieldShareKey<F> {
139    fn random(mut rng: impl CryptoRngCore) -> Self {
140        FieldShareKey {
141            alpha: GlobalFieldKey::random(&mut rng),
142            beta: FieldElement::random(&mut rng),
143        }
144    }
145}
146
147impl<F: FieldExtension> RandomWith<GlobalFieldKey<F>> for FieldShareKey<F> {
148    fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalFieldKey<F>) -> Self {
149        FieldShareKey {
150            alpha,
151            beta: FieldElement::random(&mut rng),
152        }
153    }
154}
155
156// --------------
157// | Arithmetic |
158// --------------
159
160// === Addition === //
161
162#[macros::op_variants(owned, borrowed, flipped_commutative)]
163impl<F: FieldExtension> Add<&FieldShareKey<F>> for FieldShareKey<F> {
164    type Output = FieldShareKey<F>;
165
166    #[inline]
167    fn add(mut self, other: &FieldShareKey<F>) -> Self::Output {
168        assert_eq!(self.alpha, other.alpha);
169        self.beta += &other.beta;
170        self
171    }
172}
173
174#[macros::op_variants(owned)]
175impl<'a, F: FieldExtension> AddAssign<&'a FieldShareKey<F>> for FieldShareKey<F> {
176    #[inline]
177    fn add_assign(&mut self, other: &'a FieldShareKey<F>) {
178        assert_eq!(self.alpha, other.alpha);
179        self.beta += &other.beta;
180    }
181}
182
183// === Subtraction === //
184
185#[macros::op_variants(owned, borrowed, flipped)]
186impl<F: FieldExtension> Sub<&FieldShareKey<F>> for FieldShareKey<F> {
187    type Output = FieldShareKey<F>;
188
189    #[inline]
190    fn sub(mut self, other: &FieldShareKey<F>) -> Self::Output {
191        assert_eq!(self.alpha, other.alpha);
192        self.beta -= other.beta;
193        self
194    }
195}
196
197#[macros::op_variants(owned)]
198impl<'a, F: FieldExtension> SubAssign<&'a FieldShareKey<F>> for FieldShareKey<F> {
199    #[inline]
200    fn sub_assign(&mut self, other: &'a FieldShareKey<F>) {
201        assert_eq!(self.alpha, other.alpha);
202        self.beta -= &other.beta;
203    }
204}
205
206// === One-to-many multiplication === //
207
208#[macros::op_variants(owned, borrowed, flipped)]
209impl<'a, F: FieldExtension> Mul<&'a FieldElement<F>> for FieldShareKey<F> {
210    type Output = FieldShareKey<F>;
211
212    #[inline]
213    fn mul(mut self, other: &'a FieldElement<F>) -> Self::Output {
214        self.beta *= other;
215        self
216    }
217}
218
219#[macros::op_variants(owned, borrowed, flipped)]
220impl<'a, F: FieldExtension> Mul<&'a SubfieldElement<F>> for FieldShareKey<F> {
221    type Output = FieldShareKey<F>;
222
223    #[inline]
224    fn mul(mut self, other: &'a SubfieldElement<F>) -> Self::Output {
225        self.beta *= other;
226        self
227    }
228}
229
230#[macros::op_variants(owned)]
231impl<'a, F: FieldExtension> MulAssign<&'a FieldElement<F>> for FieldShareKey<F> {
232    #[inline]
233    fn mul_assign(&mut self, other: &'a FieldElement<F>) {
234        self.beta *= other;
235    }
236}
237
238#[macros::op_variants(owned)]
239impl<'a, F: FieldExtension> MulAssign<&'a SubfieldElement<F>> for FieldShareKey<F> {
240    #[inline]
241    fn mul_assign(&mut self, other: &'a SubfieldElement<F>) {
242        self.beta *= other;
243    }
244}
245
246// === Negation === //
247
248#[macros::op_variants(borrowed)]
249impl<F: FieldExtension> Neg for FieldShareKey<F> {
250    type Output = FieldShareKey<F>;
251
252    #[inline]
253    fn neg(self) -> Self::Output {
254        FieldShareKey {
255            alpha: self.alpha,
256            beta: -self.beta,
257        }
258    }
259}
260
261// === Constant Addition === //
262
263impl<F: FieldExtension> FieldShareKey<F> {
264    #[inline]
265    pub fn add_secret_owned(mut self, constant: FieldElement<F>) -> Result<Self, PrimitiveError> {
266        self.beta -= constant * *self.alpha;
267        Ok(self)
268    }
269
270    #[inline]
271    pub fn add_secret(&self, constant: FieldElement<F>) -> Result<Self, PrimitiveError> {
272        let mut result = self.clone();
273        result.beta -= constant * *result.alpha;
274        Ok(result)
275    }
276}
277
278// ---------------------------------------
279// |  Constant time Selection / Equality |
280// ---------------------------------------
281
282impl<F: FieldExtension> ConstantTimeEq for FieldShareKey<F> {
283    #[inline]
284    fn ct_eq(&self, other: &Self) -> Choice {
285        self.alpha.ct_eq(&other.alpha) & self.beta.ct_eq(&other.beta)
286    }
287}
288
289impl<F: FieldExtension> FieldShareKey<F> {
290    #[inline]
291    pub fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
292        FieldShareKey {
293            alpha: GlobalFieldKey::conditional_select(&a.alpha, &b.alpha, choice),
294            beta: FieldElement::conditional_select(&a.beta, &b.beta, choice),
295        }
296    }
297}
298
299#[cfg(test)]
300mod tests {
301
302    use super::*;
303    use crate::algebra::elliptic_curve::{Curve25519Ristretto, ScalarAsExtension};
304
305    pub type Fq = ScalarAsExtension<Curve25519Ristretto>;
306    #[test]
307    fn test_addition() {
308        let alpha = GlobalFieldKey::new(Fq::from(3u32));
309        let key1 = FieldShareKey {
310            alpha: alpha.clone(),
311            beta: Fq::from(10u32),
312        };
313        let key2 = FieldShareKey {
314            alpha: alpha.clone(),
315            beta: Fq::from(7u32),
316        };
317        let expected_result = FieldShareKey {
318            alpha,
319            beta: Fq::from(17u32),
320        };
321        assert_eq!(key1 + key2, expected_result);
322    }
323
324    #[test]
325    fn test_subtraction() {
326        let alpha = GlobalFieldKey::new(Fq::from(3u32));
327        let key1 = FieldShareKey {
328            alpha: alpha.clone(),
329            beta: Fq::from(10u32),
330        };
331        let key2 = FieldShareKey {
332            alpha: alpha.clone(),
333            beta: Fq::from(7u32),
334        };
335        let expected_result = FieldShareKey {
336            alpha,
337            beta: Fq::from(3u32),
338        };
339        assert_eq!(key1 - key2, expected_result);
340    }
341
342    #[test]
343    fn test_multiplication() {
344        let alpha = GlobalFieldKey::new(Fq::from(3u32));
345        let key = FieldShareKey {
346            alpha: alpha.clone(),
347            beta: Fq::from(10u32),
348        };
349        let scalar = Fq::from(3u32);
350        let expected_result = FieldShareKey {
351            alpha,
352            beta: Fq::from(30u32),
353        };
354        assert_eq!(key * scalar, expected_result);
355    }
356
357    #[test]
358    fn test_negation() {
359        let key = FieldShareKey {
360            alpha: GlobalFieldKey::new(Fq::from(5u32)),
361            beta: Fq::from(10u32),
362        };
363        let expected_result = FieldShareKey {
364            alpha: GlobalFieldKey::new(Fq::from(5u32)),
365            beta: -Fq::from(10u32),
366        };
367        assert_eq!(-key, expected_result);
368    }
369}