Support serialization of encrypted private keys
Switch to PEM_write_bio_PKCS8PrivateKey since the other function outputs nonstandard PEM when encrypting.
This commit is contained in:
parent
7d411c7975
commit
387e78257b
|
|
@ -1496,6 +1496,10 @@ extern {
|
||||||
kstr: *mut c_uchar, klen: c_int,
|
kstr: *mut c_uchar, klen: c_int,
|
||||||
callback: Option<PasswordCallback>,
|
callback: Option<PasswordCallback>,
|
||||||
user_data: *mut c_void) -> c_int;
|
user_data: *mut c_void) -> c_int;
|
||||||
|
pub fn PEM_write_bio_PKCS8PrivateKey(bio: *mut BIO, pkey: *mut EVP_PKEY, cipher: *const EVP_CIPHER,
|
||||||
|
kstr: *mut c_char, klen: c_int,
|
||||||
|
callback: Option<PasswordCallback>,
|
||||||
|
user_data: *mut c_void) -> c_int;
|
||||||
pub fn PEM_write_bio_PUBKEY(bp: *mut BIO, x: *mut EVP_PKEY) -> c_int;
|
pub fn PEM_write_bio_PUBKEY(bp: *mut BIO, x: *mut EVP_PKEY) -> c_int;
|
||||||
pub fn PEM_write_bio_RSAPrivateKey(bp: *mut BIO, rsa: *mut RSA, cipher: *const EVP_CIPHER,
|
pub fn PEM_write_bio_RSAPrivateKey(bp: *mut BIO, rsa: *mut RSA, cipher: *const EVP_CIPHER,
|
||||||
kstr: *mut c_uchar, klen: c_int,
|
kstr: *mut c_uchar, klen: c_int,
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,8 @@ mod compat {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use symm::Cipher;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -220,6 +222,14 @@ mod test {
|
||||||
Dsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
Dsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_to_password() {
|
||||||
|
let key = Dsa::generate(2048).unwrap();
|
||||||
|
let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap();
|
||||||
|
Dsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
|
||||||
|
assert!(Dsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_password_callback() {
|
pub fn test_password_callback() {
|
||||||
let mut password_queried = false;
|
let mut password_queried = false;
|
||||||
|
|
|
||||||
|
|
@ -113,5 +113,25 @@ macro_rules! private_key_to_pem {
|
||||||
Ok(bio.get_buf().to_owned())
|
Ok(bio.get_buf().to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Serializes the private key to PEM, encrypting it with the specified symmetric cipher and
|
||||||
|
/// passphrase.
|
||||||
|
pub fn private_key_to_pem_passphrase(&self,
|
||||||
|
cipher: ::symm::Cipher,
|
||||||
|
passphrase: &[u8])
|
||||||
|
-> Result<Vec<u8>, ::error::ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
let bio = try!(::bio::MemBio::new());
|
||||||
|
assert!(passphrase.len() <= ::libc::c_int::max_value() as usize);
|
||||||
|
try!(cvt($f(bio.as_ptr(),
|
||||||
|
self.as_ptr(),
|
||||||
|
cipher.as_ptr(),
|
||||||
|
passphrase.as_ptr() as *const _ as *mut _,
|
||||||
|
passphrase.len() as ::libc::c_int,
|
||||||
|
None,
|
||||||
|
ptr::null_mut())));
|
||||||
|
Ok(bio.get_buf().to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ impl PKeyRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private_key_to_pem!(ffi::PEM_write_bio_PrivateKey);
|
private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey);
|
||||||
|
|
||||||
/// Encodes the public key in the PEM format.
|
/// Encodes the public key in the PEM format.
|
||||||
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
pub fn public_key_to_pem(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||||
|
|
@ -185,6 +185,7 @@ impl PKey {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use symm::Cipher;
|
||||||
use dh::Dh;
|
use dh::Dh;
|
||||||
use dsa::Dsa;
|
use dsa::Dsa;
|
||||||
use ec_key::EcKey;
|
use ec_key::EcKey;
|
||||||
|
|
@ -193,6 +194,15 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_to_password() {
|
||||||
|
let rsa = Rsa::generate(2048).unwrap();
|
||||||
|
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||||
|
let pem = pkey.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap();
|
||||||
|
PKey::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
|
||||||
|
assert!(PKey::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_private_key_from_pem() {
|
fn test_private_key_from_pem() {
|
||||||
let key = include_bytes!("../test/key.pem");
|
let key = include_bytes!("../test/key.pem");
|
||||||
|
|
|
||||||
|
|
@ -404,16 +404,18 @@ mod compat {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use symm::Cipher;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_password() {
|
fn test_from_password() {
|
||||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||||
Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_password_callback() {
|
fn test_from_password_callback() {
|
||||||
let mut password_queried = false;
|
let mut password_queried = false;
|
||||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||||
Rsa::private_key_from_pem_callback(key, |password| {
|
Rsa::private_key_from_pem_callback(key, |password| {
|
||||||
|
|
@ -427,7 +429,15 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_public_encrypt_private_decrypt_with_padding() {
|
fn test_to_password() {
|
||||||
|
let key = Rsa::generate(2048).unwrap();
|
||||||
|
let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar").unwrap();
|
||||||
|
Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
|
||||||
|
assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_public_encrypt_private_decrypt_with_padding() {
|
||||||
let key = include_bytes!("../test/rsa.pem.pub");
|
let key = include_bytes!("../test/rsa.pem.pub");
|
||||||
let public_key = Rsa::public_key_from_pem(key).unwrap();
|
let public_key = Rsa::public_key_from_pem(key).unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue