Unverified Commit 99bce5b3 authored by Steven Fackler's avatar Steven Fackler Committed by GitHub
Browse files

Merge pull request #2000 from zh-jq/ec_point_to_hex_str

add EcPointRef::to_hex_str and EcPoint::from_hex_str
parents 82f049d6 ebf8027a
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -152,6 +152,20 @@ extern "C" {
        ctx: *mut BN_CTX,
    ) -> c_int;

    pub fn EC_POINT_point2hex(
        group: *const EC_GROUP,
        p: *const EC_POINT,
        form: point_conversion_form_t,
        ctx: *mut BN_CTX,
    ) -> *mut c_char;

    pub fn EC_POINT_hex2point(
        group: *const EC_GROUP,
        s: *const c_char,
        p: *mut EC_POINT,
        ctx: *mut BN_CTX,
    ) -> *mut EC_POINT;

    pub fn EC_POINT_add(
        group: *const EC_GROUP,
        r: *mut EC_POINT,
+63 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
//! [`EcGroup`]: struct.EcGroup.html
//! [`Nid`]: ../nid/struct.Nid.html
//! [Elliptic Curve Cryptography]: https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
use cfg_if::cfg_if;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
use std::fmt;
@@ -28,6 +29,13 @@ use crate::util::ForeignTypeRefExt;
use crate::{cvt, cvt_n, cvt_p, init};
use openssl_macros::corresponds;

cfg_if! {
    if #[cfg(not(boringssl))] {
        use std::ffi::CString;
        use crate::string::OpensslString;
    }
}

/// Compressed or Uncompressed conversion
///
/// Conversion from the binary value of the point on the curve is performed in one of
@@ -463,6 +471,26 @@ impl EcPointRef {
        }
    }

    /// Serializes the point to a hexadecimal string representation.
    #[corresponds(EC_POINT_point2hex)]
    #[cfg(not(boringssl))]
    pub fn to_hex_str(
        &self,
        group: &EcGroupRef,
        form: PointConversionForm,
        ctx: &mut BigNumContextRef,
    ) -> Result<OpensslString, ErrorStack> {
        unsafe {
            let buf = cvt_p(ffi::EC_POINT_point2hex(
                group.as_ptr(),
                self.as_ptr(),
                form.0,
                ctx.as_ptr(),
            ))?;
            Ok(OpensslString::from_ptr(buf))
        }
    }

    /// Creates a new point on the specified curve with the same value.
    #[corresponds(EC_POINT_dup)]
    pub fn to_owned(&self, group: &EcGroupRef) -> Result<EcPoint, ErrorStack> {
@@ -631,6 +659,27 @@ impl EcPoint {
        }
        Ok(point)
    }

    /// Creates point from a hexadecimal string representation
    #[corresponds(EC_POINT_hex2point)]
    #[cfg(not(boringssl))]
    pub fn from_hex_str(
        group: &EcGroupRef,
        s: &str,
        ctx: &mut BigNumContextRef,
    ) -> Result<EcPoint, ErrorStack> {
        let point = EcPoint::new(group)?;
        unsafe {
            let c_str = CString::new(s.as_bytes()).unwrap();
            cvt_p(ffi::EC_POINT_hex2point(
                group.as_ptr(),
                c_str.as_ptr() as *const _,
                point.as_ptr(),
                ctx.as_ptr(),
            ))?;
        }
        Ok(point)
    }
}

generic_foreign_type_and_impl_send_sync! {
@@ -1121,6 +1170,20 @@ mod test {
        assert!(point.eq(&group, &point2, &mut ctx).unwrap());
    }

    #[test]
    #[cfg(not(boringssl))]
    fn point_hex_str() {
        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let key = EcKey::generate(&group).unwrap();
        let point = key.public_key();
        let mut ctx = BigNumContext::new().unwrap();
        let hex = point
            .to_hex_str(&group, PointConversionForm::COMPRESSED, &mut ctx)
            .unwrap();
        let point2 = EcPoint::from_hex_str(&group, &hex, &mut ctx).unwrap();
        assert!(point.eq(&group, &point2, &mut ctx).unwrap());
    }

    #[test]
    fn point_owned() {
        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();