sfackler / rust-openssl

OpenSSL bindings for Rust
1.4k stars 748 forks source link

Fix `from_private_components`: support creation of an EC private key from Curve NID and BIGNUM scalar only #2075

Open bgrieder opened 12 months ago

bgrieder commented 12 months ago

The function int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); is available in the openssl API but is not correctly exposed in rust-openssl.

The available function is

/// Constructs an public/private key pair given a curve, a private key and a public key point.
    #[corresponds(EC_KEY_set_private_key)]
    pub fn from_private_components(
        group: &EcGroupRef,
        private_number: &BigNumRef,
        public_key: &EcPointRef,
    ) -> Result<EcKey<Private>, ErrorStack>;

But this one requires a public key, which is not always available and does not match the EC_KEY_set_private_key parameters.

bgrieder commented 12 months ago

In the meantime, a possible workaround is (to re-calculate the public key from the scalar d and the generator)

let big_num_context = BigNumContext::new()?;
let scalar =  BigNum::from_slice(d.to_bytes_be().as_slice())?;
let ec_group = EcGroup::from_curve_name(openssl::nid::Nid::X9_62_PRIME256V1)?;
let mut ec_public_key = EcPoint::new(&ec_group)?;

ec_public_key.mul_generator(
    &ec_group,
    &scalar,
    &big_num_context,
)?;
EcKey::from_private_components(
    &ec_group,
    &scalar,
    &ec_public_key,
)?
Skepfyr commented 8 months ago

Yeah this method somewhat weirdly corresponds to EC_KEY_set_group, EC_KEY_set_private_key, and EC_KEY_set_public_key. If you need them we'd happily accept a PR to add a method that invokes just one of those OpenSSL functions.