diff --git a/k256/src/arithmetic/field.rs b/k256/src/arithmetic/field.rs index 0f073527a..0d11ed014 100644 --- a/k256/src/arithmetic/field.rs +++ b/k256/src/arithmetic/field.rs @@ -29,13 +29,16 @@ use core::{ use elliptic_curve::{ Generate, bigint::{Odd, U256, modular::Retrieve}, - ff::{self, Field, PrimeField}, + ff::{self, Field, FromUniformBytes, PrimeField}, ops::Invert, rand_core::{TryCryptoRng, TryRng}, subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}, zeroize::DefaultIsZeroes, }; +#[cfg(feature = "bits")] +use {crate::ScalarBits, elliptic_curve::group::ff::PrimeFieldBits}; + #[cfg(test)] use num_bigint::{BigUint, ToBigUint}; @@ -324,6 +327,33 @@ impl PrimeField for FieldElement { } } +impl FromUniformBytes<64> for FieldElement { + fn from_uniform_bytes(bytes: &[u8; 64]) -> Self { + let hi = U256::from_be_slice(&bytes[..32]); + let lo = U256::from_be_slice(&bytes[32..]); + let modulus = const { *Odd::from_be_hex(MODULUS_HEX).as_nz_ref() }; + Self(FieldElementImpl::from_u256_unchecked( + U256::rem_wide_vartime((lo, hi), &modulus), + )) + } +} + +#[cfg(feature = "bits")] +impl PrimeFieldBits for FieldElement { + cpubits! { + 32 => { type ReprBits = [u32; 8]; } + 64 => { type ReprBits = [u64; 4]; } + } + + fn to_le_bits(&self) -> ScalarBits { + self.into() + } + + fn char_le_bits() -> ScalarBits { + U256::from_be_hex(MODULUS_HEX).to_words().into() + } +} + impl Retrieve for FieldElement { type Output = U256; @@ -509,6 +539,13 @@ impl<'a> Product<&'a FieldElement> for FieldElement { } } +#[cfg(feature = "bits")] +impl From<&FieldElement> for ScalarBits { + fn from(scalar: &FieldElement) -> ScalarBits { + scalar.0.to_u256().to_words().into() + } +} + #[cfg(test)] mod tests { use elliptic_curve::Generate;