Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkcs8: provide PrivateKeyInfoRef/PrivateKeyInfoOwned #1483

Merged
merged 14 commits into from
Sep 4, 2024
73 changes: 49 additions & 24 deletions pkcs8/src/encrypted_private_key_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use der::{
use pkcs5::EncryptionScheme;

#[cfg(feature = "alloc")]
use der::SecretDocument;
use {alloc::boxed::Box, der::SecretDocument};

#[cfg(feature = "encryption")]
use {pkcs5::pbes2, rand_core::CryptoRngCore};
Expand Down Expand Up @@ -37,23 +37,26 @@ use der::pem::PemLabel;
///
/// [RFC 5208 Section 6]: https://tools.ietf.org/html/rfc5208#section-6
#[derive(Clone, Eq, PartialEq)]
pub struct EncryptedPrivateKeyInfo<'a> {
pub struct EncryptedPrivateKeyInfo<Data> {
/// Algorithm identifier describing a password-based symmetric encryption
/// scheme used to encrypt the `encrypted_data` field.
pub encryption_algorithm: EncryptionScheme,

/// Private key data
pub encrypted_data: &'a [u8],
pub encrypted_data: Data,
}

impl<'a> EncryptedPrivateKeyInfo<'a> {
impl<'a, Data> EncryptedPrivateKeyInfo<Data>
where
Data: AsRef<[u8]> + From<&'a [u8]>,
{
/// Attempt to decrypt this encrypted private key using the provided
/// password to derive an encryption key.
#[cfg(feature = "encryption")]
pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
Ok(self
.encryption_algorithm
.decrypt(password, self.encrypted_data)?
.decrypt(password, self.encrypted_data.as_ref())?
.try_into()?)
}

Expand All @@ -66,7 +69,7 @@ impl<'a> EncryptedPrivateKeyInfo<'a> {
doc: &[u8],
) -> Result<SecretDocument> {
let pbes2_params = pbes2::Parameters::recommended(rng);
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, doc)
EncryptedPrivateKeyInfoOwned::encrypt_with(pbes2_params, password, doc)
}

/// Encrypt this private key using a symmetric encryption key derived
Expand All @@ -81,52 +84,61 @@ impl<'a> EncryptedPrivateKeyInfo<'a> {

EncryptedPrivateKeyInfo {
encryption_algorithm: pbes2_params.into(),
encrypted_data: &encrypted_data,
encrypted_data,
}
.try_into()
}
}

impl<'a> DecodeValue<'a> for EncryptedPrivateKeyInfo<'a> {
impl<'a, Data> DecodeValue<'a> for EncryptedPrivateKeyInfo<Data>
where
Data: From<&'a [u8]>,
{
type Error = der::Error;

fn decode_value<R: Reader<'a>>(
reader: &mut R,
header: Header,
) -> der::Result<EncryptedPrivateKeyInfo<'a>> {
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
reader.read_nested(header.length, |reader| {
Ok(Self {
encryption_algorithm: reader.decode()?,
encrypted_data: OctetStringRef::decode(reader)?.as_bytes(),
encrypted_data: OctetStringRef::decode(reader)?.as_bytes().into(),
})
})
}
}

impl EncodeValue for EncryptedPrivateKeyInfo<'_> {
impl<Data> EncodeValue for EncryptedPrivateKeyInfo<Data>
where
Data: AsRef<[u8]>,
{
fn value_len(&self) -> der::Result<Length> {
self.encryption_algorithm.encoded_len()?
+ OctetStringRef::new(self.encrypted_data)?.encoded_len()?
+ OctetStringRef::new(self.encrypted_data.as_ref())?.encoded_len()?
}

fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
self.encryption_algorithm.encode(writer)?;
OctetStringRef::new(self.encrypted_data)?.encode(writer)?;
OctetStringRef::new(self.encrypted_data.as_ref())?.encode(writer)?;
Ok(())
}
}

