elliptic_curve/scalar/
blinded.rs

1//! Random blinding support for [`Scalar`]
2
3use super::Scalar;
4use crate::{ops::Invert, CurveArithmetic};
5use group::ff::Field;
6use rand_core::CryptoRngCore;
7use subtle::CtOption;
8use zeroize::Zeroize;
9
10/// Scalar blinded with a randomly generated masking value.
11///
12/// This provides a randomly blinded impl of [`Invert`] which is useful for
13/// e.g. ECDSA ephemeral (`k`) scalars.
14///
15/// It implements masked variable-time inversions using Stein's algorithm, which
16/// may be helpful for performance on embedded platforms.
17#[derive(Clone)]
18pub struct BlindedScalar<C>
19where
20    C: CurveArithmetic,
21{
22    /// Actual scalar value.
23    scalar: Scalar<C>,
24
25    /// Mask value.
26    mask: Scalar<C>,
27}
28
29impl<C> BlindedScalar<C>
30where
31    C: CurveArithmetic,
32{
33    /// Create a new [`BlindedScalar`] from a scalar and a [`CryptoRngCore`].
34    pub fn new(scalar: Scalar<C>, rng: &mut impl CryptoRngCore) -> Self {
35        Self {
36            scalar,
37            mask: Scalar::<C>::random(rng),
38        }
39    }
40}
41
42impl<C> AsRef<Scalar<C>> for BlindedScalar<C>
43where
44    C: CurveArithmetic,
45{
46    fn as_ref(&self) -> &Scalar<C> {
47        &self.scalar
48    }
49}
50
51impl<C> Invert for BlindedScalar<C>
52where
53    C: CurveArithmetic,
54{
55    type Output = CtOption<Scalar<C>>;
56
57    fn invert(&self) -> CtOption<Scalar<C>> {
58        // prevent side channel analysis of scalar inversion by pre-and-post-multiplying
59        // with the random masking scalar
60        (self.scalar * self.mask)
61            .invert_vartime()
62            .map(|s| s * self.mask)
63    }
64}
65
66impl<C> Drop for BlindedScalar<C>
67where
68    C: CurveArithmetic,
69{
70    fn drop(&mut self) {
71        self.scalar.zeroize();
72        self.mask.zeroize();
73    }
74}