Skip to content

Commit

Permalink
elliptic-curve: make FromEncodedPoint return a CtOption (#782)
Browse files Browse the repository at this point in the history
Internally `k256`/`p256` return a `CtOption` for this method, then
convert to an `Option`.

It would be helpful when implementing other traits from the `group`
crate, e.g. `GroupEncoding`, if this instead returned a `CtOption`.
  • Loading branch information
tarcieri authored Oct 2, 2021
1 parent fea0010 commit 23cddf0
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 67 deletions.
23 changes: 15 additions & 8 deletions elliptic-curve/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,13 @@ impl ConstantTimeEq for AffinePoint {
}

impl ConditionallySelectable for AffinePoint {
fn conditional_select(_a: &Self, _b: &Self, _choice: Choice) -> Self {
unimplemented!();
fn conditional_select(a: &Self, b: &Self, choice: Choice) -> Self {
// Not really constant time, but this is dev code
if choice.into() {
*b
} else {
*a
}
}
}

Expand All @@ -381,12 +386,14 @@ impl Default for AffinePoint {
impl DefaultIsZeroes for AffinePoint {}

impl FromEncodedPoint<MockCurve> for AffinePoint {
fn from_encoded_point(point: &EncodedPoint) -> Option<Self> {
if point.is_identity() {
Some(Self::Identity)
fn from_encoded_point(encoded_point: &EncodedPoint) -> CtOption<Self> {
let point = if encoded_point.is_identity() {
Self::Identity
} else {
Some(Self::Other(*point))
}
Self::Other(*encoded_point)
};

CtOption::new(point, Choice::from(1))
}
}

Expand Down Expand Up @@ -472,7 +479,7 @@ impl From<ProjectivePoint> for AffinePoint {
}

impl FromEncodedPoint<MockCurve> for ProjectivePoint {
fn from_encoded_point(_point: &EncodedPoint) -> Option<Self> {
fn from_encoded_point(_point: &EncodedPoint) -> CtOption<Self> {
unimplemented!();
}
}
Expand Down
41 changes: 14 additions & 27 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, PrimeCurve, Result,
Curve, Error, FieldBytes, FieldSize, Result,
};
use alloc::{
borrow::ToOwned,
Expand Down Expand Up @@ -114,7 +114,7 @@ impl JwkEcKey {
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn to_public_key<C>(&self) -> Result<PublicKey<C>>
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -124,7 +124,7 @@ impl JwkEcKey {
/// Create a JWK from a SEC1 [`EncodedPoint`].
pub fn from_encoded_point<C>(point: &EncodedPoint<C>) -> Option<Self>
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
FieldSize<C>: ModulusSize,
{
match point.coordinates() {
Expand All @@ -141,7 +141,7 @@ impl JwkEcKey {
/// Get the public key component of this JWK as a SEC1 [`EncodedPoint`].
pub fn to_encoded_point<C>(&self) -> Result<EncodedPoint<C>>
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
FieldSize<C>: ModulusSize,
{
if self.crv != C::CRV {
Expand All @@ -158,7 +158,7 @@ impl JwkEcKey {
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
pub fn to_secret_key<C>(&self) -> Result<SecretKey<C>>
where
C: PrimeCurve + JwkParameters + ValidatePublicKey,
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
{
self.try_into()
Expand All @@ -179,23 +179,10 @@ impl ToString for JwkEcKey {
}
}

#[cfg(feature = "arithmetic")]
#[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))]
impl<C> FromEncodedPoint<C> for JwkEcKey
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
fn from_encoded_point(point: &EncodedPoint<C>) -> Option<Self> {
Self::from_encoded_point::<C>(point)
}
}

#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<JwkEcKey> for SecretKey<C>
where
C: PrimeCurve + JwkParameters + ValidatePublicKey,
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
{
type Error = Error;
Expand All @@ -208,7 +195,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<&JwkEcKey> for SecretKey<C>
where
C: PrimeCurve + JwkParameters + ValidatePublicKey,
C: Curve + JwkParameters + ValidatePublicKey,
FieldSize<C>: ModulusSize,
{
type Error = Error;
Expand All @@ -235,7 +222,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<SecretKey<C>> for JwkEcKey
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -249,7 +236,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<&SecretKey<C>> for JwkEcKey
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -267,7 +254,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<JwkEcKey> for PublicKey<C>
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -283,7 +270,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> TryFrom<&JwkEcKey> for PublicKey<C>
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -299,7 +286,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<PublicKey<C>> for JwkEcKey
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -313,7 +300,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
impl<C> From<&PublicKey<C>> for JwkEcKey
where
C: PrimeCurve + JwkParameters + ProjectiveArithmetic,
C: Curve + JwkParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand Down Expand Up @@ -587,7 +574,7 @@ impl Serialize for JwkEcKey {
}

/// Decode a Base64url-encoded field element
fn decode_base64url_fe<C: PrimeCurve>(s: &str) -> Result<FieldBytes<C>> {
fn decode_base64url_fe<C: Curve>(s: &str) -> Result<FieldBytes<C>> {
let mut result = FieldBytes::<C>::default();
Base64Url::decode(s, &mut result).map_err(|_| Error)?;
Ok(result)
Expand Down
47 changes: 26 additions & 21 deletions elliptic-curve/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ use {core::str::FromStr, pkcs8::ToPublicKey};
use {
crate::{
sec1::{EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint},
FieldSize, PointCompression, PrimeCurve,
FieldSize, PointCompression,
},
core::cmp::Ordering,
subtle::CtOption,
};

#[cfg(any(feature = "jwk", feature = "pem"))]
Expand Down Expand Up @@ -96,12 +97,12 @@ where
#[cfg(feature = "sec1")]
pub fn from_sec1_bytes(bytes: &[u8]) -> Result<Self>
where
C: PrimeCurve,
C: Curve,
FieldSize<C>: ModulusSize,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
{
let point = EncodedPoint::<C>::from_bytes(bytes).map_err(|_| Error)?;
Self::from_encoded_point(&point).ok_or(Error)
Option::from(Self::from_encoded_point(&point)).ok_or(Error)
}

/// Borrow the inner [`AffinePoint`] from this [`PublicKey`].
Expand All @@ -121,7 +122,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk(jwk: &JwkEcKey) -> Result<Self>
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -133,7 +134,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn from_jwk_str(jwk: &str) -> Result<Self>
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -145,7 +146,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk(&self) -> JwkEcKey
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -157,7 +158,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "jwk")))]
pub fn to_jwk_string(&self) -> String
where
C: PrimeCurve + JwkParameters,
C: Curve + JwkParameters,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -180,22 +181,24 @@ impl<C> Copy for PublicKey<C> where C: Curve + ProjectiveArithmetic {}
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> FromEncodedPoint<C> for PublicKey<C>
where
C: PrimeCurve + ProjectiveArithmetic,
C: Curve + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
/// Initialize [`PublicKey`] from an [`EncodedPoint`]
fn from_encoded_point(encoded_point: &EncodedPoint<C>) -> Option<Self> {
AffinePoint::<C>::from_encoded_point(encoded_point)
.and_then(|point| PublicKey::from_affine(point).ok())
fn from_encoded_point(encoded_point: &EncodedPoint<C>) -> CtOption<Self> {
AffinePoint::<C>::from_encoded_point(encoded_point).and_then(|point| {
let is_identity = ProjectivePoint::<C>::from(point).is_identity();
CtOption::new(PublicKey { point }, !is_identity)
})
}
}

#[cfg(feature = "sec1")]
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> ToEncodedPoint<C> for PublicKey<C>
where
C: PrimeCurve + ProjectiveArithmetic,
C: Curve + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -210,7 +213,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> From<PublicKey<C>> for EncodedPoint<C>
where
C: PrimeCurve + ProjectiveArithmetic + PointCompression,
C: Curve + ProjectiveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -223,7 +226,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> From<&PublicKey<C>> for EncodedPoint<C>
where
C: PrimeCurve + ProjectiveArithmetic + PointCompression,
C: Curve + ProjectiveArithmetic + PointCompression,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -236,7 +239,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> PartialOrd for PublicKey<C>
where
C: PrimeCurve + ProjectiveArithmetic,
C: Curve + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -249,7 +252,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "sec1")))]
impl<C> Ord for PublicKey<C>
where
C: PrimeCurve + ProjectiveArithmetic,
C: Curve + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -265,7 +268,7 @@ where
#[cfg_attr(docsrs, doc(cfg(all(feature = "pkcs8", feature = "sec1"))))]
impl<C> FromPublicKey for PublicKey<C>
where
C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
C: Curve + AlgorithmParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -292,7 +295,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> ToPublicKey for PublicKey<C>
where
C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
C: Curve + AlgorithmParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -311,7 +314,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> FromStr for PublicKey<C>
where
C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
C: Curve + AlgorithmParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -326,7 +329,7 @@ where
#[cfg_attr(docsrs, doc(cfg(feature = "pem")))]
impl<C> ToString for PublicKey<C>
where
C: PrimeCurve + AlgorithmParameters + ProjectiveArithmetic,
C: Curve + AlgorithmParameters + ProjectiveArithmetic,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
Expand All @@ -345,6 +348,8 @@ mod tests {
#[test]
fn from_encoded_point_rejects_identity() {
let identity = EncodedPoint::identity();
assert_eq!(PublicKey::from_encoded_point(&identity), None);
assert!(bool::from(
PublicKey::from_encoded_point(&identity).is_none()
));
}
}
Loading

0 comments on commit 23cddf0

Please sign in to comment.