use core::{
cmp,
iter::{self, Product, Sum},
};
use rand_core::{CryptoRng, RngCore};
use subtle::{ConstantTimeEq, CtOption};
use crate::{
as_raw::FromRaw,
core::{ByteArray, FromUniformBytes},
errors::{ZeroPoint, ZeroScalar},
Curve, Point, Scalar, SecretScalar,
};
use self::definition::NonZero;
pub mod coords;
pub mod definition;
impl<E: Curve> NonZero<Point<E>> {
pub fn from_point(point: Point<E>) -> Option<Self> {
Self::ct_from_point(point).into()
}
pub fn ct_from_point(point: Point<E>) -> CtOption<Self> {
let zero = Point::zero();
let is_non_zero = !point.ct_eq(&zero);
CtOption::new(Self::new_unchecked(point), is_non_zero)
}
}
impl<E: Curve> NonZero<Scalar<E>> {
#[doc = include_str!("../../docs/nonzero_scalar_random.md")]
pub fn random<R: RngCore>(rng: &mut R) -> Self {
match iter::repeat_with(|| {
let mut bytes = <<E::Scalar as FromUniformBytes>::Bytes as ByteArray>::zeroes();
rng.fill_bytes(bytes.as_mut());
<E::Scalar as FromUniformBytes>::from_uniform_bytes(&bytes)
})
.take(100)
.flat_map(|s| NonZero::from_scalar(Scalar::from_raw(s)))
.next()
{
Some(s) => s,
None => panic!("defected source of randomness"),
}
}
#[doc = include_str!("../../docs/nonzero_scalar_random_vartime.md")]
pub fn random_vartime<R: RngCore>(rng: &mut R) -> Self {
match iter::repeat_with(|| {
<E::Scalar as generic_ec_core::SamplableVartime>::random_vartime(rng)
})
.take(100)
.flat_map(|s| NonZero::from_scalar(Scalar::from_raw(s)))
.next()
{
Some(s) => s,
None => panic!("defected source of randomness"),
}
}
#[doc = include_str!("../../docs/hash_to_scalar.md")]
#[cfg(feature = "hash-to-scalar")]
pub fn from_hash<D: digest::Digest>(data: &impl udigest::Digestable) -> Self {
let mut rng = rand_hash::HashRng::<D, _>::from_seed(data);
Self::random(&mut rng)
}
pub fn one() -> Self {
Self::new_unchecked(Scalar::one())
}
pub fn from_scalar(scalar: Scalar<E>) -> Option<Self> {
Self::ct_from_scalar(scalar).into()
}
pub fn ct_from_scalar(scalar: Scalar<E>) -> CtOption<Self> {
let zero = Scalar::zero();
let is_non_zero = !scalar.ct_eq(&zero);
CtOption::new(Self::new_unchecked(scalar), is_non_zero)
}
pub fn invert(&self) -> NonZero<Scalar<E>> {
#[allow(clippy::expect_used)]
let inv = (**self)
.invert()
.expect("nonzero scalar always has an invert");
Self::new_unchecked(inv)
}
pub fn into_secret(self) -> NonZero<SecretScalar<E>> {
let mut scalar = self.into_inner();
let secret_scalar = SecretScalar::new(&mut scalar);
NonZero::new_unchecked(secret_scalar)
}
}
impl<E: Curve> NonZero<SecretScalar<E>> {
#[doc = include_str!("../../docs/nonzero_scalar_random.md")]
pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
<Self as crate::traits::Samplable>::random(rng)
}
#[doc = include_str!("../../docs/nonzero_scalar_random_vartime.md")]
pub fn random_vartime<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
<Self as crate::traits::Samplable>::random_vartime(rng)
}
pub fn one() -> Self {
Self::new_unchecked(SecretScalar::one())
}
pub fn from_secret_scalar(scalar: SecretScalar<E>) -> Option<Self> {
Self::ct_from_secret_scalar(scalar).into()
}
pub fn ct_from_secret_scalar(secret_scalar: SecretScalar<E>) -> CtOption<Self> {
let zero = Scalar::zero();
let is_non_zero = !secret_scalar.as_ref().ct_eq(&zero);
CtOption::new(Self::new_unchecked(secret_scalar), is_non_zero)
}
pub fn invert(&self) -> NonZero<SecretScalar<E>> {
#[allow(clippy::expect_used)]
let inv = (**self)
.invert()
.expect("nonzero scalar always has an invert");
Self::new_unchecked(inv)
}
}
impl<E: Curve> From<NonZero<Point<E>>> for Point<E> {
fn from(point: NonZero<Point<E>>) -> Self {
point.into_inner()
}
}
impl<E: Curve> From<NonZero<Scalar<E>>> for Scalar<E> {
fn from(scalar: NonZero<Scalar<E>>) -> Self {
scalar.into_inner()
}
}
impl<E: Curve> From<NonZero<SecretScalar<E>>> for SecretScalar<E> {
fn from(secret_scalar: NonZero<SecretScalar<E>>) -> Self {
secret_scalar.into_inner()
}
}
impl<E: Curve> TryFrom<Point<E>> for NonZero<Point<E>> {
type Error = ZeroPoint;
fn try_from(point: Point<E>) -> Result<Self, Self::Error> {
Self::from_point(point).ok_or(ZeroPoint)
}
}
impl<E: Curve> TryFrom<Scalar<E>> for NonZero<Scalar<E>> {
type Error = ZeroScalar;
fn try_from(scalar: Scalar<E>) -> Result<Self, Self::Error> {
Self::from_scalar(scalar).ok_or(ZeroScalar)
}
}
impl<E: Curve> TryFrom<SecretScalar<E>> for NonZero<SecretScalar<E>> {
type Error = ZeroScalar;
fn try_from(secret_scalar: SecretScalar<E>) -> Result<Self, Self::Error> {
Self::from_secret_scalar(secret_scalar).ok_or(ZeroScalar)
}
}
impl<E: Curve> Sum<NonZero<Scalar<E>>> for Scalar<E> {
fn sum<I: Iterator<Item = NonZero<Scalar<E>>>>(iter: I) -> Self {
iter.fold(Scalar::zero(), |acc, x| acc + x)
}
}
impl<'s, E: Curve> Sum<&'s NonZero<Scalar<E>>> for Scalar<E> {
fn sum<I: Iterator<Item = &'s NonZero<Scalar<E>>>>(iter: I) -> Self {
iter.fold(Scalar::zero(), |acc, x| acc + x)
}
}
impl<'s, E: Curve> Sum<&'s NonZero<SecretScalar<E>>> for SecretScalar<E> {
fn sum<I: Iterator<Item = &'s NonZero<SecretScalar<E>>>>(iter: I) -> Self {
let mut out = Scalar::zero();
iter.for_each(|x| out += x);
SecretScalar::new(&mut out)
}
}
impl<E: Curve> Sum<NonZero<SecretScalar<E>>> for SecretScalar<E> {
fn sum<I: Iterator<Item = NonZero<SecretScalar<E>>>>(iter: I) -> Self {
let mut out = Scalar::zero();
iter.for_each(|x| out += x);
SecretScalar::new(&mut out)
}
}
impl<E: Curve> Product<NonZero<Scalar<E>>> for NonZero<Scalar<E>> {
fn product<I: Iterator<Item = NonZero<Scalar<E>>>>(iter: I) -> Self {
iter.fold(Self::one(), |acc, x| acc * x)
}
}
impl<'s, E: Curve> Product<&'s NonZero<Scalar<E>>> for NonZero<Scalar<E>> {
fn product<I: Iterator<Item = &'s NonZero<Scalar<E>>>>(iter: I) -> Self {
iter.fold(Self::one(), |acc, x| acc * x)
}
}
impl<'s, E: Curve> Product<&'s NonZero<SecretScalar<E>>> for NonZero<SecretScalar<E>> {
fn product<I: Iterator<Item = &'s NonZero<SecretScalar<E>>>>(iter: I) -> Self {
let mut out = NonZero::<Scalar<E>>::one();
iter.for_each(|x| out *= x);
out.into_secret()
}
}
impl<E: Curve> Product<NonZero<SecretScalar<E>>> for NonZero<SecretScalar<E>> {
fn product<I: Iterator<Item = NonZero<SecretScalar<E>>>>(iter: I) -> Self {
let mut out = NonZero::<Scalar<E>>::one();
iter.for_each(|x| out *= x);
out.into_secret()
}
}
impl<E: Curve> Sum<NonZero<Point<E>>> for Point<E> {
fn sum<I: Iterator<Item = NonZero<Point<E>>>>(iter: I) -> Self {
iter.fold(Point::zero(), |acc, x| acc + x)
}
}
impl<'s, E: Curve> Sum<&'s NonZero<Point<E>>> for Point<E> {
fn sum<I: Iterator<Item = &'s NonZero<Point<E>>>>(iter: I) -> Self {
iter.fold(Point::zero(), |acc, x| acc + x)
}
}
impl<E: Curve> crate::traits::Samplable for NonZero<Scalar<E>> {
fn random<R: RngCore>(rng: &mut R) -> Self {
Self::random(rng)
}
fn random_vartime<R: rand_core::RngCore>(rng: &mut R) -> Self {
Self::random_vartime(rng)
}
}
impl<E: Curve> crate::traits::Samplable for NonZero<SecretScalar<E>> {
fn random<R: RngCore>(rng: &mut R) -> Self {
NonZero::<Scalar<E>>::random(rng).into_secret()
}
fn random_vartime<R: rand_core::RngCore>(rng: &mut R) -> Self {
NonZero::<Scalar<E>>::random_vartime(rng).into_secret()
}
}
impl<T> crate::traits::IsZero for NonZero<T> {
#[inline(always)]
fn is_zero(&self) -> bool {
false
}
}
impl<E: Curve> crate::traits::One for NonZero<Scalar<E>> {
fn one() -> Self {
Self::one()
}
fn is_one(x: &Self) -> subtle::Choice {
x.ct_eq(&Self::one())
}
}
impl<E: Curve> AsRef<Scalar<E>> for NonZero<SecretScalar<E>> {
fn as_ref(&self) -> &Scalar<E> {
let secret_scalar: &SecretScalar<E> = self.as_ref();
secret_scalar.as_ref()
}
}
impl<T> cmp::PartialEq<T> for NonZero<T>
where
T: cmp::PartialEq,
{
fn eq(&self, other: &T) -> bool {
self.as_ref() == other
}
}
impl<T> cmp::PartialOrd<T> for NonZero<T>
where
T: cmp::PartialOrd,
{
fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
self.as_ref().partial_cmp(other)
}
}
macro_rules! impl_reverse_partial_eq_cmp {
($($t:ty),+) => {$(
impl<E: Curve> cmp::PartialEq<NonZero<$t>> for $t {
fn eq(&self, other: &NonZero<$t>) -> bool {
let other: &$t = other.as_ref();
self == other
}
}
impl<E: Curve> cmp::PartialOrd<NonZero<$t>> for $t {
fn partial_cmp(&self, other: &NonZero<$t>) -> Option<cmp::Ordering> {
let other: &$t = other.as_ref();
self.partial_cmp(other)
}
}
)*};
}
impl_reverse_partial_eq_cmp!(Point<E>, Scalar<E>);
impl<T: ConstantTimeEq> ConstantTimeEq for NonZero<T> {
fn ct_eq(&self, other: &Self) -> subtle::Choice {
self.as_ref().ct_eq(other.as_ref())
}
}
#[cfg(all(test, feature = "serde"))]
mod non_zero_is_serializable {
use crate::{Curve, NonZero, Point, Scalar, SecretScalar};
fn impls_serde<T>()
where
T: serde::Serialize + serde::de::DeserializeOwned,
{
}
#[allow(dead_code)]
fn ensure_non_zero_is_serde<E: Curve>() {
impls_serde::<NonZero<Point<E>>>();
impls_serde::<NonZero<Scalar<E>>>();
impls_serde::<NonZero<SecretScalar<E>>>();
}
}