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
4 changes: 3 additions & 1 deletion elliptic-curve/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::{
sec1::{CompressedPoint, FromEncodedPoint, ToEncodedPoint},
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
zeroize::DefaultIsZeroes,
Curve, CurveArithmetic, PrimeCurve,
Curve, CurveArithmetic, FieldBytesEncoding, PrimeCurve,
};
use core::{
iter::{Product, Sum},
Expand Down Expand Up @@ -339,6 +339,8 @@ impl Reduce<U256> for Scalar {
}
}

impl FieldBytesEncoding<MockCurve> for U256 {}

impl From<u64> for Scalar {
fn from(n: u64) -> Scalar {
Self(n.into())
Expand Down
44 changes: 42 additions & 2 deletions elliptic-curve/src/field.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,50 @@
//! Field elements.

use crate::Curve;
use generic_array::GenericArray;
use crate::{
bigint::{ArrayEncoding, ByteArray, Integer},
Curve,
};
use generic_array::{typenum::Unsigned, GenericArray};

/// Size of serialized field elements of this elliptic curve.
pub type FieldBytesSize<C> = <C as Curve>::FieldBytesSize;

/// Byte representation of a base/scalar field element of a given curve.
pub type FieldBytes<C> = GenericArray<u8, FieldBytesSize<C>>;

/// Trait for decoding/encoding `Curve::Uint` from/to [`FieldBytes`] using
/// curve-specific rules.
///
/// Namely a curve's modulus may be smaller than the big integer type used to
/// internally represent field elements (since the latter are multiples of the
/// limb size), such as in the case of curves like NIST P-224 and P-521, and so
/// it may need to be padded/truncated to the right length.
///
/// Additionally, different curves have different endianness conventions, also
/// captured here.
pub trait FieldBytesEncoding<C>: ArrayEncoding + Integer
where
C: Curve,
{
/// Decode unsigned integer from serialized field element.
///
/// The default implementation assumes a big endian encoding.
fn decode_field_bytes(field_bytes: &FieldBytes<C>) -> Self {
debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);
let mut byte_array = ByteArray::<Self>::default();
byte_array[..field_bytes.len()].copy_from_slice(field_bytes);
Self::from_be_byte_array(byte_array)
}

/// Encode unsigned integer into serialized field element.
///
/// The default implementation assumes a big endian encoding.
fn encode_field_bytes(&self) -> FieldBytes<C> {
let mut field_bytes = FieldBytes::<C>::default();
debug_assert!(field_bytes.len() <= Self::ByteSize::USIZE);

let len = field_bytes.len();
field_bytes.copy_from_slice(&self.to_be_byte_array()[..len]);
field_bytes
}
}
30 changes: 4 additions & 26 deletions elliptic-curve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ mod voprf;

pub use crate::{
error::{Error, Result},
field::{FieldBytes, FieldBytesSize},
field::{FieldBytes, FieldBytesEncoding, FieldBytesSize},
scalar::ScalarPrimitive,
secret_key::SecretKey,
};
Expand Down Expand Up @@ -140,8 +140,7 @@ use core::{
fmt::Debug,
ops::{Add, ShrAssign},
};
use crypto_bigint::{ArrayEncoding, ByteArray};
use generic_array::{typenum::Unsigned, ArrayLength};
use generic_array::ArrayLength;

/// Algorithm [`ObjectIdentifier`][`pkcs8::ObjectIdentifier`] for elliptic
/// curve public key cryptography (`id-ecPublicKey`).
Expand All @@ -167,7 +166,7 @@ pub trait Curve: 'static + Copy + Clone + Debug + Default + Eq + Ord + Send + Sy
type FieldBytesSize: ArrayLength<u8> + Add + Eq;

/// Integer type used to represent field elements of this elliptic curve.
type Uint: ArrayEncoding
type Uint: bigint::ArrayEncoding
+ bigint::AddMod<Output = Self::Uint>
+ bigint::Encoding
+ bigint::Integer
Expand All @@ -176,33 +175,12 @@ pub trait Curve: 'static + Copy + Clone + Debug + Default + Eq + Ord + Send + Sy
+ bigint::RandomMod
+ bigint::SubMod<Output = Self::Uint>
+ zeroize::Zeroize
+ FieldBytesEncoding<Self>
+ ShrAssign<usize>;

/// Order of this elliptic curve, i.e. number of elements in the scalar
/// field.
const ORDER: Self::Uint;

/// Decode unsigned integer from serialized field element.
///
/// The default implementation assumes a big endian encoding.
fn decode_field_bytes(field_bytes: &FieldBytes<Self>) -> Self::Uint {
debug_assert!(field_bytes.len() <= <Self::Uint as ArrayEncoding>::ByteSize::USIZE);
let mut byte_array = ByteArray::<Self::Uint>::default();
byte_array[..field_bytes.len()].copy_from_slice(field_bytes);
Self::Uint::from_be_byte_array(byte_array)
}

/// Encode unsigned integer into serialized field element.
///
/// The default implementation assumes a big endian encoding.
fn encode_field_bytes(uint: &Self::Uint) -> FieldBytes<Self> {
let mut field_bytes = FieldBytes::<Self>::default();
debug_assert!(field_bytes.len() <= <Self::Uint as ArrayEncoding>::ByteSize::USIZE);

let len = field_bytes.len();
field_bytes.copy_from_slice(&uint.to_be_byte_array()[..len]);
field_bytes
}
}

/// Marker trait for elliptic curves with prime order.
Expand Down
6 changes: 3 additions & 3 deletions elliptic-curve/src/scalar/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
bigint::{prelude::*, Limb, NonZero},
scalar::FromUintUnchecked,
scalar::IsHigh,
Curve, Error, FieldBytes, Result,
Curve, Error, FieldBytes, FieldBytesEncoding, Result,
};
use base16ct::HexDisplay;
use core::{
Expand Down Expand Up @@ -78,7 +78,7 @@ where

/// Decode [`ScalarPrimitive`] from a serialized field element
pub fn from_bytes(bytes: &FieldBytes<C>) -> CtOption<Self> {
Self::new(C::decode_field_bytes(bytes))
Self::new(C::Uint::decode_field_bytes(bytes))
}

/// Decode [`ScalarPrimitive`] from a big endian byte slice.
Expand Down Expand Up @@ -117,7 +117,7 @@ where

/// Encode [`ScalarPrimitive`] as a serialized field element.
pub fn to_bytes(&self) -> FieldBytes<C> {
C::encode_field_bytes(&self.inner)
self.inner.encode_field_bytes()
}

/// Convert to a `C::Uint`.
Expand Down