Skip to content
Closed
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
7 changes: 6 additions & 1 deletion elliptic-curve/src/ecdh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ where
#[allow(clippy::op_ref)]
let shared_secret = public_key.to_projective() * &*self.scalar;
// SharedSecret::new expects an uncompressed point
SharedSecret::new(shared_secret.to_affine().to_encoded_point(false))
SharedSecret::new(
shared_secret
.to_affine()
.to_encoded_point(false)
.expect("secret is identity"),
)
}
}

Expand Down
18 changes: 11 additions & 7 deletions elliptic-curve/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ where
}
}

impl<C> From<PublicKey<C>> for EncodedPoint<C>
impl<C> TryFrom<PublicKey<C>> for EncodedPoint<C>
where
C: Curve + ProjectiveArithmetic + point::Compression,
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Expand All @@ -162,12 +162,14 @@ where
UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
UncompressedPointSize<C>: ArrayLength<u8>,
{
fn from(public_key: PublicKey<C>) -> EncodedPoint<C> {
EncodedPoint::<C>::from(&public_key)
type Error = Error;

fn try_from(public_key: PublicKey<C>) -> Result<EncodedPoint<C>, Error> {
EncodedPoint::<C>::try_from(&public_key)
}
}

impl<C> From<&PublicKey<C>> for EncodedPoint<C>
impl<C> TryFrom<&PublicKey<C>> for EncodedPoint<C>
where
C: Curve + ProjectiveArithmetic + point::Compression,
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Expand All @@ -177,8 +179,10 @@ where
UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
UncompressedPointSize<C>: ArrayLength<u8>,
{
fn from(public_key: &PublicKey<C>) -> EncodedPoint<C> {
public_key.to_encoded_point(C::COMPRESS_POINTS)
type Error = Error;

fn try_from(public_key: &PublicKey<C>) -> Result<EncodedPoint<C>, Error> {
public_key.to_encoded_point(C::COMPRESS_POINTS).ok_or(Error)
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These conversions could potentially remain infallible if we had PublicKey enforce the invariant that the inner point cannot be the additive identity.

That would require making PublicKey::from_affine fallible, which might make sense, and would nicely match the similar invariants of SecretKey, which wraps a NonZeroScalar.

All that said, I'd like to follow up on that in a separate PR.

}

Expand Down Expand Up @@ -210,7 +214,7 @@ where
{
/// Serialize this [`PublicKey`] as a SEC1 [`EncodedPoint`], optionally applying
/// point compression
fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C> {
fn to_encoded_point(&self, compress: bool) -> Option<EncodedPoint<C>> {
self.point.to_encoded_point(compress)
}
}
Expand Down
18 changes: 14 additions & 4 deletions elliptic-curve/src/sec1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ where
(C::ProjectivePoint::generator() * secret_key.secret_scalar())
.to_affine()
.to_encoded_point(compress)
.expect("secret is identity")
}

/// Get the length of the encoded point in bytes
Expand Down Expand Up @@ -204,19 +205,19 @@ where
match self.coordinates() {
Coordinates::Compressed { x, y_is_odd } => {
AffinePoint::<C>::decompress(x, Choice::from(y_is_odd as u8))
.map(|s| s.to_encoded_point(false))
.map(|s| s.to_encoded_point(false).expect("point is identity"))
.into()
}
Coordinates::Uncompressed { .. } => Some(self.clone()),
}
}

/// Encode an [`EncodedPoint`] from the desired type
pub fn encode<T>(encodable: T, compress: bool) -> Self
pub fn encode<T>(encodable: T, compress: bool) -> Result<Self, Error>
where
T: ToEncodedPoint<C>,
{
encodable.to_encoded_point(compress)
encodable.to_encoded_point(compress).ok_or(Error)
}

/// Decode this [`EncodedPoint`] into the desired type
Expand Down Expand Up @@ -366,7 +367,16 @@ where
{
/// Serialize this value as a SEC1 [`EncodedPoint`], optionally applying
/// point compression.
fn to_encoded_point(&self, compress: bool) -> EncodedPoint<C>;
///
/// # Returns
///
/// `None` if this point is the additive identity (a.k.a. point-at-infinity).
///
/// Though the additive identity can technically be encoded using the
/// `Elliptic-Curve-Point-to-Octet-String` encoding specified in SEC1
/// Section 2.3.3, this encoding is not supported by [`EncodedPoint`] and
/// implementers of this trait should return `None` for this case instead.
fn to_encoded_point(&self, compress: bool) -> Option<EncodedPoint<C>>;
}

/// Tag byte used by the `Elliptic-Curve-Point-to-Octet-String` encoding.
Expand Down