Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

k256+p256: impl Reduce trait on Scalar types #436

Merged
merged 1 commit into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions k256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use elliptic_curve::{
bigint::{limb, nlimbs, ArrayEncoding, Encoding, Limb, U256},
generic_array::arr,
group::ff::{Field, PrimeField},
ops::Reduce,
rand_core::{CryptoRng, RngCore},
subtle::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
Expand Down Expand Up @@ -210,16 +211,6 @@ impl Scalar {
/// Multiplicative identity.
pub const ONE: Self = Self(U256::ONE);

/// Parses the given byte array as a scalar.
///
/// Subtracts the modulus when the byte array is larger than the modulus.
pub fn from_bytes_reduced(bytes: &FieldBytes) -> Self {
let w = U256::from_be_slice(bytes);
let (r, underflow) = w.sbb(&ORDER, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BIT_SIZE - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow))
}

/// Is this scalar greater than or equal to n / 2?
pub fn is_high(&self) -> Choice {
self.0.ct_gt(&FRAC_MODULUS_2)
Expand Down Expand Up @@ -398,7 +389,7 @@ impl FromDigest<Secp256k1> for Scalar {
where
D: Digest<OutputSize = U32>,
{
Self::from_bytes_reduced(&digest.finalize())
Self::from_be_bytes_reduced(digest.finalize())
}
}

Expand Down Expand Up @@ -570,6 +561,14 @@ impl MulAssign<&Scalar> for Scalar {
}
}

impl Reduce<U256> for Scalar {
fn from_uint_reduced(w: U256) -> Self {
let (r, underflow) = w.sbb(&ORDER, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BIT_SIZE - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow))
}
}

#[cfg(feature = "bits")]
#[cfg_attr(docsrs, doc(cfg(feature = "bits")))]
impl From<&Scalar> for ScalarBits {
Expand Down
9 changes: 7 additions & 2 deletions k256/src/ecdsa/recoverable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ use crate::{
signature::{digest::Digest, DigestVerifier},
VerifyingKey,
},
elliptic_curve::{consts::U32, ops::Invert, subtle::Choice, DecompressPoint},
elliptic_curve::{
consts::U32,
ops::{Invert, Reduce},
subtle::Choice,
DecompressPoint,
},
lincomb, AffinePoint, FieldBytes, NonZeroScalar, ProjectivePoint, Scalar,
};

