1 //! Public/private key processing. 2 //! 3 //! Asymmetric public key algorithms solve the problem of establishing and sharing 4 //! secret keys to securely send and receive messages. 5 //! This system uses a pair of keys: a public key, which can be freely 6 //! distributed, and a private key, which is kept to oneself. An entity may 7 //! encrypt information using a user's public key. The encrypted information can 8 //! only be deciphered using that user's private key. 9 //! 10 //! This module offers support for five popular algorithms: 11 //! 12 //! * RSA 13 //! 14 //! * DSA 15 //! 16 //! * Diffie-Hellman 17 //! 18 //! * Elliptic Curves 19 //! 20 //! * HMAC 21 //! 22 //! These algorithms rely on hard mathematical problems - namely integer factorization, 23 //! discrete logarithms, and elliptic curve relationships - that currently do not 24 //! yield efficient solutions. This property ensures the security of these 25 //! cryptographic algorithms. 26 //! 27 //! # Example 28 //! 29 //! Generate a 2048-bit RSA public/private key pair and print the public key. 30 //! 31 //! ```rust 32 //! use openssl::rsa::Rsa; 33 //! use openssl::pkey::PKey; 34 //! use std::str; 35 //! 36 //! let rsa = Rsa::generate(2048).unwrap(); 37 //! let pkey = PKey::from_rsa(rsa).unwrap(); 38 //! 39 //! let pub_key: Vec<u8> = pkey.public_key_to_pem().unwrap(); 40 //! println!("{:?}", str::from_utf8(pub_key.as_slice()).unwrap()); 41 //! ``` 42 #![allow(clippy::missing_safety_doc)] 43 use crate::bio::{MemBio, MemBioSlice}; 44 #[cfg(ossl110)] 45 use crate::cipher::CipherRef; 46 use crate::dh::Dh; 47 use crate::dsa::Dsa; 48 use crate::ec::EcKey; 49 use crate::error::ErrorStack; 50 #[cfg(any(ossl110, boringssl, libressl370))] 51 use crate::pkey_ctx::PkeyCtx; 52 use crate::rsa::Rsa; 53 use crate::symm::Cipher; 54 use crate::util::{invoke_passwd_cb, CallbackState}; 55 use crate::{cvt, cvt_p}; 56 use cfg_if::cfg_if; 57 use foreign_types::{ForeignType, ForeignTypeRef}; 58 use libc::{c_int, c_long}; 59 use openssl_macros::corresponds; 60 use std::convert::{TryFrom, TryInto}; 61 use std::ffi::CString; 62 use std::fmt; 63 use std::mem; 64 use std::ptr; 65 66 /// A tag type indicating that a key only has parameters. 67 pub enum Params {} 68 69 /// A tag type indicating that a key only has public components. 70 pub enum Public {} 71 72 /// A tag type indicating that a key has private components. 73 pub enum Private {} 74 75 /// An identifier of a kind of key. 76 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 77 pub struct Id(c_int); 78 79 impl Id { 80 pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); 81 #[cfg(not(boringssl))] 82 pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC); 83 #[cfg(not(boringssl))] 84 pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC); 85 pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); 86 pub const DH: Id = Id(ffi::EVP_PKEY_DH); 87 pub const EC: Id = Id(ffi::EVP_PKEY_EC); 88 #[cfg(ossl111)] 89 pub const SM2: Id = Id(ffi::EVP_PKEY_SM2); 90 91 #[cfg(any(ossl110, boringssl))] 92 pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); 93 94 #[cfg(any(ossl111, boringssl, libressl370))] 95 pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); 96 #[cfg(ossl111)] 97 pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); 98 #[cfg(any(ossl111, boringssl, libressl370))] 99 pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); 100 #[cfg(ossl111)] 101 pub const X448: Id = Id(ffi::EVP_PKEY_X448); 102 #[cfg(ossl111)] 103 pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305); 104 105 /// Creates a `Id` from an integer representation. from_raw(value: c_int) -> Id106 pub fn from_raw(value: c_int) -> Id { 107 Id(value) 108 } 109 110 /// Returns the integer representation of the `Id`. 111 #[allow(clippy::trivially_copy_pass_by_ref)] as_raw(&self) -> c_int112 pub fn as_raw(&self) -> c_int { 113 self.0 114 } 115 } 116 117 /// A trait indicating that a key has parameters. 118 pub unsafe trait HasParams {} 119 120 unsafe impl HasParams for Params {} 121 122 unsafe impl<T> HasParams for T where T: HasPublic {} 123 124 /// A trait indicating that a key has public components. 125 pub unsafe trait HasPublic {} 126 127 unsafe impl HasPublic for Public {} 128 129 unsafe impl<T> HasPublic for T where T: HasPrivate {} 130 131 /// A trait indicating that a key has private components. 132 pub unsafe trait HasPrivate {} 133 134 unsafe impl HasPrivate for Private {} 135 136 generic_foreign_type_and_impl_send_sync! { 137 type CType = ffi::EVP_PKEY; 138 fn drop = ffi::EVP_PKEY_free; 139 140 /// A public or private key. 141 pub struct PKey<T>; 142 /// Reference to `PKey`. 143 pub struct PKeyRef<T>; 144 } 145 146 impl<T> ToOwned for PKeyRef<T> { 147 type Owned = PKey<T>; 148 to_owned(&self) -> PKey<T>149 fn to_owned(&self) -> PKey<T> { 150 unsafe { 151 EVP_PKEY_up_ref(self.as_ptr()); 152 PKey::from_ptr(self.as_ptr()) 153 } 154 } 155 } 156 157 impl<T> PKeyRef<T> { 158 /// Returns a copy of the internal RSA key. 159 #[corresponds(EVP_PKEY_get1_RSA)] rsa(&self) -> Result<Rsa<T>, ErrorStack>160 pub fn rsa(&self) -> Result<Rsa<T>, ErrorStack> { 161 unsafe { 162 let rsa = cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))?; 163 Ok(Rsa::from_ptr(rsa)) 164 } 165 } 166 167 /// Returns a copy of the internal DSA key. 168 #[corresponds(EVP_PKEY_get1_DSA)] dsa(&self) -> Result<Dsa<T>, ErrorStack>169 pub fn dsa(&self) -> Result<Dsa<T>, ErrorStack> { 170 unsafe { 171 let dsa = cvt_p(ffi::EVP_PKEY_get1_DSA(self.as_ptr()))?; 172 Ok(Dsa::from_ptr(dsa)) 173 } 174 } 175 176 /// Returns a copy of the internal DH key. 177 #[corresponds(EVP_PKEY_get1_DH)] dh(&self) -> Result<Dh<T>, ErrorStack>178 pub fn dh(&self) -> Result<Dh<T>, ErrorStack> { 179 unsafe { 180 let dh = cvt_p(ffi::EVP_PKEY_get1_DH(self.as_ptr()))?; 181 Ok(Dh::from_ptr(dh)) 182 } 183 } 184 185 /// Returns a copy of the internal elliptic curve key. 186 #[corresponds(EVP_PKEY_get1_EC_KEY)] ec_key(&self) -> Result<EcKey<T>, ErrorStack>187 pub fn ec_key(&self) -> Result<EcKey<T>, ErrorStack> { 188 unsafe { 189 let ec_key = cvt_p(ffi::EVP_PKEY_get1_EC_KEY(self.as_ptr()))?; 190 Ok(EcKey::from_ptr(ec_key)) 191 } 192 } 193 194 /// Returns the `Id` that represents the type of this key. 195 #[corresponds(EVP_PKEY_id)] id(&self) -> Id196 pub fn id(&self) -> Id { 197 unsafe { Id::from_raw(ffi::EVP_PKEY_id(self.as_ptr())) } 198 } 199 200 /// Returns the maximum size of a signature in bytes. 201 #[corresponds(EVP_PKEY_size)] size(&self) -> usize202 pub fn size(&self) -> usize { 203 unsafe { ffi::EVP_PKEY_size(self.as_ptr()) as usize } 204 } 205 } 206 207 impl<T> PKeyRef<T> 208 where 209 T: HasPublic, 210 { 211 to_pem! { 212 /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure. 213 /// 214 /// The output will have a header of `-----BEGIN PUBLIC KEY-----`. 215 #[corresponds(PEM_write_bio_PUBKEY)] 216 public_key_to_pem, 217 ffi::PEM_write_bio_PUBKEY 218 } 219 220 to_der! { 221 /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure. 222 #[corresponds(i2d_PUBKEY)] 223 public_key_to_der, 224 ffi::i2d_PUBKEY 225 } 226 227 /// Returns the size of the key. 228 /// 229 /// This corresponds to the bit length of the modulus of an RSA key, and the bit length of the 230 /// group order for an elliptic curve key, for example. 231 #[corresponds(EVP_PKEY_bits)] bits(&self) -> u32232 pub fn bits(&self) -> u32 { 233 unsafe { ffi::EVP_PKEY_bits(self.as_ptr()) as u32 } 234 } 235 236 ///Returns the number of security bits. 237 /// 238 ///Bits of security is defined in NIST SP800-57. 239 #[corresponds(EVP_PKEY_security_bits)] 240 #[cfg(any(ossl110, libressl360))] security_bits(&self) -> u32241 pub fn security_bits(&self) -> u32 { 242 unsafe { ffi::EVP_PKEY_security_bits(self.as_ptr()) as u32 } 243 } 244 245 /// Compares the public component of this key with another. 246 #[corresponds(EVP_PKEY_cmp)] public_eq<U>(&self, other: &PKeyRef<U>) -> bool where U: HasPublic,247 pub fn public_eq<U>(&self, other: &PKeyRef<U>) -> bool 248 where 249 U: HasPublic, 250 { 251 let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }; 252 // Clear the stack. OpenSSL will put an error on the stack when the 253 // keys are different types in some situations. 254 let _ = ErrorStack::get(); 255 res 256 } 257 258 /// Raw byte representation of a public key. 259 /// 260 /// This function only works for algorithms that support raw public keys. 261 /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. 262 #[corresponds(EVP_PKEY_get_raw_public_key)] 263 #[cfg(any(ossl111, boringssl, libressl370))] raw_public_key(&self) -> Result<Vec<u8>, ErrorStack>264 pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> { 265 unsafe { 266 let mut len = 0; 267 cvt(ffi::EVP_PKEY_get_raw_public_key( 268 self.as_ptr(), 269 ptr::null_mut(), 270 &mut len, 271 ))?; 272 let mut buf = vec![0u8; len]; 273 cvt(ffi::EVP_PKEY_get_raw_public_key( 274 self.as_ptr(), 275 buf.as_mut_ptr(), 276 &mut len, 277 ))?; 278 buf.truncate(len); 279 Ok(buf) 280 } 281 } 282 } 283 284 impl<T> PKeyRef<T> 285 where 286 T: HasPrivate, 287 { 288 private_key_to_pem! { 289 /// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure. 290 /// 291 /// The output will have a header of `-----BEGIN PRIVATE KEY-----`. 292 #[corresponds(PEM_write_bio_PKCS8PrivateKey)] 293 private_key_to_pem_pkcs8, 294 /// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure. 295 /// 296 /// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`. 297 #[corresponds(PEM_write_bio_PKCS8PrivateKey)] 298 private_key_to_pem_pkcs8_passphrase, 299 ffi::PEM_write_bio_PKCS8PrivateKey 300 } 301 302 to_der! { 303 /// Serializes the private key to a DER-encoded key type specific format. 304 #[corresponds(i2d_PrivateKey)] 305 private_key_to_der, 306 ffi::i2d_PrivateKey 307 } 308 309 /// Raw byte representation of a private key. 310 /// 311 /// This function only works for algorithms that support raw private keys. 312 /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. 313 #[corresponds(EVP_PKEY_get_raw_private_key)] 314 #[cfg(any(ossl111, boringssl, libressl370))] raw_private_key(&self) -> Result<Vec<u8>, ErrorStack>315 pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> { 316 unsafe { 317 let mut len = 0; 318 cvt(ffi::EVP_PKEY_get_raw_private_key( 319 self.as_ptr(), 320 ptr::null_mut(), 321 &mut len, 322 ))?; 323 let mut buf = vec![0u8; len]; 324 cvt(ffi::EVP_PKEY_get_raw_private_key( 325 self.as_ptr(), 326 buf.as_mut_ptr(), 327 &mut len, 328 ))?; 329 buf.truncate(len); 330 Ok(buf) 331 } 332 } 333 334 /// Serializes a private key into an unencrypted DER-formatted PKCS#8 335 #[corresponds(i2d_PKCS8PrivateKey_bio)] private_key_to_pkcs8(&self) -> Result<Vec<u8>, ErrorStack>336 pub fn private_key_to_pkcs8(&self) -> Result<Vec<u8>, ErrorStack> { 337 unsafe { 338 let bio = MemBio::new()?; 339 cvt(ffi::i2d_PKCS8PrivateKey_bio( 340 bio.as_ptr(), 341 self.as_ptr(), 342 ptr::null(), 343 ptr::null_mut(), 344 0, 345 None, 346 ptr::null_mut(), 347 ))?; 348 349 Ok(bio.get_buf().to_owned()) 350 } 351 } 352 353 /// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to 354 /// encrypt the key. 355 #[corresponds(i2d_PKCS8PrivateKey_bio)] private_key_to_pkcs8_passphrase( &self, cipher: Cipher, passphrase: &[u8], ) -> Result<Vec<u8>, ErrorStack>356 pub fn private_key_to_pkcs8_passphrase( 357 &self, 358 cipher: Cipher, 359 passphrase: &[u8], 360 ) -> Result<Vec<u8>, ErrorStack> { 361 unsafe { 362 let bio = MemBio::new()?; 363 cvt(ffi::i2d_PKCS8PrivateKey_bio( 364 bio.as_ptr(), 365 self.as_ptr(), 366 cipher.as_ptr(), 367 passphrase.as_ptr() as *const _ as *mut _, 368 passphrase.len().try_into().unwrap(), 369 None, 370 ptr::null_mut(), 371 ))?; 372 373 Ok(bio.get_buf().to_owned()) 374 } 375 } 376 } 377 378 impl<T> fmt::Debug for PKey<T> { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result379 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 380 let alg = match self.id() { 381 Id::RSA => "RSA", 382 #[cfg(not(boringssl))] 383 Id::HMAC => "HMAC", 384 Id::DSA => "DSA", 385 Id::DH => "DH", 386 Id::EC => "EC", 387 #[cfg(ossl111)] 388 Id::ED25519 => "Ed25519", 389 #[cfg(ossl111)] 390 Id::ED448 => "Ed448", 391 _ => "unknown", 392 }; 393 fmt.debug_struct("PKey").field("algorithm", &alg).finish() 394 // TODO: Print details for each specific type of key 395 } 396 } 397 398 impl<T> Clone for PKey<T> { clone(&self) -> PKey<T>399 fn clone(&self) -> PKey<T> { 400 PKeyRef::to_owned(self) 401 } 402 } 403 404 impl<T> PKey<T> { 405 /// Creates a new `PKey` containing an RSA key. 406 #[corresponds(EVP_PKEY_assign_RSA)] from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>407 pub fn from_rsa(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 408 unsafe { 409 let evp = cvt_p(ffi::EVP_PKEY_new())?; 410 let pkey = PKey::from_ptr(evp); 411 cvt(ffi::EVP_PKEY_assign_RSA(pkey.0, rsa.as_ptr()))?; 412 mem::forget(rsa); 413 Ok(pkey) 414 } 415 } 416 417 /// Creates a new `PKey` containing a DSA key. 418 #[corresponds(EVP_PKEY_assign_DSA)] from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>419 pub fn from_dsa(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 420 unsafe { 421 let evp = cvt_p(ffi::EVP_PKEY_new())?; 422 let pkey = PKey::from_ptr(evp); 423 cvt(ffi::EVP_PKEY_assign_DSA(pkey.0, dsa.as_ptr()))?; 424 mem::forget(dsa); 425 Ok(pkey) 426 } 427 } 428 429 /// Creates a new `PKey` containing a Diffie-Hellman key. 430 #[corresponds(EVP_PKEY_assign_DH)] 431 #[cfg(not(boringssl))] from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>432 pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 433 unsafe { 434 let evp = cvt_p(ffi::EVP_PKEY_new())?; 435 let pkey = PKey::from_ptr(evp); 436 cvt(ffi::EVP_PKEY_assign_DH(pkey.0, dh.as_ptr()))?; 437 mem::forget(dh); 438 Ok(pkey) 439 } 440 } 441 442 /// Creates a new `PKey` containing an elliptic curve key. 443 #[corresponds(EVP_PKEY_assign_EC_KEY)] from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>444 pub fn from_ec_key(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 445 unsafe { 446 let evp = cvt_p(ffi::EVP_PKEY_new())?; 447 let pkey = PKey::from_ptr(evp); 448 cvt(ffi::EVP_PKEY_assign_EC_KEY(pkey.0, ec_key.as_ptr()))?; 449 mem::forget(ec_key); 450 Ok(pkey) 451 } 452 } 453 } 454 455 impl PKey<Private> { 456 /// Creates a new `PKey` containing an HMAC key. 457 /// 458 /// # Note 459 /// 460 /// To compute HMAC values, use the `sign` module. 461 #[corresponds(EVP_PKEY_new_mac_key)] 462 #[cfg(not(boringssl))] hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack>463 pub fn hmac(key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 464 unsafe { 465 assert!(key.len() <= c_int::max_value() as usize); 466 let key = cvt_p(ffi::EVP_PKEY_new_mac_key( 467 ffi::EVP_PKEY_HMAC, 468 ptr::null_mut(), 469 key.as_ptr() as *const _, 470 key.len() as c_int, 471 ))?; 472 Ok(PKey::from_ptr(key)) 473 } 474 } 475 476 /// Creates a new `PKey` containing a CMAC key. 477 /// 478 /// Requires OpenSSL 1.1.0 or newer. 479 /// 480 /// # Note 481 /// 482 /// To compute CMAC values, use the `sign` module. 483 #[cfg(all(not(boringssl), ossl110))] 484 #[allow(clippy::trivially_copy_pass_by_ref)] cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack>485 pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result<PKey<Private>, ErrorStack> { 486 let mut ctx = PkeyCtx::new_id(Id::CMAC)?; 487 ctx.keygen_init()?; 488 ctx.set_keygen_cipher(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) })?; 489 ctx.set_keygen_mac_key(key)?; 490 ctx.keygen() 491 } 492 493 #[cfg(any(ossl111, boringssl, libressl370))] generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack>494 fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> { 495 let mut ctx = PkeyCtx::new_id(id)?; 496 ctx.keygen_init()?; 497 ctx.keygen() 498 } 499 500 /// Generates a new private X25519 key. 501 /// 502 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 503 /// 504 /// # Examples 505 /// 506 /// ``` 507 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 508 /// use openssl::pkey::{PKey, Id}; 509 /// use openssl::derive::Deriver; 510 /// 511 /// let public = // ... 512 /// # &PKey::generate_x25519()?.raw_public_key()?; 513 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X25519)?; 514 /// 515 /// let key = PKey::generate_x25519()?; 516 /// let mut deriver = Deriver::new(&key)?; 517 /// deriver.set_peer(&public_key)?; 518 /// 519 /// let secret = deriver.derive_to_vec()?; 520 /// assert_eq!(secret.len(), 32); 521 /// # Ok(()) } 522 /// ``` 523 #[cfg(any(ossl111, boringssl, libressl370))] generate_x25519() -> Result<PKey<Private>, ErrorStack>524 pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> { 525 PKey::generate_eddsa(Id::X25519) 526 } 527 528 /// Generates a new private X448 key. 529 /// 530 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 531 /// 532 /// # Examples 533 /// 534 /// ``` 535 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 536 /// use openssl::pkey::{PKey, Id}; 537 /// use openssl::derive::Deriver; 538 /// 539 /// let public = // ... 540 /// # &PKey::generate_x448()?.raw_public_key()?; 541 /// let public_key = PKey::public_key_from_raw_bytes(public, Id::X448)?; 542 /// 543 /// let key = PKey::generate_x448()?; 544 /// let mut deriver = Deriver::new(&key)?; 545 /// deriver.set_peer(&public_key)?; 546 /// 547 /// let secret = deriver.derive_to_vec()?; 548 /// assert_eq!(secret.len(), 56); 549 /// # Ok(()) } 550 /// ``` 551 #[cfg(ossl111)] generate_x448() -> Result<PKey<Private>, ErrorStack>552 pub fn generate_x448() -> Result<PKey<Private>, ErrorStack> { 553 PKey::generate_eddsa(Id::X448) 554 } 555 556 /// Generates a new private Ed25519 key. 557 /// 558 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 559 /// 560 /// # Examples 561 /// 562 /// ``` 563 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 564 /// use openssl::pkey::{PKey, Id}; 565 /// use openssl::sign::Signer; 566 /// 567 /// let key = PKey::generate_ed25519()?; 568 /// let public_key = key.raw_public_key()?; 569 /// 570 /// let mut signer = Signer::new_without_digest(&key)?; 571 /// let digest = // ... 572 /// # &vec![0; 32]; 573 /// let signature = signer.sign_oneshot_to_vec(digest)?; 574 /// assert_eq!(signature.len(), 64); 575 /// # Ok(()) } 576 /// ``` 577 #[cfg(any(ossl111, boringssl, libressl370))] generate_ed25519() -> Result<PKey<Private>, ErrorStack>578 pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> { 579 PKey::generate_eddsa(Id::ED25519) 580 } 581 582 /// Generates a new private Ed448 key. 583 /// 584 /// To import a private key from raw bytes see [`PKey::private_key_from_raw_bytes`]. 585 /// 586 /// # Examples 587 /// 588 /// ``` 589 /// # fn main() -> Result<(), Box<dyn std::error::Error>> { 590 /// use openssl::pkey::{PKey, Id}; 591 /// use openssl::sign::Signer; 592 /// 593 /// let key = PKey::generate_ed448()?; 594 /// let public_key = key.raw_public_key()?; 595 /// 596 /// let mut signer = Signer::new_without_digest(&key)?; 597 /// let digest = // ... 598 /// # &vec![0; 32]; 599 /// let signature = signer.sign_oneshot_to_vec(digest)?; 600 /// assert_eq!(signature.len(), 114); 601 /// # Ok(()) } 602 /// ``` 603 #[cfg(ossl111)] generate_ed448() -> Result<PKey<Private>, ErrorStack>604 pub fn generate_ed448() -> Result<PKey<Private>, ErrorStack> { 605 PKey::generate_eddsa(Id::ED448) 606 } 607 608 /// Generates a new EC key using the provided curve. 609 /// 610 /// Requires OpenSSL 3.0.0 or newer. 611 #[corresponds(EVP_EC_gen)] 612 #[cfg(ossl300)] ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack>613 pub fn ec_gen(curve: &str) -> Result<PKey<Private>, ErrorStack> { 614 ffi::init(); 615 616 let curve = CString::new(curve).unwrap(); 617 unsafe { 618 let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?; 619 Ok(PKey::from_ptr(ptr)) 620 } 621 } 622 623 private_key_from_pem! { 624 /// Deserializes a private key from a PEM-encoded key type specific format. 625 #[corresponds(PEM_read_bio_PrivateKey)] 626 private_key_from_pem, 627 628 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 629 #[corresponds(PEM_read_bio_PrivateKey)] 630 private_key_from_pem_passphrase, 631 632 /// Deserializes a private key from a PEM-encoded encrypted key type specific format. 633 /// 634 /// The callback should fill the password into the provided buffer and return its length. 635 #[corresponds(PEM_read_bio_PrivateKey)] 636 private_key_from_pem_callback, 637 PKey<Private>, 638 ffi::PEM_read_bio_PrivateKey 639 } 640 641 from_der! { 642 /// Decodes a DER-encoded private key. 643 /// 644 /// This function will attempt to automatically detect the underlying key format, and 645 /// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific 646 /// formats. 647 #[corresponds(d2i_AutoPrivateKey)] 648 private_key_from_der, 649 PKey<Private>, 650 ffi::d2i_AutoPrivateKey 651 } 652 653 /// Deserializes a DER-formatted PKCS#8 unencrypted private key. 654 /// 655 /// This method is mainly for interoperability reasons. Encrypted keyfiles should be preferred. private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack>656 pub fn private_key_from_pkcs8(der: &[u8]) -> Result<PKey<Private>, ErrorStack> { 657 unsafe { 658 ffi::init(); 659 let len = der.len().min(c_long::max_value() as usize) as c_long; 660 let p8inf = cvt_p(ffi::d2i_PKCS8_PRIV_KEY_INFO( 661 ptr::null_mut(), 662 &mut der.as_ptr(), 663 len, 664 ))?; 665 let res = cvt_p(ffi::EVP_PKCS82PKEY(p8inf)).map(|p| PKey::from_ptr(p)); 666 ffi::PKCS8_PRIV_KEY_INFO_free(p8inf); 667 res 668 } 669 } 670 671 /// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password 672 /// if the key is encrypted. 673 /// 674 /// The callback should copy the password into the provided buffer and return the number of 675 /// bytes written. 676 #[corresponds(d2i_PKCS8PrivateKey_bio)] private_key_from_pkcs8_callback<F>( der: &[u8], callback: F, ) -> Result<PKey<Private>, ErrorStack> where F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,677 pub fn private_key_from_pkcs8_callback<F>( 678 der: &[u8], 679 callback: F, 680 ) -> Result<PKey<Private>, ErrorStack> 681 where 682 F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>, 683 { 684 unsafe { 685 ffi::init(); 686 let mut cb = CallbackState::new(callback); 687 let bio = MemBioSlice::new(der)?; 688 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 689 bio.as_ptr(), 690 ptr::null_mut(), 691 Some(invoke_passwd_cb::<F>), 692 &mut cb as *mut _ as *mut _, 693 )) 694 .map(|p| PKey::from_ptr(p)) 695 } 696 } 697 698 /// Deserializes a DER-formatted PKCS#8 private key, using the supplied password if the key is 699 /// encrypted. 700 /// 701 /// # Panics 702 /// 703 /// Panics if `passphrase` contains an embedded null. 704 #[corresponds(d2i_PKCS8PrivateKey_bio)] private_key_from_pkcs8_passphrase( der: &[u8], passphrase: &[u8], ) -> Result<PKey<Private>, ErrorStack>705 pub fn private_key_from_pkcs8_passphrase( 706 der: &[u8], 707 passphrase: &[u8], 708 ) -> Result<PKey<Private>, ErrorStack> { 709 unsafe { 710 ffi::init(); 711 let bio = MemBioSlice::new(der)?; 712 let passphrase = CString::new(passphrase).unwrap(); 713 cvt_p(ffi::d2i_PKCS8PrivateKey_bio( 714 bio.as_ptr(), 715 ptr::null_mut(), 716 None, 717 passphrase.as_ptr() as *const _ as *mut _, 718 )) 719 .map(|p| PKey::from_ptr(p)) 720 } 721 } 722 723 /// Creates a private key from its raw byte representation 724 /// 725 /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448 726 #[corresponds(EVP_PKEY_new_raw_private_key)] 727 #[cfg(any(ossl111, boringssl, libressl370))] private_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Private>, ErrorStack>728 pub fn private_key_from_raw_bytes( 729 bytes: &[u8], 730 key_type: Id, 731 ) -> Result<PKey<Private>, ErrorStack> { 732 unsafe { 733 ffi::init(); 734 cvt_p(ffi::EVP_PKEY_new_raw_private_key( 735 key_type.as_raw(), 736 ptr::null_mut(), 737 bytes.as_ptr(), 738 bytes.len(), 739 )) 740 .map(|p| PKey::from_ptr(p)) 741 } 742 } 743 } 744 745 impl PKey<Public> { 746 from_pem! { 747 /// Decodes a PEM-encoded SubjectPublicKeyInfo structure. 748 /// 749 /// The input should have a header of `-----BEGIN PUBLIC KEY-----`. 750 #[corresponds(PEM_read_bio_PUBKEY)] 751 public_key_from_pem, 752 PKey<Public>, 753 ffi::PEM_read_bio_PUBKEY 754 } 755 756 from_der! { 757 /// Decodes a DER-encoded SubjectPublicKeyInfo structure. 758 #[corresponds(d2i_PUBKEY)] 759 public_key_from_der, 760 PKey<Public>, 761 ffi::d2i_PUBKEY 762 } 763 764 /// Creates a public key from its raw byte representation 765 /// 766 /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448 767 #[corresponds(EVP_PKEY_new_raw_public_key)] 768 #[cfg(any(ossl111, boringssl, libressl370))] public_key_from_raw_bytes( bytes: &[u8], key_type: Id, ) -> Result<PKey<Public>, ErrorStack>769 pub fn public_key_from_raw_bytes( 770 bytes: &[u8], 771 key_type: Id, 772 ) -> Result<PKey<Public>, ErrorStack> { 773 unsafe { 774 ffi::init(); 775 cvt_p(ffi::EVP_PKEY_new_raw_public_key( 776 key_type.as_raw(), 777 ptr::null_mut(), 778 bytes.as_ptr(), 779 bytes.len(), 780 )) 781 .map(|p| PKey::from_ptr(p)) 782 } 783 } 784 } 785 786 cfg_if! { 787 if #[cfg(any(boringssl, ossl110, libressl270))] { 788 use ffi::EVP_PKEY_up_ref; 789 } else { 790 #[allow(bad_style)] 791 unsafe extern "C" fn EVP_PKEY_up_ref(pkey: *mut ffi::EVP_PKEY) { 792 ffi::CRYPTO_add_lock( 793 &mut (*pkey).references, 794 1, 795 ffi::CRYPTO_LOCK_EVP_PKEY, 796 "pkey.rs\0".as_ptr() as *const _, 797 line!() as c_int, 798 ); 799 } 800 } 801 } 802 803 impl<T> TryFrom<EcKey<T>> for PKey<T> { 804 type Error = ErrorStack; 805 try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack>806 fn try_from(ec_key: EcKey<T>) -> Result<PKey<T>, ErrorStack> { 807 PKey::from_ec_key(ec_key) 808 } 809 } 810 811 impl<T> TryFrom<PKey<T>> for EcKey<T> { 812 type Error = ErrorStack; 813 try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack>814 fn try_from(pkey: PKey<T>) -> Result<EcKey<T>, ErrorStack> { 815 pkey.ec_key() 816 } 817 } 818 819 impl<T> TryFrom<Rsa<T>> for PKey<T> { 820 type Error = ErrorStack; 821 try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack>822 fn try_from(rsa: Rsa<T>) -> Result<PKey<T>, ErrorStack> { 823 PKey::from_rsa(rsa) 824 } 825 } 826 827 impl<T> TryFrom<PKey<T>> for Rsa<T> { 828 type Error = ErrorStack; 829 try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack>830 fn try_from(pkey: PKey<T>) -> Result<Rsa<T>, ErrorStack> { 831 pkey.rsa() 832 } 833 } 834 835 impl<T> TryFrom<Dsa<T>> for PKey<T> { 836 type Error = ErrorStack; 837 try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack>838 fn try_from(dsa: Dsa<T>) -> Result<PKey<T>, ErrorStack> { 839 PKey::from_dsa(dsa) 840 } 841 } 842 843 impl<T> TryFrom<PKey<T>> for Dsa<T> { 844 type Error = ErrorStack; 845 try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack>846 fn try_from(pkey: PKey<T>) -> Result<Dsa<T>, ErrorStack> { 847 pkey.dsa() 848 } 849 } 850 851 #[cfg(not(boringssl))] 852 impl<T> TryFrom<Dh<T>> for PKey<T> { 853 type Error = ErrorStack; 854 try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack>855 fn try_from(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> { 856 PKey::from_dh(dh) 857 } 858 } 859 860 impl<T> TryFrom<PKey<T>> for Dh<T> { 861 type Error = ErrorStack; 862 try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack>863 fn try_from(pkey: PKey<T>) -> Result<Dh<T>, ErrorStack> { 864 pkey.dh() 865 } 866 } 867 868 #[cfg(test)] 869 mod tests { 870 use std::convert::TryInto; 871 872 #[cfg(not(boringssl))] 873 use crate::dh::Dh; 874 use crate::dsa::Dsa; 875 use crate::ec::EcKey; 876 use crate::error::Error; 877 use crate::nid::Nid; 878 use crate::rsa::Rsa; 879 use crate::symm::Cipher; 880 881 use super::*; 882 883 #[cfg(ossl111)] 884 use crate::rand::rand_bytes; 885 886 #[test] test_to_password()887 fn test_to_password() { 888 let rsa = Rsa::generate(2048).unwrap(); 889 let pkey = PKey::from_rsa(rsa).unwrap(); 890 let pem = pkey 891 .private_key_to_pem_pkcs8_passphrase(Cipher::aes_128_cbc(), b"foobar") 892 .unwrap(); 893 PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); 894 assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); 895 } 896 897 #[test] test_unencrypted_pkcs8()898 fn test_unencrypted_pkcs8() { 899 let key = include_bytes!("../test/pkcs8-nocrypt.der"); 900 let pkey = PKey::private_key_from_pkcs8(key).unwrap(); 901 let serialized = pkey.private_key_to_pkcs8().unwrap(); 902 let pkey2 = PKey::private_key_from_pkcs8(&serialized).unwrap(); 903 904 assert_eq!( 905 pkey2.private_key_to_der().unwrap(), 906 pkey.private_key_to_der().unwrap() 907 ); 908 } 909 910 #[test] test_encrypted_pkcs8_passphrase()911 fn test_encrypted_pkcs8_passphrase() { 912 let key = include_bytes!("../test/pkcs8.der"); 913 PKey::private_key_from_pkcs8_passphrase(key, b"mypass").unwrap(); 914 915 let rsa = Rsa::generate(2048).unwrap(); 916 let pkey = PKey::from_rsa(rsa).unwrap(); 917 let der = pkey 918 .private_key_to_pkcs8_passphrase(Cipher::aes_128_cbc(), b"mypass") 919 .unwrap(); 920 let pkey2 = PKey::private_key_from_pkcs8_passphrase(&der, b"mypass").unwrap(); 921 assert_eq!( 922 pkey.private_key_to_der().unwrap(), 923 pkey2.private_key_to_der().unwrap() 924 ); 925 } 926 927 #[test] test_encrypted_pkcs8_callback()928 fn test_encrypted_pkcs8_callback() { 929 let mut password_queried = false; 930 let key = include_bytes!("../test/pkcs8.der"); 931 PKey::private_key_from_pkcs8_callback(key, |password| { 932 password_queried = true; 933 password[..6].copy_from_slice(b"mypass"); 934 Ok(6) 935 }) 936 .unwrap(); 937 assert!(password_queried); 938 } 939 940 #[test] test_private_key_from_pem()941 fn test_private_key_from_pem() { 942 let key = include_bytes!("../test/key.pem"); 943 PKey::private_key_from_pem(key).unwrap(); 944 } 945 946 #[test] test_public_key_from_pem()947 fn test_public_key_from_pem() { 948 let key = include_bytes!("../test/key.pem.pub"); 949 PKey::public_key_from_pem(key).unwrap(); 950 } 951 952 #[test] test_public_key_from_der()953 fn test_public_key_from_der() { 954 let key = include_bytes!("../test/key.der.pub"); 955 PKey::public_key_from_der(key).unwrap(); 956 } 957 958 #[test] test_private_key_from_der()959 fn test_private_key_from_der() { 960 let key = include_bytes!("../test/key.der"); 961 PKey::private_key_from_der(key).unwrap(); 962 } 963 964 #[test] test_pem()965 fn test_pem() { 966 let key = include_bytes!("../test/key.pem"); 967 let key = PKey::private_key_from_pem(key).unwrap(); 968 969 let priv_key = key.private_key_to_pem_pkcs8().unwrap(); 970 let pub_key = key.public_key_to_pem().unwrap(); 971 972 // As a super-simple verification, just check that the buffers contain 973 // the `PRIVATE KEY` or `PUBLIC KEY` strings. 974 assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); 975 assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); 976 } 977 978 #[test] test_rsa_accessor()979 fn test_rsa_accessor() { 980 let rsa = Rsa::generate(2048).unwrap(); 981 let pkey = PKey::from_rsa(rsa).unwrap(); 982 pkey.rsa().unwrap(); 983 assert_eq!(pkey.id(), Id::RSA); 984 assert!(pkey.dsa().is_err()); 985 } 986 987 #[test] test_dsa_accessor()988 fn test_dsa_accessor() { 989 let dsa = Dsa::generate(2048).unwrap(); 990 let pkey = PKey::from_dsa(dsa).unwrap(); 991 pkey.dsa().unwrap(); 992 assert_eq!(pkey.id(), Id::DSA); 993 assert!(pkey.rsa().is_err()); 994 } 995 996 #[test] 997 #[cfg(not(boringssl))] test_dh_accessor()998 fn test_dh_accessor() { 999 let dh = include_bytes!("../test/dhparams.pem"); 1000 let dh = Dh::params_from_pem(dh).unwrap(); 1001 let pkey = PKey::from_dh(dh).unwrap(); 1002 pkey.dh().unwrap(); 1003 assert_eq!(pkey.id(), Id::DH); 1004 assert!(pkey.rsa().is_err()); 1005 } 1006 1007 #[test] test_ec_key_accessor()1008 fn test_ec_key_accessor() { 1009 let ec_key = EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 1010 let pkey = PKey::from_ec_key(ec_key).unwrap(); 1011 pkey.ec_key().unwrap(); 1012 assert_eq!(pkey.id(), Id::EC); 1013 assert!(pkey.rsa().is_err()); 1014 } 1015 1016 #[test] test_rsa_conversion()1017 fn test_rsa_conversion() { 1018 let rsa = Rsa::generate(2048).unwrap(); 1019 let pkey: PKey<Private> = rsa.clone().try_into().unwrap(); 1020 let rsa_: Rsa<Private> = pkey.try_into().unwrap(); 1021 // Eq is missing 1022 assert_eq!(rsa.p(), rsa_.p()); 1023 assert_eq!(rsa.q(), rsa_.q()); 1024 } 1025 1026 #[test] test_dsa_conversion()1027 fn test_dsa_conversion() { 1028 let dsa = Dsa::generate(2048).unwrap(); 1029 let pkey: PKey<Private> = dsa.clone().try_into().unwrap(); 1030 let dsa_: Dsa<Private> = pkey.try_into().unwrap(); 1031 // Eq is missing 1032 assert_eq!(dsa.priv_key(), dsa_.priv_key()); 1033 } 1034 1035 #[test] test_ec_key_conversion()1036 fn test_ec_key_conversion() { 1037 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::X9_62_PRIME256V1).unwrap(); 1038 let ec_key = EcKey::generate(&group).unwrap(); 1039 let pkey: PKey<Private> = ec_key.clone().try_into().unwrap(); 1040 let ec_key_: EcKey<Private> = pkey.try_into().unwrap(); 1041 // Eq is missing 1042 assert_eq!(ec_key.private_key(), ec_key_.private_key()); 1043 } 1044 1045 #[test] 1046 #[cfg(any(ossl110, libressl360))] test_security_bits()1047 fn test_security_bits() { 1048 let group = crate::ec::EcGroup::from_curve_name(crate::nid::Nid::SECP521R1).unwrap(); 1049 let ec_key = EcKey::generate(&group).unwrap(); 1050 let pkey: PKey<Private> = ec_key.try_into().unwrap(); 1051 1052 assert_eq!(pkey.security_bits(), 256); 1053 } 1054 1055 #[test] 1056 #[cfg(not(boringssl))] test_dh_conversion()1057 fn test_dh_conversion() { 1058 let dh_params = include_bytes!("../test/dhparams.pem"); 1059 let dh_params = Dh::params_from_pem(dh_params).unwrap(); 1060 let dh = dh_params.generate_key().unwrap(); 1061 1062 // Clone is missing for Dh, save the parameters 1063 let p = dh.prime_p().to_owned().unwrap(); 1064 let q = dh.prime_q().map(|q| q.to_owned().unwrap()); 1065 let g = dh.generator().to_owned().unwrap(); 1066 1067 let pkey: PKey<Private> = dh.try_into().unwrap(); 1068 let dh_: Dh<Private> = pkey.try_into().unwrap(); 1069 1070 // Eq is missing 1071 assert_eq!(&p, dh_.prime_p()); 1072 assert_eq!(q, dh_.prime_q().map(|q| q.to_owned().unwrap())); 1073 assert_eq!(&g, dh_.generator()); 1074 } 1075 1076 #[cfg(any(ossl111, boringssl, libressl370))] test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1077 fn test_raw_public_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) { 1078 // Generate a new key 1079 let key = gen().unwrap(); 1080 1081 // Get the raw bytes, and create a new key from the raw bytes 1082 let raw = key.raw_public_key().unwrap(); 1083 let from_raw = PKey::public_key_from_raw_bytes(&raw, key_type).unwrap(); 1084 1085 // Compare the der encoding of the original and raw / restored public key 1086 assert_eq!( 1087 key.public_key_to_der().unwrap(), 1088 from_raw.public_key_to_der().unwrap() 1089 ); 1090 } 1091 1092 #[cfg(any(ossl111, boringssl, libressl370))] test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id)1093 fn test_raw_private_key(gen: fn() -> Result<PKey<Private>, ErrorStack>, key_type: Id) { 1094 // Generate a new key 1095 let key = gen().unwrap(); 1096 1097 // Get the raw bytes, and create a new key from the raw bytes 1098 let raw = key.raw_private_key().unwrap(); 1099 let from_raw = PKey::private_key_from_raw_bytes(&raw, key_type).unwrap(); 1100 1101 // Compare the der encoding of the original and raw / restored public key 1102 assert_eq!( 1103 key.private_key_to_pkcs8().unwrap(), 1104 from_raw.private_key_to_pkcs8().unwrap() 1105 ); 1106 } 1107 1108 #[cfg(any(ossl111, boringssl, libressl370))] 1109 #[test] test_raw_public_key_bytes()1110 fn test_raw_public_key_bytes() { 1111 test_raw_public_key(PKey::generate_x25519, Id::X25519); 1112 test_raw_public_key(PKey::generate_ed25519, Id::ED25519); 1113 #[cfg(all(not(boringssl), not(libressl370)))] 1114 test_raw_public_key(PKey::generate_x448, Id::X448); 1115 #[cfg(all(not(boringssl), not(libressl370)))] 1116 test_raw_public_key(PKey::generate_ed448, Id::ED448); 1117 } 1118 1119 #[cfg(any(ossl111, boringssl, libressl370))] 1120 #[test] test_raw_private_key_bytes()1121 fn test_raw_private_key_bytes() { 1122 test_raw_private_key(PKey::generate_x25519, Id::X25519); 1123 test_raw_private_key(PKey::generate_ed25519, Id::ED25519); 1124 #[cfg(all(not(boringssl), not(libressl370)))] 1125 test_raw_private_key(PKey::generate_x448, Id::X448); 1126 #[cfg(all(not(boringssl), not(libressl370)))] 1127 test_raw_private_key(PKey::generate_ed448, Id::ED448); 1128 } 1129 1130 #[cfg(ossl111)] 1131 #[test] test_raw_hmac()1132 fn test_raw_hmac() { 1133 let mut test_bytes = vec![0u8; 32]; 1134 rand_bytes(&mut test_bytes).unwrap(); 1135 1136 let hmac_key = PKey::hmac(&test_bytes).unwrap(); 1137 assert!(hmac_key.raw_public_key().is_err()); 1138 1139 let key_bytes = hmac_key.raw_private_key().unwrap(); 1140 assert_eq!(key_bytes, test_bytes); 1141 } 1142 1143 #[cfg(ossl111)] 1144 #[test] test_raw_key_fail()1145 fn test_raw_key_fail() { 1146 // Getting a raw byte representation will not work with Nist curves 1147 let group = crate::ec::EcGroup::from_curve_name(Nid::SECP256K1).unwrap(); 1148 let ec_key = EcKey::generate(&group).unwrap(); 1149 let pkey = PKey::from_ec_key(ec_key).unwrap(); 1150 assert!(pkey.raw_private_key().is_err()); 1151 assert!(pkey.raw_public_key().is_err()); 1152 } 1153 1154 #[cfg(ossl300)] 1155 #[test] test_ec_gen()1156 fn test_ec_gen() { 1157 let key = PKey::ec_gen("prime256v1").unwrap(); 1158 assert!(key.ec_key().is_ok()); 1159 } 1160 1161 #[test] test_public_eq()1162 fn test_public_eq() { 1163 let rsa = Rsa::generate(2048).unwrap(); 1164 let pkey1 = PKey::from_rsa(rsa).unwrap(); 1165 1166 let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 1167 let ec_key = EcKey::generate(&group).unwrap(); 1168 let pkey2 = PKey::from_ec_key(ec_key).unwrap(); 1169 1170 assert!(!pkey1.public_eq(&pkey2)); 1171 assert!(Error::get().is_none()); 1172 } 1173 } 1174