Rename key serialization/deserialization methods

Also document their specific formats.

Closes #502
This commit is contained in:
Steven Fackler 2018-01-06 08:36:35 -08:00
parent 753a7d07b1
commit 3c19702299
14 changed files with 595 additions and 305 deletions

View File

@ -2620,6 +2620,8 @@ extern "C" {
pub fn d2i_DSAPrivateKey(a: *mut *mut DSA, pp: *mut *const c_uchar, length: c_long)
-> *mut DSA;
pub fn i2d_DSAPrivateKey(a: *const DSA, pp: *mut *mut c_uchar) -> c_int;
pub fn d2i_DSA_PUBKEY(k: *mut *mut DSA, pp: *mut *const c_uchar, length: c_long) -> *mut DSA;
pub fn i2d_DSA_PUBKEY(a: *mut DSA, pp: *mut *mut c_uchar) -> c_int;
pub fn d2i_ECPrivateKey(
k: *mut *mut EC_KEY,

View File

@ -21,8 +21,27 @@ impl<T> DhRef<T>
where
T: HasParams,
{
to_pem!(ffi::PEM_write_bio_DHparams);
to_der!(ffi::i2d_DHparams);
to_pem! {
/// Serializes the parameters into a PEM-encoded PKCS#3 DHparameter structure.
///
/// The output will have a header of `-----BEGIN DH PARAMETERS-----`.
///
/// This corresponds to [`PEM_write_bio_DHparams`].
///
/// [`PEM_write_bio_DHparams`]: https://www.openssl.org/docs/manmaster/man3/PEM_write_bio_DHparams.html
params_to_pem,
ffi::PEM_write_bio_DHparams
}
to_der! {
/// Serializes the parameters into a DER-encoded PKCS#3 DHparameter structure.
///
/// This corresponds to [`i2d_DHparams`].
///
/// [`i2d_DHparams`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DHparams.html
params_to_der,
ffi::i2d_DHparams
}
}
impl Dh<Params> {
@ -40,8 +59,29 @@ impl Dh<Params> {
}
}
from_pem!(Dh<Params>, ffi::PEM_read_bio_DHparams);
from_der!(Dh<Params>, ffi::d2i_DHparams);
from_pem! {
/// Deserializes a PEM-encoded PKCS#3 DHpararameters structure.
///
/// The input should have a header of `-----BEGIN DH PARAMETERS-----`.
///
/// This corresponds to [`PEM_read_bio_DHparams`].
///
/// [`PEM_read_bio_DHparams`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DHparams.html
params_from_pem,
Dh<Params>,
ffi::PEM_read_bio_DHparams
}
from_der! {
/// Deserializes a DER-encoded PKCS#3 DHparameters structure.
///
/// This corresponds to [`d2i_DHparams`].
///
/// [`d2i_DHparams`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_DHparams.html
params_from_der,
Dh<Params>,
ffi::d2i_DHparams
}
/// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
@ -143,15 +183,15 @@ mod tests {
fn test_dh_from_pem() {
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
let params = include_bytes!("../test/dhparams.pem");
let dh = Dh::from_pem(params).unwrap();
let dh = Dh::params_from_pem(params).unwrap();
ctx.set_tmp_dh(&dh).unwrap();
}
#[test]
fn test_dh_from_der() {
let params = include_bytes!("../test/dhparams.pem");
let dh = Dh::from_pem(params).unwrap();
let der = dh.to_der().unwrap();
Dh::from_der(&der).unwrap();
let dh = Dh::params_from_pem(params).unwrap();
let der = dh.params_to_der().unwrap();
Dh::params_from_der(&der).unwrap();
}
}

View File

@ -14,7 +14,7 @@ use std::ptr;
use {cvt, cvt_p};
use bn::BigNumRef;
use error::ErrorStack;
use pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
use pkey::{HasParams, HasPublic, Private, Public};
generic_foreign_type_and_impl_send_sync! {
type CType = ffi::DSA;
@ -58,20 +58,31 @@ generic_foreign_type_and_impl_send_sync! {
pub struct DsaRef<T>;
}
impl<T> DsaRef<T>
where
T: HasPrivate,
{
private_key_to_pem!(ffi::PEM_write_bio_DSAPrivateKey);
private_key_to_der!(ffi::i2d_DSAPrivateKey);
}
impl<T> DsaRef<T>
where
T: HasPublic,
{
public_key_to_pem!(ffi::PEM_write_bio_DSA_PUBKEY);
public_key_to_der!(ffi::i2d_DSAPublicKey);
to_pem! {
/// Serialies the public key into a PEM-encoded SubjectPublicKeyInfo structure.
///
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_write_bio_DSA_PUBKEY`].
///
/// [`PEM_write_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSA_PUBKEY.html
public_key_to_pem,
ffi::PEM_write_bio_DSA_PUBKEY
}
to_der! {
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
///
/// This corresponds to [`i2d_DSA_PUBKEY`].
///
/// [`i2d_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DSA_PUBKEY.html
public_key_to_der,
ffi::i2d_DSA_PUBKEY
}
}
impl<T> DsaRef<T>
@ -139,14 +150,32 @@ impl Dsa<Private> {
Ok(dsa)
}
}
private_key_from_pem!(Dsa<Private>, ffi::PEM_read_bio_DSAPrivateKey);
private_key_from_der!(Dsa<Private>, ffi::d2i_DSAPrivateKey);
}
impl Dsa<Public> {
public_key_from_pem!(Dsa<Public>, ffi::PEM_read_bio_DSA_PUBKEY);
public_key_from_der!(Dsa<Public>, ffi::d2i_DSAPublicKey);
from_pem! {
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
///
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_read_bio_DSA_PUBKEY`].
///
/// [`PEM_read_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DSA_PUBKEY.html
public_key_from_pem,
Dsa<Public>,
ffi::PEM_read_bio_DSA_PUBKEY
}
from_der! {
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
///
/// This corresponds to [`d2i_DSA_PUBKEY`].
///
/// [`d2i_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_DSA_PUBKEY.html
public_key_from_der,
Dsa<Public>,
ffi::d2i_DSA_PUBKEY
}
}
impl<T> fmt::Debug for Dsa<T> {
@ -178,40 +207,10 @@ mod compat {
#[cfg(test)]
mod test {
use symm::Cipher;
use super::*;
#[test]
pub fn test_generate() {
Dsa::generate(1024).unwrap();
}
#[test]
pub fn test_password() {
let key = include_bytes!("../test/dsa-encrypted.pem");
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]
pub fn test_password_callback() {
let mut password_queried = false;
let key = include_bytes!("../test/dsa-encrypted.pem");
Dsa::private_key_from_pem_callback(key, |password| {
password_queried = true;
password[..6].copy_from_slice(b"mypass");
Ok(6)
}).unwrap();
assert!(password_queried);
}
}

View File

@ -522,8 +522,35 @@ impl<T> EcKeyRef<T>
where
T: HasPrivate,
{
private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey);
private_key_to_der!(ffi::i2d_ECPrivateKey);
private_key_to_pem! {
/// Serializes the private key to a PEM-encoded ECPrivateKey structure.
///
/// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_ECPrivateKey`].
///
/// [`PEM_write_bio_ECPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_ECPrivateKey.html
private_key_to_pem,
/// Serializes the private key to a PEM-encoded encrypted ECPrivateKey structure.
///
/// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_ECPrivateKey`].
///
/// [`PEM_write_bio_ECPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_ECPrivateKey.html
private_key_to_pem_passphrase,
ffi::PEM_write_bio_ECPrivateKey
}
to_der! {
/// Serializes the private key into a DER-encoded ECPrivateKey structure.
///
/// This corresponds to [`i2d_ECPrivateKey`].
///
/// [`i2d_ECPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivate_key.html
private_key_to_der,
ffi::i2d_ECPrivateKey
}
/// Return [`EcPoint`] associated with the private key
///
@ -702,8 +729,43 @@ impl EcKey<Private> {
}
}
private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey);
private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey);
private_key_from_pem! {
/// Deserializes a private key from a PEM-encoded ECPrivateKey structure.
///
/// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
///
/// This corresponds to `PEM_read_bio_ECPrivateKey`.
private_key_from_pem,
/// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
///
/// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
///
/// This corresponds to `PEM_read_bio_ECPrivateKey`.
private_key_from_pem_passphrase,
/// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
///
/// The callback should fill the password into the provided buffer and return its length.
///
/// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
///
/// This corresponds to `PEM_read_bio_ECPrivateKey`.
private_key_from_pem_callback,
EcKey<Private>,
ffi::PEM_read_bio_ECPrivateKey
}
from_der! {
/// Decodes a DER-encoded elliptic curve private key structure.
///
/// This corresponds to [`d2i_ECPrivateKey`].
///
/// [`d2i_ECPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_ECPrivate_key.html
private_key_from_der,
EcKey<Private>,
ffi::d2i_ECPrivateKey
}
}
impl<T> Clone for EcKey<T> {

View File

@ -1,18 +1,9 @@
macro_rules! private_key_from_pem {
($t:ty, $f:path) => {
from_pem_inner!(/// Deserializes a PEM-formatted private key.
private_key_from_pem, $t, $f);
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $(#[$m3:meta])* $n3:ident, $t:ty, $f:path) => {
from_pem!($(#[$m])* $n, $t, $f);
/// Deserializes a PEM-formatted private key, using the supplied password if the key is
/// encrypted.
///
/// # Panics
///
/// Panics if `passphrase` contains an embedded null.
pub fn private_key_from_pem_passphrase(pem: &[u8],
passphrase: &[u8])
-> Result<$t, ::error::ErrorStack> {
$(#[$m2])*
pub fn $n2(pem: &[u8], passphrase: &[u8]) -> Result<$t, ::error::ErrorStack> {
unsafe {
ffi::init();
let bio = try!(::bio::MemBioSlice::new(pem));
@ -25,14 +16,8 @@ macro_rules! private_key_from_pem {
}
}
/// Deserializes a PEM-formatted private key, using a callback to retrieve a password if the
/// key is encrypted.
///
/// The callback should copy the password into the provided buffer and return the number of
/// bytes written.
pub fn private_key_from_pem_callback<F>(pem: &[u8],
callback: F)
-> Result<$t, ::error::ErrorStack>
$(#[$m3])*
pub fn $n3<F>(pem: &[u8], callback: F) -> Result<$t, ::error::ErrorStack>
where F: FnOnce(&mut [u8]) -> Result<usize, ::error::ErrorStack>
{
unsafe {
@ -50,9 +35,9 @@ macro_rules! private_key_from_pem {
}
macro_rules! private_key_to_pem {
($f:path) => {
/// Serializes the private key to PEM.
pub fn private_key_to_pem(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $f:path) => {
$(#[$m])*
pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
unsafe {
let bio = try!(::bio::MemBio::new());
try!(cvt($f(bio.as_ptr(),
@ -66,12 +51,12 @@ macro_rules! private_key_to_pem {
}
}
/// Serializes the private key to PEM, encrypting it with the specified symmetric cipher and
/// passphrase.
pub fn private_key_to_pem_passphrase(&self,
$(#[$m2])*
pub fn $n2(
&self,
cipher: ::symm::Cipher,
passphrase: &[u8])
-> Result<Vec<u8>, ::error::ErrorStack> {
passphrase: &[u8]
) -> Result<Vec<u8>, ::error::ErrorStack> {
unsafe {
let bio = try!(::bio::MemBio::new());
assert!(passphrase.len() <= ::libc::c_int::max_value() as usize);
@ -88,9 +73,9 @@ macro_rules! private_key_to_pem {
}
}
macro_rules! to_pem_inner {
(#[$m:meta] $n:ident, $f:path) => {
#[$m]
macro_rules! to_pem {
($(#[$m:meta])* $n:ident, $f:path) => {
$(#[$m])*
pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
unsafe {
let bio = try!(::bio::MemBio::new());
@ -101,23 +86,9 @@ macro_rules! to_pem_inner {
}
}
macro_rules! public_key_to_pem {
($f:path) => {
to_pem_inner!(/// Serializes a public key to PEM.
public_key_to_pem, $f);
}
}
macro_rules! to_pem {
($f:path) => {
to_pem_inner!(/// Serializes this value to PEM.
to_pem, $f);
}
}
macro_rules! to_der_inner {
(#[$m:meta] $n:ident, $f:path) => {
#[$m]
macro_rules! to_der {
($(#[$m:meta])* $n:ident, $f:path) => {
$(#[$m])*
pub fn $n(&self) -> Result<Vec<u8>, ::error::ErrorStack> {
unsafe {
let len = try!(::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
@ -131,30 +102,9 @@ macro_rules! to_der_inner {
};
}
macro_rules! to_der {
($f:path) => {
to_der_inner!(/// Serializes this value to DER.
to_der, $f);
}
}
macro_rules! private_key_to_der {
($f:path) => {
to_der_inner!(/// Serializes the private key to DER.
private_key_to_der, $f);
}
}
macro_rules! public_key_to_der {
($f:path) => {
to_der_inner!(/// Serializes the public key to DER.
public_key_to_der, $f);
}
}
macro_rules! from_der_inner {
(#[$m:meta] $n:ident, $t:ty, $f:path) => {
#[$m]
macro_rules! from_der {
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
$(#[$m])*
pub fn $n(der: &[u8]) -> Result<$t, ::error::ErrorStack> {
unsafe {
::ffi::init();
@ -166,30 +116,9 @@ macro_rules! from_der_inner {
}
}
macro_rules! from_der {
($t:ty, $f:path) => {
from_der_inner!(/// Deserializes a value from DER-formatted data.
from_der, $t, $f);
}
}
macro_rules! private_key_from_der {
($t:ty, $f:path) => {
from_der_inner!(/// Deserializes a private key from DER-formatted data.
private_key_from_der, $t, $f);
}
}
macro_rules! public_key_from_der {
($t:ty, $f:path) => {
from_der_inner!(/// Deserializes a public key from DER-formatted data.
public_key_from_der, $t, $f);
}
}
macro_rules! from_pem_inner {
(#[$m:meta] $n:ident, $t:ty, $f:path) => {
#[$m]
macro_rules! from_pem {
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
$(#[$m])*
pub fn $n(pem: &[u8]) -> Result<$t, ::error::ErrorStack> {
unsafe {
::init();
@ -201,20 +130,6 @@ macro_rules! from_pem_inner {
}
}
macro_rules! public_key_from_pem {
($t:ty, $f:path) => {
from_pem_inner!(/// Deserializes a public key from PEM-formatted data.
public_key_from_pem, $t, $f);
}
}
macro_rules! from_pem {
($t:ty, $f:path) => {
from_pem_inner!(/// Deserializes a value from PEM-formatted data.
from_pem, $t, $f);
}
}
macro_rules! foreign_type_and_impl_send_sync {
(
$(#[$impl_attr:meta])*

View File

@ -253,11 +253,28 @@ impl OcspResponse {
}
}
from_der!(OcspResponse, ffi::d2i_OCSP_RESPONSE);
from_der! {
/// Deserializes a DER-encoded OCSP response.
///
/// This corresponds to [`d2i_OCSP_RESPONSE`].
///
/// [`d2i_OCSP_RESPONSE`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_OCSP_RESPONSE.html
from_der,
OcspResponse,
ffi::d2i_OCSP_RESPONSE
}
}
impl OcspResponseRef {
to_der!(ffi::i2d_OCSP_RESPONSE);
to_der! {
/// Serializes the response to its standard DER encoding.
///
/// This corresponds to [`i2d_OCSP_RESPONSE`].
///
/// [`i2d_OCSP_RESPONSE`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_OCSP_RESPONSE.html
to_der,
ffi::i2d_OCSP_RESPONSE
}
/// Returns the status of the response.
pub fn status(&self) -> OcspResponseStatus {
@ -289,11 +306,28 @@ impl OcspRequest {
}
}
from_der!(OcspRequest, ffi::d2i_OCSP_REQUEST);
from_der! {
/// Deserializes a DER-encoded OCSP request.
///
/// This corresponds to [`d2i_OCSP_REQUEST`].
///
/// [`d2i_OCSP_REQUEST`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_OCSP_REQUEST.html
from_der,
OcspRequest,
ffi::d2i_OCSP_REQUEST
}
}
impl OcspRequestRef {
to_der!(ffi::i2d_OCSP_REQUEST);
to_der! {
/// Serializes the request to its standard DER encoding.
///
/// This corresponds to [`i2d_OCSP_REQUEST`].
///
/// [`i2d_OCSP_REQUEST`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_OCSP_REQUEST.html
to_der,
ffi::i2d_OCSP_REQUEST
}
pub fn add_id(&mut self, id: OcspCertId) -> Result<&mut OcspOneReqRef, ErrorStack> {
unsafe {

View File

@ -22,7 +22,15 @@ foreign_type_and_impl_send_sync! {
}
impl Pkcs12Ref {
to_der!(ffi::i2d_PKCS12);
to_der! {
/// Serializes the `Pkcs12` to its standard DER encoding.
///
/// This corresponds to [`i2d_PKCS12`].
///
/// [`i2d_PKCS12`]: https://www.openssl.org/docs/manmaster/man3/i2d_PKCS12.html
to_der,
ffi::i2d_PKCS12
}
/// Extracts the contents of the `Pkcs12`.
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
@ -60,7 +68,16 @@ impl Pkcs12Ref {
}
impl Pkcs12 {
from_der!(Pkcs12, ffi::d2i_PKCS12);
from_der! {
/// Deserializes a DER-encoded PKCS#12 archive.
///
/// This corresponds to [`d2i_PKCS12`].
///
/// [`d2i_PKCS12`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_PKCS12.html
from_der,
Pkcs12,
ffi::d2i_PKCS12
}
/// Creates a new builder for a protected pkcs12 certificate.
///
@ -204,19 +221,14 @@ mod test {
let parsed = pkcs12.parse("mypass").unwrap();
assert_eq!(
hex::encode(parsed
.cert
.fingerprint(MessageDigest::sha1())
.unwrap()),
hex::encode(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap()),
"59172d9313e84459bcff27f967e79e6e9217e584"
);
let chain = parsed.chain.unwrap();
assert_eq!(chain.len(), 1);
assert_eq!(
hex::encode(chain[0]
.fingerprint(MessageDigest::sha1())
.unwrap()),
hex::encode(chain[0].fingerprint(MessageDigest::sha1()).unwrap()),
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
);
}

View File

@ -96,8 +96,27 @@ impl<T> PKeyRef<T>
where
T: HasPublic,
{
public_key_to_pem!(ffi::PEM_write_bio_PUBKEY);
public_key_to_der!(ffi::i2d_PUBKEY);
to_pem! {
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
///
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_write_bio_PUBKEY`].
///
/// [`PEM_write_bio_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_PUBKEY.html
public_key_to_pem,
ffi::PEM_write_bio_PUBKEY
}
to_der! {
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
///
/// This corresponds to [`i2d_PUBKEY`].
///
/// [`i2d_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_PUBKEY.html
public_key_to_der,
ffi::i2d_PUBKEY
}
/// Returns the size of the key.
///
@ -120,8 +139,35 @@ impl<T> PKeyRef<T>
where
T: HasPrivate,
{
private_key_to_pem!(ffi::PEM_write_bio_PKCS8PrivateKey);
private_key_to_der!(ffi::i2d_PrivateKey);
private_key_to_pem! {
/// Serializes the private key to a PEM-encoded PKCS#8 PrivateKeyInfo structure.
///
/// The output will have a header of `-----BEGIN PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_PKCS8PrivateKey`].
///
/// [`PEM_write_bio_PKCS8PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS8PrivateKey.html
private_key_to_pem_pkcs8,
/// Serializes the private key to a PEM-encoded PKCS#8 EncryptedPrivateKeyInfo structure.
///
/// The output will have a header of `-----BEGIN ENCRYPTED PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_PKCS8PrivateKey`].
///
/// [`PEM_write_bio_PKCS8PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_PKCS8PrivateKey.html
private_key_to_pem_pkcs8_passphrase,
ffi::PEM_write_bio_PKCS8PrivateKey
}
to_der! {
/// Serializes the private key to a DER-encoded key type specific format.
///
/// This corresponds to [`i2d_PrivateKey`].
///
/// [`i2d_PrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_PrivateKey.html
private_key_to_der,
ffi::i2d_PrivateKey
}
}
impl<T> PKey<T> {
@ -205,8 +251,47 @@ impl PKey<Private> {
}
}
private_key_from_pem!(PKey<Private>, ffi::PEM_read_bio_PrivateKey);
private_key_from_der!(PKey<Public>, ffi::d2i_AutoPrivateKey);
private_key_from_pem! {
/// Deserializes a private key from a PEM-encoded key type specific format.
///
/// This corresponds to [`PEM_read_bio_PrivateKey`].
///
/// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html
private_key_from_pem,
/// Deserializes a private key from a PEM-encoded encrypted key type specific format.
///
/// This corresponds to [`PEM_read_bio_PrivateKey`].
///
/// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html
private_key_from_pem_passphrase,
/// Deserializes a private key from a PEM-encoded encrypted key type specific format.
///
/// The callback should fill the password into the provided buffer and return its length.
///
/// This corresponds to [`PEM_read_bio_PrivateKey`].
///
/// [`PEM_read_bio_PrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_PrivateKey.html
private_key_from_pem_callback,
PKey<Private>,
ffi::PEM_read_bio_PrivateKey
}
from_der! {
/// Decodes a DER-encoded private key.
///
/// This function will automatically attempt to detect the underlying key format, and
/// supports the unencrypted PKCS#8 PrivateKeyInfo structures as well as key type specific
/// formats.
///
/// This corresponds to [`d2i_AutoPrivateKey`].
///
/// [`d2i_AutoPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_AutoPrivateKey.html
private_key_from_der,
PKey<Public>,
ffi::d2i_AutoPrivateKey
}
/// Deserializes a DER-formatted PKCS#8 private key, using a callback to retrieve the password
/// if the key is encrpyted.
@ -258,8 +343,29 @@ impl PKey<Private> {
}
impl PKey<Public> {
public_key_from_pem!(PKey<Public>, ffi::PEM_read_bio_PUBKEY);
public_key_from_der!(PKey<Public>, ffi::d2i_PUBKEY);
from_pem! {
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure.
///
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_read_bio_PUBKEY`].
///
/// [`PEM_read_bio_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_PUBKEY.html
public_key_from_pem,
PKey<Public>,
ffi::PEM_read_bio_PUBKEY
}
from_der! {
/// Decodes a DER-encoded SubjectPublicKeyInfo structure.
///
/// This corresponds to [`d2i_PUBKEY`].
///
/// [`d2i_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_PUBKEY.html
public_key_from_der,
PKey<Public>,
ffi::d2i_PUBKEY
}
}
#[cfg(test)]
@ -277,7 +383,7 @@ mod tests {
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")
let pem = pkey.private_key_to_pem_pkcs8_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());
@ -330,7 +436,7 @@ mod tests {
let key = include_bytes!("../test/key.pem");
let key = PKey::private_key_from_pem(key).unwrap();
let priv_key = key.private_key_to_pem().unwrap();
let priv_key = key.private_key_to_pem_pkcs8().unwrap();
let pub_key = key.public_key_to_pem().unwrap();
// As a super-simple verification, just check that the buffers contain
@ -358,7 +464,7 @@ mod tests {
#[test]
fn test_dh_accessor() {
let dh = include_bytes!("../test/dhparams.pem");
let dh = Dh::from_pem(dh).unwrap();
let dh = Dh::params_from_pem(dh).unwrap();
let pkey = PKey::from_dh(dh).unwrap();
pkey.dh().unwrap();
assert!(pkey.rsa().is_err());

View File

@ -40,9 +40,35 @@ impl<T> RsaRef<T>
where
T: HasPrivate,
{
// FIXME these need to specify output format
private_key_to_pem!(ffi::PEM_write_bio_RSAPrivateKey);
private_key_to_der!(ffi::i2d_RSAPrivateKey);
private_key_to_pem! {
/// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
///
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_RSAPrivateKey`].
///
/// [`PEM_write_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_RSAPrivateKey.html
private_key_to_pem,
/// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
///
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
///
/// This corresponds to [`PEM_write_bio_RSAPrivateKey`].
///
/// [`PEM_write_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_RSAPrivateKey.html
private_key_to_pem_passphrase,
ffi::PEM_write_bio_RSAPrivateKey
}
to_der! {
/// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
///
/// This corresponds to [`i2d_RSAPrivateKey`].
///
/// [`i2d_RSAPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_RSAPrivateKey.html
private_key_to_der,
ffi::i2d_RSAPrivateKey
}
/// Decrypts data using the private key, returning the number of decrypted bytes.
///
@ -165,14 +191,49 @@ impl<T> RsaRef<T>
where
T: HasPublic,
{
public_key_to_pem!(ffi::PEM_write_bio_RSA_PUBKEY);
public_key_to_der!(ffi::i2d_RSA_PUBKEY);
to_pem! {
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
///
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_write_bio_RSA_PUBKEY`].
///
/// [`PEM_write_bio_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/pem.html
public_key_to_pem,
ffi::PEM_write_bio_RSA_PUBKEY
}
to_der_inner!(
/// Serializes the public key to DER-encoded PKCS#1.
to_der! {
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
///
/// This corresponds to [`i2d_RSA_PUBKEY`].
///
/// [`i2d_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_RSA_PUBKEY.html
public_key_to_der,
ffi::i2d_RSA_PUBKEY
}
to_pem! {
/// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
///
/// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_write_bio_RSAPublicKey`].
///
/// [`PEM_write_bio_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/pem.html
public_key_to_pem_pkcs1,
ffi::PEM_write_bio_RSAPublicKey
}
to_der! {
/// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
///
/// This corresponds to [`i2d_RSAPublicKey`].
///
/// [`i2d_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_RSAPublicKey.html
public_key_to_der_pkcs1,
ffi::i2d_RSAPublicKey
);
}
pub fn size(&self) -> u32 {
unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
@ -260,15 +321,40 @@ impl Rsa<Public> {
}
}
public_key_from_pem!(Rsa<Public>, ffi::PEM_read_bio_RSA_PUBKEY);
public_key_from_der!(Rsa<Public>, ffi::d2i_RSA_PUBKEY);
from_pem! {
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
///
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
///
/// This corresponds to [`PEM_read_bio_RSA_PUBKEY`].
///
/// [`PEM_read_bio_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_RSA_PUBKEY.html
public_key_from_pem,
Rsa<Public>,
ffi::PEM_read_bio_RSA_PUBKEY
}
from_der_inner!(
/// Deserializes a public key from DER-encoded PKCS#1 data.
from_der! {
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
///
/// This corresponds to [`d2i_RSA_PUBKEY`].
///
/// [`d2i_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
public_key_from_der,
Rsa<Public>,
ffi::d2i_RSA_PUBKEY
}
from_der! {
/// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
///
/// This corresponds to [`d2i_RSAPublicKey`].
///
/// [`d2i_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
public_key_from_der_pkcs1,
Rsa<Public>,
ffi::d2i_RSAPublicKey
);
}
}
impl Rsa<Private> {
@ -318,8 +404,43 @@ impl Rsa<Private> {
}
// FIXME these need to identify input formats
private_key_from_pem!(Rsa<Private>, ffi::PEM_read_bio_RSAPrivateKey);
private_key_from_der!(Rsa<Private>, ffi::d2i_RSAPrivateKey);
private_key_from_pem! {
/// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
///
/// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
///
/// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
private_key_from_pem,
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
///
/// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
///
/// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
private_key_from_pem_passphrase,
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
///
/// The callback should fill the password into the provided buffer and return its length.
///
/// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
///
/// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
private_key_from_pem_callback,
Rsa<Private>,
ffi::PEM_read_bio_RSAPrivateKey
}
from_der! {
/// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
///
/// This corresponds to [`d2i_RSAPrivateKey`].
///
/// [`d2i_RSAPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
private_key_from_der,
Rsa<Private>,
ffi::d2i_RSAPrivateKey
}
}
impl<T> fmt::Debug for Rsa<T> {

View File

@ -390,7 +390,6 @@ mod test {
use ec::{EcGroup, EcKey};
use nid::Nid;
use rsa::{Padding, Rsa};
use dsa::Dsa;
use pkey::PKey;
const INPUT: &'static str =
@ -442,59 +441,7 @@ mod test {
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
verifier.update(b"foobar").unwrap();
assert!(!verifier
.verify(&Vec::from_hex(SIGNATURE).unwrap())
.unwrap());
}
#[test]
pub fn dsa_sign_verify() {
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
let private_key = {
let key = include_bytes!("../test/dsa.pem");
PKey::from_dsa(Dsa::private_key_from_pem(key).unwrap()).unwrap()
};
let public_key = {
let key = include_bytes!("../test/dsa.pem.pub");
PKey::from_dsa(Dsa::public_key_from_pem(key).unwrap()).unwrap()
};
let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap();
signer.update(&input).unwrap();
let sig = signer.sign_to_vec().unwrap();
let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap();
verifier.update(&input).unwrap();
assert!(verifier.verify(&sig).unwrap());
}
#[test]
pub fn dsa_sign_verify_fail() {
let input: Vec<u8> = (0..25).cycle().take(1024).collect();
let private_key = {
let key = include_bytes!("../test/dsa.pem");
PKey::from_dsa(Dsa::private_key_from_pem(key).unwrap()).unwrap()
};
let public_key = {
let key = include_bytes!("../test/dsa.pem.pub");
PKey::from_dsa(Dsa::public_key_from_pem(key).unwrap()).unwrap()
};
let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap();
signer.update(&input).unwrap();
let mut sig = signer.sign_to_vec().unwrap();
sig[0] -= 1;
let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap();
verifier.update(&input).unwrap();
match verifier.verify(&sig) {
Ok(true) => panic!("unexpected success"),
Ok(false) | Err(_) => {}
}
assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap());
}
fn test_hmac(ty: MessageDigest, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {

View File

@ -196,7 +196,7 @@ impl SslAcceptor {
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
pub fn mozilla_intermediate(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
let mut ctx = ctx(method)?;
let dh = Dh::from_pem(DHPARAM_PEM.as_bytes())?;
let dh = Dh::params_from_pem(DHPARAM_PEM.as_bytes())?;
ctx.set_tmp_dh(&dh)?;
setup_curves(&mut ctx)?;
ctx.set_cipher_list(

View File

@ -1027,7 +1027,7 @@ fn tmp_dh_callback() {
ctx.set_tmp_dh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst);
let dh = include_bytes!("../../test/dhparams.pem");
Dh::from_pem(dh)
Dh::params_from_pem(dh)
});
let ssl = Ssl::new(&ctx.build()).unwrap();
ssl.accept(stream).unwrap();
@ -1096,7 +1096,7 @@ fn tmp_dh_callback_ssl() {
ssl.set_tmp_dh_callback(|_, _, _| {
CALLED_BACK.store(true, Ordering::SeqCst);
let dh = include_bytes!("../../test/dhparams.pem");
Dh::from_pem(dh)
Dh::params_from_pem(dh)
});
ssl.accept(stream).unwrap();
});

View File

@ -482,8 +482,27 @@ impl X509Ref {
}
}
to_pem!(ffi::PEM_write_bio_X509);
to_der!(ffi::i2d_X509);
to_pem! {
/// Serializes the certificate into a PEM-encoded X509 structure.
///
/// The output will have a header of `-----BEGIN CERTIFICATE-----`.
///
/// This corresponds to [`PEM_write_bio_X509`].
///
/// [`PEM_write_bio_X509`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509.html
to_pem,
ffi::PEM_write_bio_X509
}
to_der! {
/// Serializes the certificate into a DER-encoded X509 structure.
///
/// This corresponds to [`i2d_X509`].
///
/// [`i2d_X509`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509.html
to_der,
ffi::i2d_X509
}
}
impl ToOwned for X509Ref {
@ -503,8 +522,29 @@ impl X509 {
X509Builder::new()
}
from_pem!(X509, ffi::PEM_read_bio_X509);
from_der!(X509, ffi::d2i_X509);
from_pem! {
/// Deserializes a PEM-encoded X509 structure.
///
/// The input should have a header of `-----BEGIN CERTIFICATE-----`.
///
/// This corresponds to [`PEM_read_bio_X509`].
///
/// [`PEM_read_bio_X509`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509.html
from_pem,
X509,
ffi::PEM_read_bio_X509
}
from_der! {
/// Deserializes a DER-encoded X509 structure.
///
/// This corresponds to [`d2i_X509`].
///
/// [`d2i_X509`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509.html
from_der,
X509,
ffi::d2i_X509
}
/// Deserializes a list of PEM-formatted certificates.
pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
@ -906,26 +946,53 @@ impl X509Req {
X509ReqBuilder::new()
}
/// Reads Certifcate Signing Request (CSR) from PEM.
pub fn from_pem(buf: &[u8]) -> Result<X509Req, ErrorStack> {
let mem_bio = MemBioSlice::new(buf)?;
unsafe {
let handle = cvt_p(ffi::PEM_read_bio_X509_REQ(
mem_bio.as_ptr(),
ptr::null_mut(),
None,
ptr::null_mut(),
))?;
Ok(X509Req::from_ptr(handle))
}
from_pem! {
/// Deserializes a PEM-encoded PKCS#10 certificate request structure.
///
/// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
///
/// This corresponds to [`PEM_read_bio_X509_REQ`].
///
/// [`PEM_read_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509_REQ.html
from_pem,
X509Req,
ffi::PEM_read_bio_X509_REQ
}
from_der!(X509Req, ffi::d2i_X509_REQ);
from_der! {
/// Deserializes a DER-encoded PKCS#10 certificate request structure.
///
/// This corresponds to [`d2i_X509_REQ`].
///
/// [`d2i_X509_REQ`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_X509_REQ.html
from_der,
X509Req,
ffi::d2i_X509_REQ
}
}
impl X509ReqRef {
to_pem!(ffi::PEM_write_bio_X509_REQ);
to_der!(ffi::i2d_X509_REQ);
to_pem! {
/// Serializes the certificate request to a PEM-encoded PKCS#10 structure.
///
/// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`.
///
/// This corresponds to [`PEM_write_bio_X509_REQ`].
///
/// [`PEM_write_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509_REQ.html
to_pem,
ffi::PEM_write_bio_X509_REQ
}
to_der! {
/// Serializes the certificate request to a DER-encoded PKCS#10 structure.
///
/// This corresponds to [`i2d_X509_REQ`].
///
/// [`i2d_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_X509_REQ.html
to_der,
ffi::i2d_X509_REQ
}
/// Returns the numerical value of the version field of the certificate request.
///

View File

@ -1,15 +0,0 @@
-----BEGIN DSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,5B99FC62C376CA1F
5nN039tLa3AHnSaQ0lk+Zsguu1EE+EyUlW1GHKs7ls2gOsZH1kR0+A+MiwNKlP24
Syy8KYyAbgsirhtwN5IOSsA97feR/vHTY4xQ8nEef8tB7VeRJzOFLHGgS0hwIxOM
Tb8gb4y0FtoWdAgorieP4c1emu8VwTTkHd44AArDXsP1Y7s+a3IEMcHcc3tW+qBk
xuVnqBEETL1t0I5rKy+AYvPmGgEZ0dGRRnUlVMC5jMTozJFcStdSzKUY27prUBz2
FREOJOA/dIjVn1UGijI64Io5sPCAbDPPmG2k4kywbEbd7Ee/MxEvRNcAyv4boyA8
GnHZTILKi/WY5+SNlHE3YepCFo1XU+59SovB1lDhRmi43L4vfdGc/6y8L/+rbLuU
Y58DxLdOZLTjpf9GLLf9WcpHhNZhwFfBFA8HuT8FtKDPqlf2t65z+1AVV8JTH2wM
BrRHXTrBKn8YgafXD5MisKFmajoAtNZTvhYGm0D8BLIiNwOwLsGfXZ0hYAie0eoI
Xl6MbHp1n/e+R+XKJ3M9DPM8mzWntlltAhS5+Az0Zi4aBdzqQaTpqvEku21sygq8
Hwm0fpAq7y4bMnjNbMqQVw==
-----END DSA PRIVATE KEY-----