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