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