Skip to main content

primitives/sharing/authenticated/
curve_key.rs

1use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3use serde::{Deserialize, Serialize};
4use subtle::{Choice, ConstantTimeEq};
5
6use super::{GlobalFieldKey, ScalarKey};
7use crate::{
8    algebra::elliptic_curve::{Curve, Point, Scalar, ScalarAsExtension, ScalarField},
9    errors::PrimitiveError,
10    random::{CryptoRngCore, Random, RandomWith},
11    sharing::OpenPointShare,
12    types::ConditionallySelectable,
13};
14
15pub type GlobalCurveKey<C> = GlobalFieldKey<ScalarField<C>>;
16
17// α and β, such that MAC(x) = α · x + β
18// In the context of VOLE, this corresponds to w = Δ · u + v
19#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(bound = "C: Curve")]
21pub struct CurveKey<C: Curve> {
22    pub(crate) alpha: GlobalCurveKey<C>,
23    pub(crate) beta: Point<C>,
24}
25
26impl<C: Curve> CurveKey<C> {
27    pub fn new(alpha: GlobalCurveKey<C>, beta: Point<C>) -> Self {
28        CurveKey { alpha, beta }
29    }
30
31    pub fn compute_mac(&self, value: &Point<C>) -> Point<C> {
32        self.beta + value * *self.alpha
33    }
34
35    #[inline]
36    pub fn verify_mac(&self, open_share: &OpenPointShare<C>) -> Result<(), PrimitiveError> {
37        let expected_mac = self.compute_mac(&open_share.value);
38        bool::from(expected_mac.ct_eq(&open_share.mac))
39            .then_some(())
40            .ok_or_else(|| {
41                PrimitiveError::WrongMAC(serde_json::to_string(&open_share.mac).unwrap())
42            })
43    }
44
45    pub fn get_alpha(&self) -> GlobalCurveKey<C> {
46        self.alpha.clone()
47    }
48
49    pub fn get_alpha_value(&self) -> ScalarAsExtension<C> {
50        *self.alpha
51    }
52
53    pub fn get_beta(&self) -> Point<C> {
54        self.beta
55    }
56
57    pub fn zero_batch(alphas: Vec<GlobalCurveKey<C>>) -> Vec<CurveKey<C>> {
58        alphas
59            .iter()
60            .map(|alpha| CurveKey::new(alpha.clone(), Point::<C>::identity()))
61            .collect()
62    }
63}
64
65impl<C: Curve> ConditionallySelectable for CurveKey<C> {
66    fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
67        CurveKey {
68            alpha: GlobalCurveKey::<C>::conditional_select(&a.alpha, &b.alpha, choice),
69            beta: Point::conditional_select(&a.beta, &b.beta, choice),
70        }
71    }
72}
73
74// -------------------------
75// |   Random Generation   |
76// -------------------------
77
78impl<C: Curve> Random for CurveKey<C> {
79    fn random(mut rng: impl CryptoRngCore) -> Self {
80        let alpha = GlobalCurveKey::<C>::random(&mut rng);
81        let beta = Point::<C>::random(&mut rng);
82        CurveKey { alpha, beta }
83    }
84}
85
86impl<C: Curve> RandomWith<GlobalCurveKey<C>> for CurveKey<C> {
87    fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalCurveKey<C>) -> Self {
88        CurveKey {
89            alpha,
90            beta: Point::random(&mut rng),
91        }
92    }
93}
94
95// ------------------------------------
96// | Curve Arithmetic Implementations |
97// ------------------------------------
98
99// === Addition === //
100#[macros::op_variants(owned, borrowed, flipped_commutative)]
101impl<'a, C: Curve> Add<&'a CurveKey<C>> for CurveKey<C> {
102    type Output = CurveKey<C>;
103
104    #[inline]
105    fn add(self, other: &'a CurveKey<C>) -> Self::Output {
106        assert_eq!(self.alpha, other.alpha);
107        CurveKey {
108            beta: self.beta + other.beta,
109            ..self
110        }
111    }
112}
113
114#[macros::op_variants(owned)]
115impl<'a, C: Curve> AddAssign<&'a CurveKey<C>> for CurveKey<C> {
116    #[inline]
117    fn add_assign(&mut self, rhs: &'a CurveKey<C>) {
118        assert_eq!(self.alpha, rhs.alpha);
119        self.beta += rhs.beta;
120    }
121}
122
123// === Subtraction === //
124
125#[macros::op_variants(owned, borrowed, flipped)]
126impl<'a, C: Curve> Sub<&'a CurveKey<C>> for CurveKey<C> {
127    type Output = CurveKey<C>;
128
129    #[inline]
130    fn sub(self, other: &'a CurveKey<C>) -> Self::Output {
131        assert_eq!(self.alpha, other.alpha);
132        CurveKey {
133            beta: self.beta - other.beta,
134            ..self
135        }
136    }
137}
138
139// === SubAssign === //
140
141#[macros::op_variants(owned)]
142impl<'a, C: Curve> SubAssign<&'a CurveKey<C>> for CurveKey<C> {
143    #[inline]
144    fn sub_assign(&mut self, rhs: &'a CurveKey<C>) {
145        assert_eq!(self.alpha, rhs.alpha);
146        self.beta -= rhs.beta;
147    }
148}
149
150// === Multiplication === //
151
152#[macros::op_variants(owned, borrowed, flipped)]
153impl<'a, C: Curve> Mul<&'a ScalarAsExtension<C>> for CurveKey<C> {
154    type Output = CurveKey<C>;
155
156    #[inline]
157    fn mul(self, other: &'a ScalarAsExtension<C>) -> Self::Output {
158        CurveKey {
159            beta: self.beta * other,
160            ..self
161        }
162    }
163}
164
165#[macros::op_variants(owned, borrowed, flipped)]
166impl<'a, C: Curve> Mul<&'a Scalar<C>> for CurveKey<C> {
167    type Output = CurveKey<C>;
168
169    #[inline]
170    fn mul(self, other: &'a Scalar<C>) -> Self::Output {
171        CurveKey {
172            beta: self.beta * other,
173            ..self
174        }
175    }
176}
177
178// === MulAssign === //
179
180#[macros::op_variants(owned)]
181impl<'a, C: Curve> MulAssign<&'a ScalarAsExtension<C>> for CurveKey<C> {
182    #[inline]
183    fn mul_assign(&mut self, rhs: &'a ScalarAsExtension<C>) {
184        self.beta *= rhs;
185    }
186}
187
188#[macros::op_variants(owned)]
189impl<'a, C: Curve> MulAssign<&'a Scalar<C>> for CurveKey<C> {
190    #[inline]
191    fn mul_assign(&mut self, rhs: &'a Scalar<C>) {
192        self.beta *= rhs;
193    }
194}
195
196// === Negation === //
197
198#[macros::op_variants(borrowed)]
199impl<C: Curve> Neg for CurveKey<C> {
200    type Output = CurveKey<C>;
201
202    #[inline]
203    fn neg(self) -> Self::Output {
204        CurveKey {
205            alpha: self.alpha,
206            beta: -self.beta,
207        }
208    }
209}
210
211// === Equality === //
212
213impl<C: Curve> ConstantTimeEq for CurveKey<C> {
214    #[inline]
215    fn ct_eq(&self, other: &Self) -> Choice {
216        self.alpha.ct_eq(&other.alpha) & self.beta.ct_eq(&other.beta)
217    }
218}
219
220// === Type conversions === //
221
222impl<C: Curve> From<ScalarKey<C>> for CurveKey<C> {
223    #[inline]
224    fn from(scalar_key: ScalarKey<C>) -> Self {
225        CurveKey {
226            alpha: scalar_key.alpha,
227            beta: scalar_key.beta * Point::<C>::generator(),
228        }
229    }
230}
231
232#[cfg(test)]
233mod tests {
234    use super::*;
235    use crate::algebra::elliptic_curve::Curve25519Ristretto as C;
236
237    pub type FrExt = ScalarAsExtension<C>;
238    pub type P = Point<C>;
239
240    #[test]
241    fn test_addition() {
242        let mut rng = rand::thread_rng();
243        let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
244        let beta1 = P::random(&mut rng);
245        let beta2 = P::random(&mut rng);
246
247        let key1 = CurveKey {
248            alpha: alpha.clone(),
249            beta: beta1,
250        };
251        let key2 = CurveKey {
252            alpha: alpha.clone(),
253            beta: beta2,
254        };
255        let expected_result = CurveKey {
256            alpha,
257            beta: beta1 + beta2,
258        };
259        assert_eq!(key1 + key2, expected_result);
260    }
261
262    #[test]
263    fn test_subtraction() {
264        let mut rng = rand::thread_rng();
265        let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
266        let beta1 = P::random(&mut rng);
267        let beta2 = P::random(&mut rng);
268
269        let key1 = CurveKey {
270            alpha: alpha.clone(),
271            beta: beta1,
272        };
273        let key2 = CurveKey {
274            alpha: alpha.clone(),
275            beta: beta2,
276        };
277        let expected_result = CurveKey {
278            alpha,
279            beta: beta1 - beta2,
280        };
281        assert_eq!(key1 - key2, expected_result);
282    }
283
284    #[test]
285    fn test_multiplication() {
286        let mut rng = rand::thread_rng();
287        let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
288        let beta1 = P::random(&mut rng);
289
290        let key = CurveKey {
291            alpha: alpha.clone(),
292            beta: beta1,
293        };
294        let scalar = FrExt::from(3u32);
295        let expected_result = CurveKey {
296            alpha,
297            beta: beta1 * scalar,
298        };
299        assert_eq!(key * scalar, expected_result);
300    }
301
302    #[test]
303    fn test_negation() {
304        let mut rng = rand::thread_rng();
305        let alpha = GlobalCurveKey::<C>::new(FrExt::random(&mut rng));
306        let beta1 = P::random(&mut rng);
307
308        let key = CurveKey {
309            alpha: alpha.clone(),
310            beta: beta1,
311        };
312        let expected_result = CurveKey {
313            alpha,
314            beta: -beta1,
315        };
316        assert_eq!(-key, expected_result);
317    }
318}