diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 353f619f..69c95395 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1674,6 +1674,7 @@ extern "C" { pub fn EC_KEY_generate_key(key: *mut EC_KEY) -> c_int; pub fn EC_KEY_check_key(key: *const EC_KEY) -> c_int; pub fn EC_KEY_free(key: *mut EC_KEY); + pub fn EC_KEY_set_public_key_affine_coordinates(key: *mut EC_KEY, x: *const BIGNUM, y: *const BIGNUM) -> c_int; #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] pub fn EC_GF2m_simple_method() -> *const EC_METHOD; diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index baa903a3..e6c89289 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -31,3 +31,4 @@ tempdir = "0.3" winapi = "0.2" ws2_32-sys = "0.2" hex = "0.2" +data-encoding = "1.2" diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs index 95baa833..5ff9fd5b 100644 --- a/openssl/src/ec.rs +++ b/openssl/src/ec.rs @@ -459,12 +459,26 @@ impl EcKeyBuilderRef { pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> { unsafe { cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self) } } + + /// Sets the public key based on affine coordinates. + pub fn set_public_key_affine_coordinates(&mut self, + x: &BigNumRef, + y: &BigNumRef) + -> Result<&mut EcKeyBuilderRef, ErrorStack> { + unsafe { + cvt(ffi::EC_KEY_set_public_key_affine_coordinates(self.as_ptr(), + x.as_ptr(), + y.as_ptr()) + ).map(|_| self) + } + } } #[cfg(test)] mod test { - use bn::BigNumContext; + use bn::{BigNum, BigNumContext}; use nid; + use data_encoding; use super::*; #[test] @@ -539,4 +553,24 @@ mod test { assert!(ec_key.public_key().is_some()); assert!(ec_key.private_key().is_none()); } + + #[test] + fn key_from_affine_coordinates() { + let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap(); + let x = data_encoding::base64url::decode_nopad("MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4".as_bytes()) + .unwrap(); + let y = data_encoding::base64url::decode_nopad("4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM".as_bytes()) + .unwrap(); + + let xbn = BigNum::from_slice(&x).unwrap(); + let ybn = BigNum::from_slice(&y).unwrap(); + + let mut builder = EcKeyBuilder::new().unwrap(); + builder.set_group(&group).unwrap(); + builder.set_public_key_affine_coordinates(&xbn, &ybn).unwrap(); + + let ec_key = builder.build(); + assert!(ec_key.check_key().is_ok()); + assert!(ec_key.public_key().is_some()); + } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 44752dcc..a6d5e6a0 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -13,6 +13,8 @@ extern crate openssl_sys as ffi; extern crate hex; #[cfg(test)] extern crate tempdir; +#[cfg(test)] +extern crate data_encoding; #[doc(inline)] pub use ffi::init;