Skip to content
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
3 changes: 2 additions & 1 deletion k256/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ criterion = "0.3"
[features]
default = ["arithmetic", "std"]
arithmetic = []
digest = ["ecdsa/digest"]
field-montgomery = []
force-32-bit = []
rand = ["elliptic-curve/rand_core"]
sha256 = ["ecdsa/digest", "ecdsa/hazmat", "sha2"]
sha256 = ["digest", "ecdsa/hazmat", "sha2"]
test-vectors = []
std = ["elliptic-curve/std"]

Expand Down
18 changes: 16 additions & 2 deletions k256/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ use num_bigint::{BigUint, ToBigUint};
use core::ops::Neg;
use elliptic_curve::subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

#[cfg(feature = "zeroize")]
use zeroize::Zeroize;
#[cfg(feature = "digest")]
use ecdsa::signature::digest::{consts::U32, Digest};

#[cfg(feature = "rand")]
use elliptic_curve::rand_core::{CryptoRng, RngCore};

#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

/// An element in the finite field modulo curve order.
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
Expand Down Expand Up @@ -71,6 +74,17 @@ impl Scalar {
CtOption::map(value, Self)
}

/// Convert the output of a digest algorithm into a [`Scalar`] reduced
/// modulo n.
#[cfg(feature = "digest")]
#[cfg_attr(docsrs, doc(cfg(feature = "digest")))]
pub fn from_digest<D>(digest: D) -> Self
where
D: Digest<OutputSize = U32>,
{
Self(ScalarImpl::from_bytes_reduced(&digest.finalize().into()))
}

/// Returns the SEC-1 encoding of this scalar.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes()
Expand Down
17 changes: 17 additions & 0 deletions k256/src/arithmetic/scalar/scalar_4x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ impl Scalar4x64 {
CtOption::new(Self(w), underflow)
}

/// Parses the given byte array as a scalar.
///
/// Subtracts the modulus when the byte array is larger than the modulus.
#[cfg(feature = "digest")]
pub fn from_bytes_reduced(bytes: &[u8; 32]) -> Self {
// Interpret the bytes as a big-endian integer w.
let w3 = u64::from_be_bytes(bytes[0..8].try_into().unwrap());
let w2 = u64::from_be_bytes(bytes[8..16].try_into().unwrap());
let w1 = u64::from_be_bytes(bytes[16..24].try_into().unwrap());
let w0 = u64::from_be_bytes(bytes[24..32].try_into().unwrap());
let w = [w0, w1, w2, w3];

// If w is in the range [0, n) then w - n will underflow
let (r2, underflow) = sbb_array_with_underflow(&w, &MODULUS);
Self(conditional_select(&w, &r2, !underflow))
}

/// Returns the SEC-1 encoding of this scalar.
pub fn to_bytes(&self) -> [u8; 32] {
let mut ret = [0; 32];
Expand Down
21 changes: 21 additions & 0 deletions k256/src/arithmetic/scalar/scalar_8x32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,27 @@ impl Scalar8x32 {
CtOption::new(Self(w), underflow)
}

/// Parses the given byte array as a scalar.
///
/// Subtracts the modulus when the byte array is larger than the modulus.
#[cfg(feature = "digest")]
pub fn from_bytes_reduced(bytes: &[u8; 32]) -> Self {
// Interpret the bytes as a big-endian integer w.
let w7 = u32::from_be_bytes(bytes[0..4].try_into().unwrap());
let w6 = u32::from_be_bytes(bytes[4..8].try_into().unwrap());
let w5 = u32::from_be_bytes(bytes[8..12].try_into().unwrap());
let w4 = u32::from_be_bytes(bytes[12..16].try_into().unwrap());
let w3 = u32::from_be_bytes(bytes[16..20].try_into().unwrap());
let w2 = u32::from_be_bytes(bytes[20..24].try_into().unwrap());
let w1 = u32::from_be_bytes(bytes[24..28].try_into().unwrap());
let w0 = u32::from_be_bytes(bytes[28..32].try_into().unwrap());
let w = [w0, w1, w2, w3, w4, w5, w6, w7];

// If w is in the range [0, n) then w - n will underflow
let (r2, underflow) = sbb_array_with_underflow(&w, &MODULUS);
Self(conditional_select(&w, &r2, !underflow))
}

/// Returns the SEC-1 encoding of this scalar.
pub fn to_bytes(&self) -> [u8; 32] {
let mut ret = [0; 32];
Expand Down