impl<'a> Sequence<'a> for EncryptedPrivateKeyInfo<'a> {}
impl<'a, Data> Sequence<'a> for EncryptedPrivateKeyInfo<Data> where
Data: AsRef<[u8]> + From<&'a [u8]>
{
}

impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> {
impl<'a, Data> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<Data>
where
Data: AsRef<[u8]> + From<&'a [u8]> + 'a,
{
type Error = Error;

fn try_from(bytes: &'a [u8]) -> Result<Self> {
Ok(Self::from_der(bytes)?)
}
}

impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> {
impl<Data> fmt::Debug for EncryptedPrivateKeyInfo<Data> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EncryptedPrivateKeyInfo")
.field("encryption_algorithm", &self.encryption_algorithm)
Expand All @@ -135,24 +147,37 @@ impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> {
}

#[cfg(feature = "alloc")]
impl TryFrom<EncryptedPrivateKeyInfo<'_>> for SecretDocument {
impl<'a, Data> TryFrom<EncryptedPrivateKeyInfo<Data>> for SecretDocument
where
Data: AsRef<[u8]> + From<&'a [u8]>,
{
type Error = Error;

fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
SecretDocument::try_from(&encrypted_private_key)
}
}

#[cfg(feature = "alloc")]
impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument {
impl<'a, Data> TryFrom<&EncryptedPrivateKeyInfo<Data>> for SecretDocument
where
Data: AsRef<[u8]> + From<&'a [u8]>,
{
type Error = Error;

fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
Ok(Self::encode_msg(encrypted_private_key)?)
}
}

#[cfg(feature = "pem")]
impl PemLabel for EncryptedPrivateKeyInfo<'_> {
impl<Data> PemLabel for EncryptedPrivateKeyInfo<Data> {
const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
}

/// [`EncryptedPrivateKeyInfo`] with `&[u8]` encrypted data.
pub type EncryptedPrivateKeyInfoRef<'a> = EncryptedPrivateKeyInfo<&'a [u8]>;

#[cfg(feature = "alloc")]
/// [`EncryptedPrivateKeyInfo`] with `Box<[u8]>` encrypted data.
pub type EncryptedPrivateKeyInfoOwned = EncryptedPrivateKeyInfo<Box<[u8]>>;
13 changes: 9 additions & 4 deletions pkcs8/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
//! [PKCS#5v2 Password Based Encryption Scheme 2 (RFC 8018)]: https://tools.ietf.org/html/rfc8018#section-6.2
//! [scrypt]: https://en.wikipedia.org/wiki/Scrypt

#[cfg(feature = "pem")]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
Expand All @@ -85,7 +85,7 @@ pub(crate) mod encrypted_private_key_info;

pub use crate::{
error::{Error, Result},
private_key_info::PrivateKeyInfo,
private_key_info::{PrivateKeyInfo, PrivateKeyInfoInner},
traits::DecodePrivateKey,
version::Version,
};
Expand All @@ -96,16 +96,21 @@ pub use spki::{

#[cfg(feature = "alloc")]
pub use {
crate::traits::EncodePrivateKey,
crate::{private_key_info::PrivateKeyInfoOwned, traits::EncodePrivateKey},
der::{Document, SecretDocument},
spki::EncodePublicKey,
};

#[cfg(feature = "pem")]
pub use der::pem::LineEnding;

#[cfg(all(feature = "alloc", feature = "pkcs5"))]
pub use encrypted_private_key_info::EncryptedPrivateKeyInfoOwned;
#[cfg(feature = "pkcs5")]
pub use {encrypted_private_key_info::EncryptedPrivateKeyInfo, pkcs5};
pub use {
encrypted_private_key_info::{EncryptedPrivateKeyInfo, EncryptedPrivateKeyInfoRef},
pkcs5,
};

#[cfg(feature = "rand_core")]
pub use rand_core;
Loading
Loading