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(serde_json::to_string(open_shares.get_mac()).unwrap())
56 })
57 }
58}
59
60impl<C: Curve, M: Positive> ConditionallySelectable for CurveKeys<C, M> {
61 fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
62 CurveKeys {
63 alpha: GlobalCurveKey::<C>::conditional_select(&a.alpha, &b.alpha, choice),
64 betas: CurvePoints::conditional_select(&a.betas, &b.betas, choice),
65 }
66 }
67}
68
69impl<C: Curve, M: Positive> Random for CurveKeys<C, M> {
74 fn random(mut rng: impl CryptoRngCore) -> Self {
75 let alpha = GlobalCurveKey::<C>::random(&mut rng);
76 let betas = CurvePoints::random(&mut rng);
77 CurveKeys { alpha, betas }
78 }
79}
80
81impl<C: Curve, M: Positive> RandomWith<GlobalCurveKey<C>> for CurveKeys<C, M> {
82 fn random_with(mut rng: impl CryptoRngCore, alpha: GlobalCurveKey<C>) -> Self {
83 CurveKeys {
84 alpha,
85 betas: CurvePoints::random(&mut rng),
86 }
87 }
88}
89
90#[macros::op_variants(owned, borrowed, flipped_commutative)]
97impl<'a, C: Curve, M: Positive> Add<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
98 type Output = CurveKeys<C, M>;
99
100 #[inline]
101 fn add(mut self, other: &'a CurveKeys<C, M>) -> Self::Output {
102 assert_eq!(self.alpha, other.alpha);
103 self.betas += &other.betas;
104 self
105 }
106}
107
108#[macros::op_variants(owned)]
109impl<'a, C: Curve, M: Positive> AddAssign<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
110 #[inline]
111 fn add_assign(&mut self, rhs: &'a CurveKeys<C, M>) {
112 assert_eq!(self.alpha, rhs.alpha);
113 self.betas += &rhs.betas;
114 }
115}
116
117#[macros::op_variants(owned, borrowed, flipped)]
120impl<'a, C: Curve, M: Positive> Sub<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
121 type Output = CurveKeys<C, M>;
122
123 #[inline]
124 fn sub(mut self, other: &'a CurveKeys<C, M>) -> Self::Output {
125 assert_eq!(self.alpha, other.alpha);
126 self.betas -= &other.betas;
127 self
128 }
129}
130
131#[macros::op_variants(owned)]
132impl<'a, C: Curve, M: Positive> SubAssign<&'a CurveKeys<C, M>> for CurveKeys<C, M> {
133 #[inline]
134 fn sub_assign(&mut self, rhs: &'a CurveKeys<C, M>) {
135 assert_eq!(self.alpha, rhs.alpha);
136 self.betas -= &rhs.betas;
137 }
138}
139
140#[macros::op_variants(owned, borrowed)]
143impl<'a, C: Curve, M: Positive> Mul<&'a ScalarAsExtension<C>> for CurveKeys<C, M> {
144 type Output = CurveKeys<C, M>;
145
146 #[inline]
147 fn mul(mut self, other: &'a ScalarAsExtension<C>) -> Self::Output {
148 self.betas *= other;
149 self
150 }
151}
152
153#[macros::op_variants(owned, borrowed)]
154impl<'a, C: Curve, M: Positive> Mul<&'a Scalar<C>> for CurveKeys<C, M> {
155 type Output = CurveKeys<C, M>;
156
157 #[inline]
158 fn mul(mut self, other: &'a Scalar<C>) -> Self::Output {
159 self.betas *= other;
160 self
161 }
162}
163
164#[macros::op_variants(owned, borrowed)]
165impl<'a, C: Curve, M: Positive> Mul<&'a ScalarsAsExtension<C, M>> for CurveKeys<C, M> {
166 type Output = CurveKeys<C, M>;
167
168 #[inline]
169 fn mul(mut self, other: &'a ScalarsAsExtension<C, M>) -> Self::Output {
170 self.betas *= other;
171 self
172 }
173}
174
175#[macros::op_variants(owned, borrowed)]
176impl<'a, C: Curve, M: Positive> Mul<&'a Scalars<C, M>> for CurveKeys<C, M> {
177 type Output = CurveKeys<C, M>;
178
179 #[inline]
180 fn mul(mut self, other: &'a Scalars<C, M>) -> Self::Output {
181 self.betas *= other;
182 self
183 }
184}
185
186#[macros::op_variants(owned)]
189impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarAsExtension<C>> for CurveKeys<C, M> {
190 #[inline]
191 fn mul_assign(&mut self, rhs: &'a ScalarAsExtension<C>) {
192 self.betas *= rhs;
193 }
194}
195
196#[macros::op_variants(owned)]
197impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalar<C>> for CurveKeys<C, M> {
198 #[inline]
199 fn mul_assign(&mut self, rhs: &'a Scalar<C>) {
200 self.betas *= rhs;
201 }
202}
203
204#[macros::op_variants(owned)]
205impl<'a, C: Curve, M: Positive> MulAssign<&'a ScalarsAsExtension<C, M>> for CurveKeys<C, M> {
206 #[inline]
207 fn mul_assign(&mut self, rhs: &'a ScalarsAsExtension<C, M>) {
208 self.betas *= rhs;
209 }
210}
211
212#[macros::op_variants(owned)]
213impl<'a, C: Curve, M: Positive> MulAssign<&'a Scalars<C, M>> for CurveKeys<C, M> {
214 #[inline]
215 fn mul_assign(&mut self, rhs: &'a Scalars<C, M>) {
216 self.betas *= rhs;
217 }
218}
219#[macros::op_variants(borrowed)]
222impl<C: Curve, M: Positive> Neg for CurveKeys<C, M> {
223 type Output = CurveKeys<C, M>;
224
225 #[inline]
226 fn neg(self) -> Self::Output {
227 CurveKeys {
228 alpha: self.alpha,
229 betas: -self.betas,
230 }
231 }
232}
233
234impl<C: Curve, M: Positive> ConstantTimeEq for CurveKeys<C, M> {
237 #[inline]
238 fn ct_eq(&self, other: &Self) -> Choice {
239 self.alpha.ct_eq(&other.alpha) & self.betas.ct_eq(&other.betas)
240 }
241}
242
243impl<C: Curve, M: Positive> From<ScalarKeys<C, M>> for CurveKeys<C, M> {
246 #[inline]
247 fn from(scalar_key: ScalarKeys<C, M>) -> Self {
248 CurveKeys {
249 alpha: scalar_key.alpha,
250 betas: scalar_key.betas * Point::<C>::generator(),
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use typenum::U8;
258
259 use super::*;
260 use crate::{
261 algebra::elliptic_curve::Curve25519Ristretto as C,
262 random::{self, Random},
263 };
264 pub type FrExt = ScalarAsExtension<C>;
265 pub type Ps = CurvePoints<C, U8>;
266
267 #[test]
268 fn test_addition() {
269 let mut rng = random::test_rng();
270 let alpha = GlobalCurveKey::<C>::random(&mut rng);
271 let beta1 = Ps::random(&mut rng);
272 let beta2 = Ps::random(&mut rng);
273
274 let key1 = CurveKeys {
275 alpha: alpha.clone(),
276 betas: beta1.clone(),
277 };
278 let key2 = CurveKeys {
279 alpha: alpha.clone(),
280 betas: beta2.clone(),
281 };
282 let expected_result = CurveKeys {
283 alpha,
284 betas: beta1 + beta2,
285 };
286 assert_eq!(key1 + key2, expected_result);
287 }
288
289 #[test]
290 fn test_subtraction() {
291 let mut rng = random::test_rng();
292 let alpha = GlobalCurveKey::<C>::random(&mut rng);
293 let beta1 = Ps::random(&mut rng);
294 let beta2 = Ps::random(&mut rng);
295
296 let key1 = CurveKeys {
297 alpha: alpha.clone(),
298 betas: beta1.clone(),
299 };
300 let key2 = CurveKeys {
301 alpha: alpha.clone(),
302 betas: beta2.clone(),
303 };
304 let expected_result = CurveKeys {
305 alpha,
306 betas: beta1 - beta2,
307 };
308 assert_eq!(key1 - key2, expected_result);
309 }
310
311 #[test]
312 fn test_multiplication() {
313 let mut rng = random::test_rng();
314 let alpha = GlobalCurveKey::<C>::random(&mut rng);
315 let beta1 = Ps::random(&mut rng);
316
317 let key = CurveKeys {
318 alpha: alpha.clone(),
319 betas: beta1.clone(),
320 };
321 let scalar = FrExt::from(3u32);
322 let expected_result = CurveKeys {
323 alpha,
324 betas: beta1 * scalar,
325 };
326 assert_eq!(key * scalar, expected_result);
327 }
328
329 #[test]
330 fn test_negation() {
331 let mut rng = random::test_rng();
332 let alpha = GlobalCurveKey::<C>::random(&mut rng);
333 let beta1 = Ps::random(&mut rng);
334
335 let key = CurveKeys {
336 alpha: alpha.clone(),
337 betas: beta1.clone(),
338 };
339 let expected_result = CurveKeys {
340 alpha,
341 betas: -beta1,
342 };
343 assert_eq!(-key, expected_result);
344 }
345}