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
6 changes: 4 additions & 2 deletions elliptic-curve/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use crate::{
bigint::{Limb, U256},
error::{Error, Result},
generic_array::typenum::U32,
ops::{LinearCombination, MulByGenerator, Reduce, Shr1},
pkcs8,
rand_core::RngCore,
Expand Down Expand Up @@ -65,6 +66,7 @@ pub type ScalarBits = crate::ScalarBits<MockCurve>;
pub struct MockCurve;

impl Curve for MockCurve {
type FieldBytesSize = U32;
type Uint = U256;

const ORDER: U256 =
Expand Down Expand Up @@ -150,11 +152,11 @@ impl PrimeField for Scalar {
const DELTA: Self = Self::ZERO; // BOGUS!

fn from_repr(bytes: FieldBytes) -> CtOption<Self> {
ScalarPrimitive::from_be_bytes(bytes).map(Self)
ScalarPrimitive::from_bytes(&bytes).map(Self)
}

fn to_repr(&self) -> FieldBytes {
self.0.to_be_bytes()
self.0.to_bytes()
}

fn is_odd(&self) -> Choice {
Expand Down
10 changes: 10 additions & 0 deletions elliptic-curve/src/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Field elements.

use crate::Curve;
use generic_array::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>>;
30 changes: 15 additions & 15 deletions elliptic-curve/src/jwk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use crate::{
sec1::{Coordinates, EncodedPoint, ModulusSize, ValidatePublicKey},
secret_key::SecretKey,
Curve, Error, FieldBytes, FieldSize, Result,
Curve, Error, FieldBytes, FieldBytesSize, Result,
};
use alloc::{
borrow::ToOwned,
Expand Down Expand Up @@ -112,7 +112,7 @@ impl JwkEcKey {
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
PublicKey::from_sec1_bytes(self.to_encoded_point::<C>()?.as_bytes())
}
Expand All @@ -121,7 +121,7 @@ impl JwkEcKey {
pub fn from_encoded_point<C>(point: &EncodedPoint<C>) -> Option<Self>
where
C: Curve + JwkParameters,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
match point.coordinates() {
Coordinates::Uncompressed { x, y } => Some(JwkEcKey {
Expand All @@ -138,7 +138,7 @@ impl JwkEcKey {
pub fn to_encoded_point<C>(&self) -> Result<EncodedPoint<C>>
where
C: Curve + JwkParameters,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
if self.crv != C::CRV {
return Err(Error);
Expand All @@ -154,7 +154,7 @@ impl JwkEcKey {
pub fn to_secret_key<C>(&self) -> Result<SecretKey<C>>
where
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
self.try_into()
}
Expand All @@ -177,7 +177,7 @@ impl ToString for JwkEcKey {
impl<C> TryFrom<JwkEcKey> for SecretKey<C>
where
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
type Error = Error;

Expand All @@ -189,15 +189,15 @@ where
impl<C> TryFrom<&JwkEcKey> for SecretKey<C>
where
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
type Error = Error;

fn try_from(jwk: &JwkEcKey) -> Result<SecretKey<C>> {
if let Some(d_base64) = &jwk.d {
let pk = jwk.to_encoded_point::<C>()?;
let mut d_bytes = decode_base64url_fe::<C>(d_base64)?;
let result = SecretKey::from_be_bytes(&d_bytes);
let result = SecretKey::from_slice(&d_bytes);
d_bytes.zeroize();

result.and_then(|secret_key| {
Expand All @@ -215,7 +215,7 @@ impl<C> From<SecretKey<C>> for JwkEcKey
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
fn from(sk: SecretKey<C>) -> JwkEcKey {
(&sk).into()
Expand All @@ -227,11 +227,11 @@ impl<C> From<&SecretKey<C>> for JwkEcKey
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
fn from(sk: &SecretKey<C>) -> JwkEcKey {
let mut jwk = sk.public_key().to_jwk();
let mut d = sk.to_be_bytes();
let mut d = sk.to_bytes();
jwk.d = Some(Base64Url::encode_string(&d));
d.zeroize();
jwk
Expand All @@ -243,7 +243,7 @@ impl<C> TryFrom<JwkEcKey> for PublicKey<C>
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
type Error = Error;

Expand All @@ -257,7 +257,7 @@ impl<C> TryFrom<&JwkEcKey> for PublicKey<C>
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
type Error = Error;

Expand All @@ -271,7 +271,7 @@ impl<C> From<PublicKey<C>> for JwkEcKey
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
fn from(pk: PublicKey<C>) -> JwkEcKey {
(&pk).into()
Expand All @@ -283,7 +283,7 @@ impl<C> From<&PublicKey<C>> for JwkEcKey
where
C: CurveArithmetic + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
FieldBytesSize<C>: ModulusSize,
{
fn from(pk: &PublicKey<C>) -> JwkEcKey {
Self::from_encoded_point::<C>(&pk.to_encoded_point(false)).expect("JWK encoding error")
Expand Down
91 changes: 50 additions & 41 deletions elliptic-curve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
//! - [`bp256`]: brainpoolP256r1 and brainpoolP256t1
//! - [`bp384`]: brainpoolP384r1 and brainpoolP384t1
//! - [`k256`]: secp256k1 a.k.a. K-256
//! - [`p224`]: NIST P-224 a.k.a. secp224r1
//! - [`p256`]: NIST P-256 a.k.a secp256r1, prime256v1
//! - [`p384`]: NIST P-384 a.k.a. secp384r1
//! - [`p521`]: NIST P-521 a.k.a. secp521r1
//!
//! The [`ecdsa`] crate provides a generic implementation of the
//! Elliptic Curve Digital Signature Algorithm which can be used with any of
Expand Down Expand Up @@ -57,8 +59,10 @@
//! [`bp256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/bp256
//! [`bp384`]: https://github.com/RustCrypto/elliptic-curves/tree/master/bp384
//! [`k256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/k256
//! [`p224`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p224
//! [`p256`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p256
//! [`p384`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p384
//! [`p521`]: https://github.com/RustCrypto/elliptic-curves/tree/master/p521
//! [`ecdsa`]: https://github.com/RustCrypto/signatures/tree/master/ecdsa

#[cfg(feature = "alloc")]
Expand All @@ -84,6 +88,7 @@ pub mod sec1;
pub mod weierstrass;

mod error;
mod field;
mod secret_key;

#[cfg(feature = "arithmetic")]
Expand All @@ -94,8 +99,12 @@ mod public_key;
#[cfg(feature = "jwk")]
mod jwk;

#[cfg(feature = "voprf")]
mod voprf;

pub use crate::{
error::{Error, Result},
field::{FieldBytes, FieldBytesSize},
point::{
AffineXCoordinate, AffineYIsOdd, DecompactPoint, DecompressPoint, PointCompaction,
PointCompression,
Expand All @@ -113,6 +122,7 @@ pub use zeroize;
pub use {
crate::{
arithmetic::{CurveArithmetic, PrimeCurveArithmetic},
point::{AffinePoint, ProjectivePoint},
public_key::PublicKey,
scalar::{NonZeroScalar, Scalar},
},
Expand All @@ -129,8 +139,15 @@ pub use crate::jwk::{JwkEcKey, JwkParameters};
#[cfg(feature = "pkcs8")]
pub use pkcs8;

use core::{fmt::Debug, ops::ShrAssign};
use generic_array::GenericArray;
#[cfg(feature = "voprf")]
pub use crate::voprf::VoprfParameters;

use core::{
fmt::Debug,
ops::{Add, ShrAssign},
};
use crypto_bigint::{ArrayEncoding, ByteArray};
use generic_array::{typenum::Unsigned, ArrayLength};

/// Algorithm [`ObjectIdentifier`][`pkcs8::ObjectIdentifier`] for elliptic
/// curve public key cryptography (`id-ecPublicKey`).
Expand All @@ -149,11 +166,15 @@ pub const ALGORITHM_OID: pkcs8::ObjectIdentifier =
/// be impl'd by these ZSTs, facilitating types which are generic over elliptic
/// curves (e.g. [`SecretKey`]).
pub trait Curve: 'static + Copy + Clone + Debug + Default + Eq + Ord + Send + Sync {
/// Size of a serialized field element in bytes.
///
/// This is typically the same as `Self::Uint::ByteSize` but for curves
/// with an unusual field modulus (e.g. P-224, P-521) it may be different.
type FieldBytesSize: ArrayLength<u8> + Add + Eq;

/// Integer type used to represent field elements of this elliptic curve.
// TODO(tarcieri): replace this with an e.g. `const Curve::MODULUS: Uint`.
// Requires rust-lang/rust#60551, i.e. `const_evaluatable_checked`
type Uint: bigint::AddMod<Output = Self::Uint>
+ bigint::ArrayEncoding
+ ArrayEncoding
+ bigint::Encoding
+ bigint::Integer
+ bigint::NegMod<Output = Self::Uint>
Expand All @@ -163,44 +184,32 @@ pub trait Curve: 'static + Copy + Clone + Debug + Default + Eq + Ord + Send + Sy
+ zeroize::Zeroize
+ ShrAssign<usize>;

/// Order constant.
///
/// Subdivided into either 32-bit or 64-bit "limbs" (depending on the
/// target CPU's word size), specified from least to most significant.
/// Order of this elliptic curve, i.e. number of elements in the scalar
/// field.
const ORDER: Self::Uint;
}

/// Marker trait for elliptic curves with prime order.
pub trait PrimeCurve: Curve {}

/// Size of field elements of this elliptic curve.
pub type FieldSize<C> = <<C as Curve>::Uint as bigint::ArrayEncoding>::ByteSize;

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

/// Affine point type for a given curve with a [`CurveArithmetic`]
/// implementation.
#[cfg(feature = "arithmetic")]
pub type AffinePoint<C> = <C as CurveArithmetic>::AffinePoint;

/// Projective point type for a given curve with a [`CurveArithmetic`]
/// implementation.
#[cfg(feature = "arithmetic")]
pub type ProjectivePoint<C> = <C as CurveArithmetic>::ProjectivePoint;

/// Elliptic curve parameters used by VOPRF.
#[cfg(feature = "voprf")]
pub trait VoprfParameters: Curve {
/// The `ID` parameter which identifies a particular elliptic curve
/// as defined in [section 4 of `draft-irtf-cfrg-voprf-08`][voprf].
/// Decode unsigned integer from serialized field element.
///
/// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-4
const ID: u16;

/// The `Hash` parameter which assigns a particular hash function to this
/// ciphersuite as defined in [section 4 of `draft-irtf-cfrg-voprf-08`][voprf].
/// 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.
///
/// [voprf]: https://www.ietf.org/archive/id/draft-irtf-cfrg-voprf-08.html#section-4
type Hash: digest::Digest;
/// 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.
pub trait PrimeCurve: Curve {}
12 changes: 11 additions & 1 deletion elliptic-curve/src/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@
mod non_identity;

#[cfg(feature = "arithmetic")]
pub use self::non_identity::NonIdentity;
pub use {self::non_identity::NonIdentity, crate::CurveArithmetic};

use crate::{Curve, FieldBytes};
use subtle::{Choice, CtOption};

/// Affine point type for a given curve with a [`CurveArithmetic`]
/// implementation.
#[cfg(feature = "arithmetic")]
pub type AffinePoint<C> = <C as CurveArithmetic>::AffinePoint;

/// Projective point type for a given curve with a [`CurveArithmetic`]
/// implementation.
#[cfg(feature = "arithmetic")]
pub type ProjectivePoint<C> = <C as CurveArithmetic>::ProjectivePoint;

/// Obtain the affine x-coordinate of an elliptic curve point.
pub trait AffineXCoordinate {
/// Field element representation.
Expand Down
Loading