Skip to main content

generic_ec/
secret_scalar.rs

1use core::fmt;
2use core::iter::{Product, Sum};
3
4use rand_core::{CryptoRng, RngCore};
5use subtle::{Choice, ConstantTimeEq};
6
7use crate::EncodedSecretScalar;
8use crate::{errors::InvalidScalar, secret, Curve, Scalar};
9
10/// Scalar representing sensitive information (like secret key)
11///
12/// Secret scalar should be treated with an extra care. You shouldn't do any
13/// branching (e.g. `Eq`, `Ord`) on the secret to avoid timing side-channel
14/// attacks, so it implements only constant time traits (like [`ConstantTimeEq`]).
15///
16/// Also, when `alloc` feature is enabled, we enforce extra measures:
17///
18/// * Secret scalar leaves no trace in RAM after it's dropped \
19///   Memory is zeroized after use
20/// * All clones of secret scalar refer to the same region in the memory \
21///   I.e. there will always be only one instance of the scalar in the memory
22///   no matter how many clones you make
23///
24/// All these guarantees can be bypassed by calling `.as_ref()` and obtaining
25/// `&Scalar<E>` that is not protected from timing attacks, leaving traces in
26/// the memory, etc.
27///
28/// [`ConstantTimeEq`]: subtle::ConstantTimeEq
29pub struct SecretScalar<E: Curve>(secret::Secret<Scalar<E>>);
30
31impl<E: Curve> Scalar<E> {
32    /// Convert this value into a [`SecretScalar`]. You should do this at the end
33    /// of computations that produce a secret, like a key exchange
34    #[inline(always)] // Prevent a byte copy in most cases
35    pub fn into_secret(mut self) -> SecretScalar<E> {
36        SecretScalar::new(&mut self)
37    }
38}
39
40impl<E: Curve> SecretScalar<E> {
41    /// Constructs a new secret scalar
42    ///
43    /// Takes the original scalar by mutable reference instead of taking by value to
44    /// avoid leaving copies of the scalar on stack. Scalar behind the reference will
45    /// be zeroized after the function has returned.
46    pub fn new(scalar: &mut Scalar<E>) -> Self {
47        Self(secret::new(scalar))
48    }
49
50    /// Returns scalar $S = 0$
51    pub fn zero() -> Self {
52        Self::new(&mut Scalar::zero())
53    }
54
55    /// Returns scalar $S = 1$
56    pub fn one() -> Self {
57        Self::new(&mut Scalar::one())
58    }
59
60    /// Returns scalar inverse
61    pub fn invert(&self) -> Option<Self> {
62        let scalar: Option<Scalar<E>> = self.as_ref().ct_invert().into();
63        Some(Self::new(&mut scalar?))
64    }
65
66    /// Generates random secret scalar
67    pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
68        let mut scalar = Scalar::random(rng);
69        Self::new(&mut scalar)
70    }
71
72    #[doc = include_str!("../docs/hash_to_scalar.md")]
73    ///
74    /// ## Example
75    /// ```rust
76    /// use generic_ec::{SecretScalar, curves::Secp256k1};
77    /// use sha2::Sha256;
78    ///
79    /// #[derive(udigest::Digestable)]
80    /// struct Data<'a> {
81    ///     nonce: &'a [u8],
82    ///     param_a: &'a str,
83    ///     param_b: u128,
84    ///     // ...
85    /// }
86    ///
87    /// let scalar = SecretScalar::<Secp256k1>::from_hash::<Sha256>(&Data {
88    ///     nonce: b"some data",
89    ///     param_a: "some other data",
90    ///     param_b: 12345,
91    ///     // ...
92    /// });
93    /// ```
94    #[cfg(feature = "hash-to-scalar")]
95    pub fn from_hash<D: digest::Digest>(data: &impl udigest::Digestable) -> Self {
96        let mut rng = rand_hash::HashRng::<D, _>::from_seed(data);
97        Self::random(&mut rng)
98    }
99
100    /// Obtain the reference to the scalar, which you can use for any operations
101    /// necessary. This bypasses all the secrecy guarantees, so be careful when
102    /// handling the resulting value; ideally this reference should not be held
103    /// for longer than one expression
104    ///
105    /// The [`AsRef`] impl uses this method under the hood, and is provided as a
106    /// less explicit but very convenient alternative
107    pub fn as_nonsecret(&self) -> &Scalar<E> {
108        secret::inner_ref(&self.0)
109    }
110
111    /// Encodes scalar as bytes in big-endian order
112    pub fn to_be_bytes(&self) -> EncodedSecretScalar<E> {
113        let bytes = self.as_ref().to_be_bytes();
114        EncodedSecretScalar::new(bytes)
115    }
116
117    /// Encodes scalar as bytes in little-endian order
118    pub fn to_le_bytes(&self) -> EncodedSecretScalar<E> {
119        let bytes = self.as_ref().to_le_bytes();
120        EncodedSecretScalar::new(bytes)
121    }
122
123    /// Decodes scalar from its bytes representation in big-endian order
124    pub fn from_be_bytes(bytes: &[u8]) -> Result<Self, InvalidScalar> {
125        let mut scalar = Scalar::from_be_bytes(bytes)?;
126        Ok(Self::new(&mut scalar))
127    }
128
129    /// Decodes scalar from its bytes representation in little-endian order
130    pub fn from_le_bytes(bytes: &[u8]) -> Result<Self, InvalidScalar> {
131        let mut scalar = Scalar::from_le_bytes(bytes)?;
132        Ok(Self::new(&mut scalar))
133    }
134}
135
136impl<E: Curve> AsRef<Scalar<E>> for SecretScalar<E> {
137    fn as_ref(&self) -> &Scalar<E> {
138        self.as_nonsecret()
139    }
140}
141
142impl<E: Curve> Clone for SecretScalar<E> {
143    fn clone(&self) -> Self {
144        Self(self.0.clone())
145    }
146}
147
148impl<E: Curve> ConstantTimeEq for SecretScalar<E> {
149    fn ct_eq(&self, other: &Self) -> Choice {
150        self.as_ref().ct_eq(other.as_ref())
151    }
152}
153
154impl<E: Curve> Sum<SecretScalar<E>> for Scalar<E> {
155    fn sum<I: Iterator<Item = SecretScalar<E>>>(iter: I) -> Self {
156        iter.fold(Scalar::<E>::zero(), |acc, i| acc + &i)
157    }
158}
159
160impl<'s, E: Curve> Sum<&'s SecretScalar<E>> for Scalar<E> {
161    fn sum<I: Iterator<Item = &'s SecretScalar<E>>>(iter: I) -> Self {
162        iter.fold(Scalar::<E>::zero(), |acc, i| acc + i)
163    }
164}
165
166impl<E: Curve> Product<SecretScalar<E>> for Scalar<E> {
167    fn product<I: Iterator<Item = SecretScalar<E>>>(iter: I) -> Self {
168        iter.fold(Scalar::<E>::one(), |acc, i| acc * &i)
169    }
170}
171
172impl<'s, E: Curve> Product<&'s SecretScalar<E>> for Scalar<E> {
173    fn product<I: Iterator<Item = &'s SecretScalar<E>>>(iter: I) -> Self {
174        iter.fold(Scalar::<E>::one(), |acc, i| acc * i)
175    }
176}
177
178impl<E: Curve> fmt::Debug for SecretScalar<E> {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        f.write_str("SecretScalar")
181    }
182}
183
184impl<E: Curve> crate::traits::Samplable for SecretScalar<E> {
185    fn random<R: RngCore>(rng: &mut R) -> Self {
186        let mut scalar = Scalar::random(rng);
187        Self::new(&mut scalar)
188    }
189
190    fn random_vartime<R: rand_core::RngCore>(rng: &mut R) -> Self {
191        let mut scalar = Scalar::random_vartime(rng);
192        Self::new(&mut scalar)
193    }
194}