use crate::{
CurveArithmetic, Error, FieldBytes, PrimeCurve, Scalar, ScalarValue, SecretKey,
ops::{Invert, Reduce, ReduceNonZero},
point::NonIdentity,
scalar::IsHigh,
};
use base16ct::HexDisplay;
use common::Generate;
use core::{
fmt,
ops::{Deref, Mul, MulAssign, Neg},
str,
};
use ff::{Field, PrimeField};
use rand_core::{CryptoRng, TryCryptoRng};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use zeroize::Zeroize;
#[cfg(feature = "serde")]
use serdect::serde::{Deserialize, Serialize, de, ser};
#[derive(Clone)]
#[repr(transparent)]
pub struct NonZeroScalar<C>
where
C: CurveArithmetic,
{
scalar: Scalar<C>,
}
impl<C: CurveArithmetic> fmt::Debug for NonZeroScalar<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NonZeroScalar").finish_non_exhaustive()
}
}
impl<C> NonZeroScalar<C>
where
C: CurveArithmetic,
{
pub fn new(scalar: Scalar<C>) -> CtOption<Self> {
CtOption::new(Self { scalar }, !scalar.is_zero())
}
pub fn from_repr(repr: FieldBytes<C>) -> CtOption<Self> {
Scalar::<C>::from_repr(repr).and_then(Self::new)
}
pub fn from_uint(uint: C::Uint) -> CtOption<Self> {
ScalarValue::new(uint).and_then(|scalar| Self::new(scalar.into()))
}
pub fn cast_array_as_inner<const N: usize>(scalars: &[Self; N]) -> &[Scalar<C>; N] {
#[allow(unsafe_code)]
unsafe {
&*scalars.as_ptr().cast()
}
}
pub fn cast_slice_as_inner(scalars: &[Self]) -> &[Scalar<C>] {
#[allow(unsafe_code)]
unsafe {
&*(core::ptr::from_ref(scalars) as *const [Scalar<C>])
}
}
#[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
Self::generate_from_rng(rng)
}
}
impl<C> AsRef<Scalar<C>> for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn as_ref(&self) -> &Scalar<C> {
&self.scalar
}
}
impl<C> ConditionallySelectable for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self {
scalar: Scalar::<C>::conditional_select(&a.scalar, &b.scalar, choice),
}
}
}
impl<C> ConstantTimeEq for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn ct_eq(&self, other: &Self) -> Choice {
self.scalar.ct_eq(&other.scalar)
}
}
impl<C> Copy for NonZeroScalar<C> where C: CurveArithmetic {}
impl<C> Deref for NonZeroScalar<C>
where
C: CurveArithmetic,
{
type Target = Scalar<C>;
fn deref(&self) -> &Scalar<C> {
&self.scalar
}
}
impl<C> Eq for NonZeroScalar<C> where C: CurveArithmetic {}
impl<C> From<NonZeroScalar<C>> for FieldBytes<C>
where
C: CurveArithmetic,
{
fn from(scalar: NonZeroScalar<C>) -> FieldBytes<C> {
Self::from(&scalar)
}
}
impl<C> From<&NonZeroScalar<C>> for FieldBytes<C>
where
C: CurveArithmetic,
{
fn from(scalar: &NonZeroScalar<C>) -> FieldBytes<C> {
scalar.to_repr()
}
}
impl<C> From<NonZeroScalar<C>> for ScalarValue<C>
where
C: CurveArithmetic,
{
#[inline]
fn from(scalar: NonZeroScalar<C>) -> ScalarValue<C> {
Self::from(&scalar)
}
}
impl<C> From<&NonZeroScalar<C>> for ScalarValue<C>
where
C: CurveArithmetic,
{
fn from(scalar: &NonZeroScalar<C>) -> ScalarValue<C> {
scalar.scalar.into()
}
}
impl<C> From<SecretKey<C>> for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn from(sk: SecretKey<C>) -> NonZeroScalar<C> {
Self::from(&sk)
}
}
impl<C> From<&SecretKey<C>> for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn from(sk: &SecretKey<C>) -> NonZeroScalar<C> {
let scalar = sk.as_scalar_value().to_scalar();
debug_assert!(!bool::from(scalar.is_zero()));
Self { scalar }
}
}
impl<C> Generate for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
loop {
if let Some(result) = Self::new(Scalar::<C>::try_generate_from_rng(rng)?).into() {
break Ok(result);
}
}
}
}
impl<C> Invert for NonZeroScalar<C>
where
C: CurveArithmetic,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>>,
{
type Output = Self;
fn invert(&self) -> Self {
Self {
scalar: Invert::invert(&self.scalar).unwrap(),
}
}
fn invert_vartime(&self) -> Self::Output {
Self {
scalar: Invert::invert_vartime(&self.scalar).unwrap(),
}
}
}
impl<C> IsHigh for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn is_high(&self) -> Choice {
self.scalar.is_high()
}
}
impl<C> Neg for NonZeroScalar<C>
where
C: CurveArithmetic,
{
type Output = NonZeroScalar<C>;
fn neg(self) -> NonZeroScalar<C> {
let scalar = -self.scalar;
debug_assert!(!bool::from(scalar.is_zero()));
NonZeroScalar { scalar }
}
}
impl<C> Mul<NonZeroScalar<C>> for NonZeroScalar<C>
where
C: PrimeCurve + CurveArithmetic,
{
type Output = Self;
#[inline]
fn mul(self, other: Self) -> Self {
Self::mul(self, &other)
}
}
impl<C> Mul<&NonZeroScalar<C>> for NonZeroScalar<C>
where
C: PrimeCurve + CurveArithmetic,
{
type Output = Self;
fn mul(self, other: &Self) -> Self {
let scalar = self.scalar * other.scalar;
debug_assert!(!bool::from(scalar.is_zero()));
NonZeroScalar { scalar }
}
}
impl<C, P> Mul<NonIdentity<P>> for NonZeroScalar<C>
where
C: CurveArithmetic,
NonIdentity<P>: Mul<NonZeroScalar<C>, Output = NonIdentity<P>>,
{
type Output = NonIdentity<P>;
fn mul(self, rhs: NonIdentity<P>) -> Self::Output {
rhs * self
}
}
impl<C, P> Mul<&NonIdentity<P>> for NonZeroScalar<C>
where
C: CurveArithmetic,
for<'a> &'a NonIdentity<P>: Mul<NonZeroScalar<C>, Output = NonIdentity<P>>,
{
type Output = NonIdentity<P>;
fn mul(self, rhs: &NonIdentity<P>) -> Self::Output {
rhs * self
}
}
impl<C, P> Mul<NonIdentity<P>> for &NonZeroScalar<C>
where
C: CurveArithmetic,
for<'a> NonIdentity<P>: Mul<&'a NonZeroScalar<C>, Output = NonIdentity<P>>,
{
type Output = NonIdentity<P>;
fn mul(self, rhs: NonIdentity<P>) -> Self::Output {
rhs * self
}
}
impl<C, P> Mul<&NonIdentity<P>> for &NonZeroScalar<C>
where
C: CurveArithmetic,
for<'a> &'a NonIdentity<P>: Mul<&'a NonZeroScalar<C>, Output = NonIdentity<P>>,
{
type Output = NonIdentity<P>;
fn mul(self, rhs: &NonIdentity<P>) -> Self::Output {
rhs * self
}
}
impl<C> MulAssign for NonZeroScalar<C>
where
C: PrimeCurve + CurveArithmetic,
{
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl<C> PartialEq for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn eq(&self, other: &Self) -> bool {
self.scalar.eq(&other.scalar)
}
}
impl<C, T> Reduce<T> for NonZeroScalar<C>
where
C: CurveArithmetic,
Scalar<C>: ReduceNonZero<T>,
{
fn reduce(n: &T) -> Self {
<Self as ReduceNonZero<T>>::reduce_nonzero(n)
}
}
impl<C, T> ReduceNonZero<T> for NonZeroScalar<C>
where
C: CurveArithmetic,
Scalar<C>: ReduceNonZero<T>,
{
fn reduce_nonzero(n: &T) -> Self {
let scalar = Scalar::<C>::reduce_nonzero(n);
debug_assert!(!bool::from(scalar.is_zero()));
Self { scalar }
}
}
impl<C> TryFrom<&[u8]> for NonZeroScalar<C>
where
C: CurveArithmetic,
{
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self, Error> {
NonZeroScalar::from_repr(bytes.try_into()?)
.into_option()
.ok_or(Error)
}
}
impl<C> Zeroize for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn zeroize(&mut self) {
self.scalar.zeroize();
self.scalar = Scalar::<C>::ONE;
}
}
impl<C> fmt::Display for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self:X}")
}
}
impl<C> fmt::LowerHex for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:x}", HexDisplay(&self.to_repr()))
}
}
impl<C> fmt::UpperHex for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:}", HexDisplay(&self.to_repr()))
}
}
impl<C> str::FromStr for NonZeroScalar<C>
where
C: CurveArithmetic,
{
type Err = Error;
fn from_str(hex: &str) -> Result<Self, Error> {
let mut bytes = FieldBytes::<C>::default();
if base16ct::mixed::decode(hex, &mut bytes)?.len() == bytes.len() {
Self::from_repr(bytes).into_option().ok_or(Error)
} else {
Err(Error)
}
}
}
#[cfg(feature = "serde")]
impl<C> Serialize for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
ScalarValue::from(self).serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, C> Deserialize<'de> for NonZeroScalar<C>
where
C: CurveArithmetic,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
let scalar = ScalarValue::deserialize(deserializer)?;
Self::new(scalar.into())
.into_option()
.ok_or_else(|| de::Error::custom("expected non-zero scalar"))
}
}
#[cfg(all(test, feature = "dev"))]
mod tests {
use crate::dev::{NonZeroScalar, Scalar};
use ff::{Field, PrimeField};
use hex_literal::hex;
use zeroize::Zeroize;
#[test]
fn round_trip() {
let bytes = hex!("c9afa9d845ba75166b5c215767b1d6934e50c3db36e89b127b8a622b120f6721");
let scalar = NonZeroScalar::from_repr(bytes.into()).unwrap();
assert_eq!(&bytes, scalar.to_repr().as_slice());
}
#[test]
fn zeroize() {
let mut scalar = NonZeroScalar::new(Scalar::from(42u64)).unwrap();
scalar.zeroize();
assert_eq!(*scalar, Scalar::ONE);
}
}