Skip to content

Commit

Permalink
elliptic-curve: add scalar::IsHigh trait (#814)
Browse files Browse the repository at this point in the history
Adds a trait for determining if a given scalar is larger than the order
divided by 2.

This is useful for "normalization" use cases such as low-S normalized
ECDSA signatures, where a scalar is conditionally negated if "high".
  • Loading branch information
tarcieri authored Nov 17, 2021
1 parent 5c7394c commit 0b26502
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 8 deletions.
8 changes: 4 additions & 4 deletions elliptic-curve/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion elliptic-curve/src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Elliptic curve arithmetic traits.
use crate::{Curve, FieldBytes, PrimeCurve, ScalarCore};
use crate::{Curve, FieldBytes, IsHigh, PrimeCurve, ScalarCore};
use core::fmt::Debug;
use subtle::{ConditionallySelectable, ConstantTimeEq};
use zeroize::DefaultIsZeroes;
Expand Down Expand Up @@ -77,6 +77,7 @@ pub trait ScalarArithmetic: Curve {
+ From<ScalarCore<Self>>
+ Into<FieldBytes<Self>>
+ Into<Self::UInt>
+ IsHigh
+ ff::Field
+ ff::PrimeField<Repr = FieldBytes<Self>>;
}
8 changes: 7 additions & 1 deletion elliptic-curve/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
sec1::{FromEncodedPoint, ToEncodedPoint},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
zeroize::DefaultIsZeroes,
AffineArithmetic, AlgorithmParameters, Curve, PrimeCurve, ProjectiveArithmetic,
AffineArithmetic, AlgorithmParameters, Curve, IsHigh, PrimeCurve, ProjectiveArithmetic,
ScalarArithmetic,
};
use core::{
Expand Down Expand Up @@ -346,6 +346,12 @@ impl From<&Scalar> for FieldBytes {
}
}

impl IsHigh for Scalar {
fn is_high(&self) -> Choice {
self.0.is_high()
}
}

/// Example affine point type
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AffinePoint {
Expand Down
2 changes: 1 addition & 1 deletion elliptic-curve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ mod jwk;
pub use crate::{
error::{Error, Result},
point::{DecompactPoint, DecompressPoint, PointCompaction, PointCompression},
scalar::core::ScalarCore,
scalar::{core::ScalarCore, IsHigh},
secret_key::SecretKey,
};
pub use crypto_bigint as bigint;
Expand Down
13 changes: 13 additions & 0 deletions elliptic-curve/src/scalar.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Scalar types.
use subtle::Choice;

pub(crate) mod core;

#[cfg(feature = "arithmetic")]
Expand All @@ -17,3 +19,14 @@ pub type Scalar<C> = <C as ScalarArithmetic>::Scalar;
#[cfg(feature = "bits")]
#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
pub type ScalarBits<C> = ff::FieldBits<<Scalar<C> as ff::PrimeFieldBits>::ReprBits>;

/// Is this scalar greater than n / 2?
///
/// # Returns
///
/// - For scalars 0 through n / 2: `Choice::from(0)`
/// - For scalars (n / 2) + 1 through n - 1: `Choice::from(1)`
pub trait IsHigh {
/// Is this scalar greater than or equal to n / 2?
fn is_high(&self) -> Choice;
}
12 changes: 11 additions & 1 deletion elliptic-curve/src/scalar/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
CtOption,
},
Curve, Error, FieldBytes, Result,
Curve, Error, FieldBytes, IsHigh, Result,
};
use core::{
cmp::Ordering,
Expand Down Expand Up @@ -337,3 +337,13 @@ where
-*self
}
}

impl<C> IsHigh for ScalarCore<C>
where
C: Curve,
{
fn is_high(&self) -> Choice {
let n_2 = C::ORDER >> 1;
self.inner.ct_gt(&n_2)
}
}

0 comments on commit 0b26502

Please sign in to comment.