1use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
2
3use serde::{Deserialize, Serialize};
4use subtle::{Choice, ConstantTimeEq};
5
6use super::{OpenPointShares, ScalarKeys};
7use crate::{
8 algebra::elliptic_curve::{Curve, Point, Scalar, ScalarAsExtension},
9 errors::PrimitiveError,
10 random::{CryptoRngCore, Random, RandomWith},
11 sharing::GlobalCurveKey,
12 types::{
13 heap_array::curve_arrays::{CurvePoints, Scalars, ScalarsAsExtension},
14 ConditionallySelectable,
15 Positive,
16 },
17};
18
19#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(bound = "C: Curve, M: Positive")]
21pub struct CurveKeys<C: Curve, M: Positive> {
22 pub(crate) alpha: GlobalCurveKey<C>,
23 pub(crate) betas: CurvePoints<C, M>,
24}
25
26impl<C: Curve, M: Positive> CurveKeys<C, M> {
27 pub fn new(alpha: GlobalCurveKey<C>, betas: CurvePoints<C, M>) -> Self {
28 CurveKeys { alpha, betas }
29 }
30
31 pub fn get_alpha(&self) -> GlobalCurveKey<C> {
32 self.alpha.clone()
33 }
34
35 pub fn get_alpha_value(&self) -> ScalarAsExtension<C> {
36 *self.alpha
37 }
38
39 pub fn get_betas(&self) -> &CurvePoints<C, M> {
40 &self.betas
41 }
42
43 pub fn compute_mac(&self, values: &CurvePoints<C, M>) -> CurvePoints<C, M> {
46 values * *self.alpha + &self.betas
47 }
48
49 #[inline]
50 pub fn verify_mac(&self, open_shares: &OpenPointShares<C, M>) -> Result<(), PrimitiveError> {
51 let computed_macs = self.compute_mac(open_shares.get_value());
52 bool::from(computed_macs.ct_eq(open_shares.get_mac()))
53 .then_some(())
54 .ok_or_else(|| {
55 PrimitiveError::WrongMAC(
56 serde_json::to_string(&computed_macs).unwrap(),
57 serde_json::to_string(open_shares.get_mac()).unwrap(),
58 )
59 })
60 }
61}
62
63impl<C: Curve, M: Positive> ConditionallySelectable for CurveKeys<C, M> {
64 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
65 CurveKeys {
66 alpha: GlobalCurveKey::<C>::conditional_select(&a.alpha, &b.alpha, choice),
67 betas: CurvePoints::conditional_select(&a.betas, &b.betas, choice),
68 }
69 }
70}
71
72impl<C: Curve, M: Positive> Random for CurveKeys<C, M> {
77 fn random(mut rng: impl CryptoRngCore) -> Self {
78 let alpha = GlobalCurveKey::<C>::random(&mut rng);
79 let betas = CurvePoints::random(&mut rng);
80 CurveKeys { alpha, betas }
81 }
82}
83
84impl<C: Curve, M: Positive> RandomWith<GlobalCurveKey<C>> for CurveKeys<C, M> {
85 fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalCurveKey<C>) -> Self {
86 CurveKeys {
87 alpha,
88 betas: CurvePoints::random(&mut rng),
89 }
90 }
91}
92
93#[macros::op_variants(owned, borrowed, flipped_commutative)]
100impl<'a, C: Curve, M: Positive> Add<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
101 type Output = CurveKeys<C, M>;
102
103 #[inline]
104 fn add(mut self, other: &'a CurveKeys<C, M>) -> Self::Output {
105 debug_assert_eq!(self.alpha, other.alpha);
106 self.betas += &other.betas;
107 self
108 }
109}
110
111#[macros::op_variants(owned)]
112impl<'a, C: Curve, M: Positive> AddAssign<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
113 #[inline]
114 fn add_assign(&mut self, rhs: &'a CurveKeys<C, M>) {
115 self.betas += &rhs.betas;
116 }
117}
118
119#[macros::op_variants(owned, borrowed, flipped)]
122impl<'a, C: Curve, M: Positive> Sub<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
123 type Output = CurveKeys<C, M>;
124
125 #[inline]
126 fn sub(mut self, other: &'a CurveKeys<C, M>) -> Self::Output {
127 debug_assert_eq!(self.alpha, other.alpha);
128 self.betas -= &other.betas;
129 self
130 }
131}
132
133#[macros::op_variants(owned)]
134impl<'a, C: Curve, M: Positive> SubAssign<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
135 #[inline]
136 fn sub_assign(&mut self, rhs: &'a CurveKeys<C, M>) {
137 self.betas -= &rhs.betas;
138 }
139}
140
141#[macros::op_variants(owned, borrowed)]
144impl<'a, C: Curve, M: Positive> Mul<&'a ScalarAsExtension<C>> for CurveKeys<C, M> {
145 type Output = CurveKeys<C, M>;
146
147 #[inline]
148 fn mul(mut self, other: &'a ScalarAsExtension<C>) -> Self::Output {
149 self.betas *= other;
150 self
151 }
152}
153
154#[macros::op_variants(owned, borrowed)]
155impl<'a, C: Curve, M: Positive> Mul<&'a Scalar<C>> for CurveKeys<C, M> {
156 type Output = CurveKeys<C, M>;
157
158 #[inline]
159 fn mul(mut self, other: &'a Scalar<C>) -> Self::Output {
160 self.betas *= other;
161 self
162 }
163}
164
165#[macros::op_variants(owned, borrowed)]
166impl<'a, C: Curve, M: Positive> Mul<&'a ScalarsAsExtension<C, M>> for CurveKeys<C, M> {
167 type Output = CurveKeys<C, M>;
168
169 #[inline]
170 fn mul(mut self, other: &'a ScalarsAsExtension<C, M>) -> Self::Output {
171 self.betas *= other;
172 self
173 }
174}
175
176#[macros::op_variants(owned, borrowed)]
177impl<'a, C: Curve, M: Positive> Mul<&'a Scalars<C, M>> for CurveKeys<C, M> {
178 type Output = CurveKeys<C, M>;
179
180 #[inline]
181 fn mul(mut self, other: &'a Scalars<C, M>) -> Self::Output {
182 self.betas *= other;
183 self
184 }
185}
186
187#[macros::op_variants(owned)]
190impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarAsExtension<C>> for CurveKeys<C, M> {
191 #[inline]
192 fn mul_assign(&mut self, rhs: &'a ScalarAsExtension<C>) {
193 self.betas *= rhs;
194 }
195}
196
197#[macros::op_variants(owned)]
198impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalar<C>> for CurveKeys<C, M> {
199 #[inline]
200 fn mul_assign(&mut self, rhs: &'a Scalar<C>) {
201 self.betas *= rhs;
202 }
203}
204
205#[macros::op_variants(owned)]
206impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarsAsExtension<C, M>> for CurveKeys<C, M> {
207 #[inline]
208 fn mul_assign(&mut self, rhs: &'a ScalarsAsExtension<C, M>) {
209 self.betas *= rhs;
210 }
211}
212
213#[macros::op_variants(owned)]
214impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalars<C, M>> for CurveKeys<C, M> {
215 #[inline]
216 fn mul_assign(&mut self, rhs: &'a Scalars<C, M>) {
217 self.betas *= rhs;
218 }
219}
220#[macros::op_variants(borrowed)]
223impl<C: Curve, M: Positive> Neg for CurveKeys<C, M> {
224 type Output = CurveKeys<C, M>;
225
226 #[inline]
227 fn neg(self) -> Self::Output {
228 CurveKeys {
229 alpha: self.alpha,
230 betas: -self.betas,
231 }
232 }
233}
234
235impl<C: Curve, M: Positive> ConstantTimeEq for CurveKeys<C, M> {
238 #[inline]
239 fn ct_eq(&self, other: &Self) -> Choice {
240 self.alpha.ct_eq(&other.alpha) & self.betas.ct_eq(&other.betas)
241 }
242}
243
244impl<C: Curve, M: Positive> From<ScalarKeys<C, M>> for CurveKeys<C, M> {
247 #[inline]
248 fn from(scalar_key: ScalarKeys<C, M>) -> Self {
249 CurveKeys {
250 alpha: scalar_key.alpha,
251 betas: scalar_key.betas * Point::<C>::generator(),
252 }
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use typenum::U8;
259
260 use super::*;
261 use crate::{
262 algebra::elliptic_curve::Curve25519Ristretto as C,
263 random::{self, Random},
264 };
265 pub type FrExt = ScalarAsExtension<C>;
266 pub type Ps = CurvePoints<C, U8>;
267
268 #[test]
269 fn test_addition() {
270 let mut rng = random::test_rng();
271 let alpha = GlobalCurveKey::<C>::random(&mut rng);
272 let beta1 = Ps::random(&mut rng);
273 let beta2 = Ps::random(&mut rng);
274
275 let key1 = CurveKeys {
276 alpha: alpha.clone(),
277 betas: beta1.clone(),
278 };
279 let key2 = CurveKeys {
280 alpha: alpha.clone(),
281 betas: beta2.clone(),
282 };
283 let expected_result = CurveKeys {
284 alpha,
285 betas: beta1 + beta2,
286 };
287 assert_eq!(key1 + key2, expected_result);
288 }
289
290 #[test]
291 fn test_subtraction() {
292 let mut rng = random::test_rng();
293 let alpha = GlobalCurveKey::<C>::random(&mut rng);
294 let beta1 = Ps::random(&mut rng);
295 let beta2 = Ps::random(&mut rng);
296
297 let key1 = CurveKeys {
298 alpha: alpha.clone(),
299 betas: beta1.clone(),
300 };
301 let key2 = CurveKeys {
302 alpha: alpha.clone(),
303 betas: beta2.clone(),
304 };
305 let expected_result = CurveKeys {
306 alpha,
307 betas: beta1 - beta2,
308 };
309 assert_eq!(key1 - key2, expected_result);
310 }
311
312 #[test]
313 fn test_multiplication() {
314 let mut rng = random::test_rng();
315 let alpha = GlobalCurveKey::<C>::random(&mut rng);
316 let beta1 = Ps::random(&mut rng);
317
318 let key = CurveKeys {
319 alpha: alpha.clone(),
320 betas: beta1.clone(),
321 };
322 let scalar = FrExt::from(3u32);
323 let expected_result = CurveKeys {
324 alpha,
325 betas: beta1 * scalar,
326 };
327 assert_eq!(key * scalar, expected_result);
328 }
329
330 #[test]
331 fn test_negation() {
332 let mut rng = random::test_rng();
333 let alpha = GlobalCurveKey::<C>::random(&mut rng);
334 let beta1 = Ps::random(&mut rng);
335
336 let key = CurveKeys {
337 alpha: alpha.clone(),
338 betas: beta1.clone(),
339 };
340 let expected_result = CurveKeys {
341 alpha,
342 betas: -beta1,
343 };
344 assert_eq!(-key, expected_result);
345 }
346}