Expand Down Expand Up @@ -170,7 +175,7 @@ impl Signature {
) -> Result<VerifyingKey, Error> {
let r = self.r();
let s = self.s();
let z = Scalar::from_bytes_reduced(digest_bytes);
let z = Scalar::from_be_bytes_reduced(*digest_bytes);
let R = AffinePoint::decompress(&r.to_bytes(), self.recovery_id().is_y_odd());

if R.is_some().into() {
Expand Down
4 changes: 2 additions & 2 deletions k256/src/ecdsa/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use ecdsa_core::{
};
use elliptic_curve::{
consts::U32,
ops::Invert,
ops::{Invert, Reduce},
rand_core::{CryptoRng, RngCore},
subtle::{Choice, ConstantTimeEq},
};
Expand Down Expand Up @@ -181,7 +181,7 @@ impl RecoverableSignPrimitive<Secp256k1> for Scalar {

// Lift x-coordinate of 𝐑 (element of base field) into a serialized big
// integer, then reduce it into an element of the scalar field
let r = Scalar::from_bytes_reduced(&R.x.to_bytes());
let r = Scalar::from_be_bytes_reduced(R.x.to_bytes());

// Compute `s` as a signature over `r` and `z`.
let s = k_inverse * (z + (r * self));
Expand Down
8 changes: 6 additions & 2 deletions k256/src/ecdsa/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ use crate::{
};
use core::convert::TryFrom;
use ecdsa_core::{hazmat::VerifyPrimitive, signature};
use elliptic_curve::{consts::U32, ops::Invert, sec1::ToEncodedPoint};
use elliptic_curve::{
consts::U32,
ops::{Invert, Reduce},
sec1::ToEncodedPoint,
};
use signature::{digest::Digest, DigestVerifier};

#[cfg(feature = "sha256")]
Expand Down Expand Up @@ -100,7 +104,7 @@ impl VerifyPrimitive<Secp256k1> for AffinePoint {
.to_affine()
.x;

if Scalar::from_bytes_reduced(&x.to_bytes()).eq(&r) {
if Scalar::from_be_bytes_reduced(x.to_bytes()).eq(&r) {
Ok(())
} else {
Err(Error::new())
Expand Down
21 changes: 10 additions & 11 deletions p256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use elliptic_curve::{
bigint::{ArrayEncoding, Encoding, Limb, U256},
generic_array::arr,
group::ff::{Field, PrimeField},
ops::Reduce,
rand_core::RngCore,
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeLess, CtOption},
zeroize::DefaultIsZeroes,
Expand Down Expand Up @@ -224,16 +225,6 @@ impl Scalar {
/// Multiplicative identity.
pub const ONE: Self = Self(U256::ONE);

/// Parses the given byte array as a scalar.
///
/// Subtracts the modulus when decoded integer is larger than the modulus.
pub fn from_bytes_reduced(bytes: &FieldBytes) -> Self {
let w = U256::from_be_slice(bytes);
let (r, underflow) = w.sbb(&NistP256::ORDER, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BIT_SIZE - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow))
}

/// Returns the SEC1 encoding of this scalar.
pub fn to_bytes(&self) -> FieldBytes {
self.0.to_be_byte_array()
Expand Down Expand Up @@ -592,7 +583,7 @@ impl FromDigest<NistP256> for Scalar {
where
D: Digest<OutputSize = U32>,
{
Self::from_bytes_reduced(&digest.finalize())
Self::from_be_bytes_reduced(digest.finalize())
}
}

Expand Down Expand Up @@ -720,6 +711,14 @@ impl<'a> Neg for &'a Scalar {
}
}

impl Reduce<U256> for Scalar {
fn from_uint_reduced(w: U256) -> Self {
let (r, underflow) = w.sbb(&NistP256::ORDER, Limb::ZERO);
let underflow = Choice::from((underflow.0 >> (Limb::BIT_SIZE - 1)) as u8);
Self(U256::conditional_select(&w, &r, !underflow))
}
}

impl ConditionallySelectable for Scalar {
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
Self(U256::conditional_select(&a.0, &b.0, choice))
Expand Down
9 changes: 6 additions & 3 deletions p256/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ use {
crate::{AffinePoint, ProjectivePoint, Scalar},
core::borrow::Borrow,
ecdsa_core::hazmat::{SignPrimitive, VerifyPrimitive},
elliptic_curve::{group::ff::Field, ops::Invert},
elliptic_curve::{
group::ff::Field,
ops::{Invert, Reduce},
},
};

/// ECDSA/P-256 signature (fixed-size)
Expand Down Expand Up @@ -94,7 +97,7 @@ impl SignPrimitive<NistP256> for Scalar {

// Lift `x` (element of base field) to serialized big endian integer,
// then reduce it to an element of the scalar field
let r = Scalar::from_bytes_reduced(&x.to_bytes());
let r = Scalar::from_be_bytes_reduced(x.to_bytes());

// Compute `s` as a signature over `r` and `z`.
let s = k_inverse * (z + &(r * self));
Expand All @@ -120,7 +123,7 @@ impl VerifyPrimitive<NistP256> for AffinePoint {
.to_affine()
.x;

if Scalar::from_bytes_reduced(&x.to_bytes()) == *r {
if Scalar::from_be_bytes_reduced(x.to_bytes()) == *r {
Ok(())
} else {
Err(Error::new())
Expand Down