elliptic_curve/scalar/
blinded.rs1use super::Scalar;
4use crate::{CurveArithmetic, ops::Invert};
5use common::Generate;
6use core::fmt;
7use rand_core::{CryptoRng, TryCryptoRng};
8use subtle::CtOption;
9use zeroize::Zeroize;
10
11#[cfg(feature = "getrandom")]
12use common::getrandom::{self, SysRng, rand_core::UnwrapErr};
13
14#[derive(Clone)]
22pub struct BlindedScalar<C>
23where
24 C: CurveArithmetic,
25{
26 scalar: Scalar<C>,
28
29 mask: Scalar<C>,
31}
32
33impl<C: CurveArithmetic> fmt::Debug for BlindedScalar<C> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 f.debug_struct("BlindedScalar").finish_non_exhaustive()
36 }
37}
38
39impl<C> BlindedScalar<C>
40where
41 C: CurveArithmetic,
42{
43 #[cfg(feature = "getrandom")]
45 pub fn new(scalar: Scalar<C>) -> Self {
46 Self::new_from_rng(scalar, &mut UnwrapErr(SysRng))
47 }
48
49 #[cfg(feature = "getrandom")]
54 pub fn try_new(scalar: Scalar<C>) -> Result<Self, getrandom::Error> {
55 Self::try_new_from_rng(scalar, &mut SysRng)
56 }
57
58 pub fn new_from_rng<R: CryptoRng + ?Sized>(scalar: Scalar<C>, rng: &mut R) -> Self {
60 let Ok(ret) = Self::try_new_from_rng(scalar, rng);
61 ret
62 }
63
64 pub fn try_new_from_rng<R>(scalar: Scalar<C>, rng: &mut R) -> Result<Self, R::Error>
69 where
70 R: TryCryptoRng + ?Sized,
71 {
72 let mask = Scalar::<C>::try_generate_from_rng(rng)?;
73 Ok(Self { scalar, mask })
74 }
75}
76
77impl<C> AsRef<Scalar<C>> for BlindedScalar<C>
78where
79 C: CurveArithmetic,
80{
81 fn as_ref(&self) -> &Scalar<C> {
82 &self.scalar
83 }
84}
85
86impl<C> Invert for BlindedScalar<C>
87where
88 C: CurveArithmetic,
89{
90 type Output = CtOption<Scalar<C>>;
91
92 fn invert(&self) -> CtOption<Scalar<C>> {
93 (self.scalar * self.mask)
96 .invert_vartime()
97 .map(|s| s * self.mask)
98 }
99}
100
101impl<C> Drop for BlindedScalar<C>
102where
103 C: CurveArithmetic,
104{
105 fn drop(&mut self) {
106 self.scalar.zeroize();
107 self.mask.zeroize();
108 }
109}