Use SEC1 for the encoding of secq256k1 points, like secp256k1 does

This commit is contained in:
Luke Parker
2025-08-28 23:51:27 -04:00
parent beac35c119
commit 5526b8d439
6 changed files with 33 additions and 28 deletions

View File

@@ -89,8 +89,9 @@ impl<C: ShortWeierstrass> Affine<C> {
pub fn decompress(x: C::FieldElement, odd_y: Choice) -> CtOption<Self> {
let y_square = ((x.square() + C::A) * x) + C::B;
y_square.sqrt().and_then(|mut y| {
y = <_>::conditional_select(&y, &-y, odd_y.ct_ne(&y.is_odd()));
CtOption::new(Self { x, y }, 1.into())
y = <_>::conditional_select(&y, &-y, y.is_odd().ct_ne(&odd_y));
// Handles the exceptional case of `y = 0, odd_y = 1`
CtOption::new(Self { x, y }, y.is_odd().ct_eq(&odd_y))
})
}

View File

@@ -35,13 +35,13 @@ pub trait ShortWeierstrass: 'static + Sized + Debug {
type Repr: 'static + Send + Sync + Copy + Default + AsRef<[u8]> + AsMut<[u8]>;
/// The representation of the identity point.
const IDENTITY: Self::Repr;
/// Compress an affine point its byte encoding.
/// Encode a compresed, on-curve point to its byte encoding.
///
/// The space of potential outputs MUST exclude `Self::IDENTITY`.
fn compress(x: Self::FieldElement, odd_y: Choice) -> Self::Repr;
/// Decode a compressed point.
fn encode_compressed(x: Self::FieldElement, odd_y: Choice) -> Self::Repr;
/// Decode the `x` coordinate and if the `y` coordinate is odd from a compressed representation.
///
/// This is expected to return the `x` coordinate and if the `y` coordinate is odd.
/// This MAY return any value if the bytes represent the identity.
fn decode_compressed(bytes: &Self::Repr) -> (<Self::FieldElement as PrimeField>::Repr, Choice);
/// If the point is outside the largest prime-order subgroup and isn't the identity point.

View File

@@ -369,13 +369,11 @@ impl<C: ShortWeierstrass> GroupEncoding for Projective<C> {
let (x, odd_y) = C::decode_compressed(bytes);
let result = C::FieldElement::from_repr(x).and_then(|x| {
// Parse x and recover y
let non_identity_on_curve_point = Affine::decompress(x, odd_y).map(Projective::from);
// Set the identity, if the identity
let identity = CtOption::new(Projective::IDENTITY, identity);
non_identity_on_curve_point.or_else(|| identity)
});
let result = C::FieldElement::from_repr(x)
.and_then(|x| Affine::decompress(x, odd_y).map(Projective::from));
// Set the identity, if the identity
let identity = CtOption::new(Projective::IDENTITY, identity);
let result = result.or_else(|| identity);
let mut result_is_valid = result.is_some();
let result = result.unwrap_or(Projective::IDENTITY);
@@ -394,7 +392,7 @@ impl<C: ShortWeierstrass> GroupEncoding for Projective<C> {
let compressed_if_not_identity = {
let affine_on_curve = affine_on_curve.unwrap_or(C::GENERATOR);
let (x, y) = affine_on_curve.coordinates();
C::compress(x, y.is_odd())
C::encode_compressed(x, y.is_odd())
};
let mut res = C::Repr::default();