Skip to content

Commit e25f4da

Browse files
committed
pkcs8: split EncryptedPrivateKeyInfo
Signed-off-by: Arthur Gautier <[email protected]>
1 parent de558e8 commit e25f4da

File tree

5 files changed

+79
-43
lines changed

5 files changed

+79
-43
lines changed

pkcs8/src/encrypted_private_key_info.rs

+49-24
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use der::{
99
use pkcs5::EncryptionScheme;
1010

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

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

4545
/// Private key data
46-
pub encrypted_data: &'a [u8],
46+
pub encrypted_data: Data,
4747
}
4848

49-
impl<'a> EncryptedPrivateKeyInfo<'a> {
49+
impl<'a, Data> EncryptedPrivateKeyInfo<Data>
50+
where
51+
Data: AsRef<[u8]> + From<&'a [u8]>,
52+
{
5053
/// Attempt to decrypt this encrypted private key using the provided
5154
/// password to derive an encryption key.
5255
#[cfg(feature = "encryption")]
5356
pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
5457
Ok(self
5558
.encryption_algorithm
56-
.decrypt(password, self.encrypted_data)?
59+
.decrypt(password, self.encrypted_data.as_ref())?
5760
.try_into()?)
5861
}
5962

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

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

8285
EncryptedPrivateKeyInfo {
8386
encryption_algorithm: pbes2_params.into(),
84-
encrypted_data: &encrypted_data,
87+
encrypted_data,
8588
}
8689
.try_into()
8790
}
8891
}
8992

90-
impl<'a> DecodeValue<'a> for EncryptedPrivateKeyInfo<'a> {
93+
impl<'a, Data> DecodeValue<'a> for EncryptedPrivateKeyInfo<Data>
94+
where
95+
Data: From<&'a [u8]>,
96+
{
9197
type Error = der::Error;
9298

93-
fn decode_value<R: Reader<'a>>(
94-
reader: &mut R,
95-
header: Header,
96-
) -> der::Result<EncryptedPrivateKeyInfo<'a>> {
99+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
97100
reader.read_nested(header.length, |reader| {
98101
Ok(Self {
99102
encryption_algorithm: reader.decode()?,
100-
encrypted_data: OctetStringRef::decode(reader)?.as_bytes(),
103+
encrypted_data: OctetStringRef::decode(reader)?.as_bytes().into(),
101104
})
102105
})
103106
}
104107
}
105108

106-
impl EncodeValue for EncryptedPrivateKeyInfo<'_> {
109+
impl<Data> EncodeValue for EncryptedPrivateKeyInfo<Data>
110+
where
111+
Data: AsRef<[u8]>,
112+
{
107113
fn value_len(&self) -> der::Result<Length> {
108114
self.encryption_algorithm.encoded_len()?
109-
+ OctetStringRef::new(self.encrypted_data)?.encoded_len()?
115+
+ OctetStringRef::new(self.encrypted_data.as_ref())?.encoded_len()?
110116
}
111117

112118
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
113119
self.encryption_algorithm.encode(writer)?;
114-
OctetStringRef::new(self.encrypted_data)?.encode(writer)?;
120+
OctetStringRef::new(self.encrypted_data.as_ref())?.encode(writer)?;
115121
Ok(())
116122
}
117123
}
118124

119-
impl<'a> Sequence<'a> for EncryptedPrivateKeyInfo<'a> {}
125+
impl<'a, Data> Sequence<'a> for EncryptedPrivateKeyInfo<Data> where
126+
Data: AsRef<[u8]> + From<&'a [u8]>
127+
{
128+
}
120129

121-
impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> {
130+
impl<'a, Data> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<Data>
131+
where
132+
Data: AsRef<[u8]> + From<&'a [u8]> + 'a,
133+
{
122134
type Error = Error;
123135

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

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

137149
#[cfg(feature = "alloc")]
138-
impl TryFrom<EncryptedPrivateKeyInfo<'_>> for SecretDocument {
150+
impl<'a, Data> TryFrom<EncryptedPrivateKeyInfo<Data>> for SecretDocument
151+
where
152+
Data: AsRef<[u8]> + From<&'a [u8]>,
153+
{
139154
type Error = Error;
140155

141-
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
156+
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
142157
SecretDocument::try_from(&encrypted_private_key)
143158
}
144159
}
145160

146161
#[cfg(feature = "alloc")]
147-
impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument {
162+
impl<'a, Data> TryFrom<&EncryptedPrivateKeyInfo<Data>> for SecretDocument
163+
where
164+
Data: AsRef<[u8]> + From<&'a [u8]>,
165+
{
148166
type Error = Error;
149167

150-
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
168+
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
151169
Ok(Self::encode_msg(encrypted_private_key)?)
152170
}
153171
}
154172

155173
#[cfg(feature = "pem")]
156-
impl PemLabel for EncryptedPrivateKeyInfo<'_> {
174+
impl<Data> PemLabel for EncryptedPrivateKeyInfo<Data> {
157175
const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
158176
}
177+
178+
/// [`EncryptedPrivateKeyInfo`] with `&[u8]` encrypted data.
179+
pub type EncryptedPrivateKeyInfoRef<'a> = EncryptedPrivateKeyInfo<&'a [u8]>;
180+
181+
#[cfg(feature = "alloc")]
182+
/// [`EncryptedPrivateKeyInfo`] with `Box<[u8]>` encrypted data.
183+
pub type EncryptedPrivateKeyInfoOwned = EncryptedPrivateKeyInfo<Box<[u8]>>;

pkcs8/src/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,13 @@ pub use {
104104
#[cfg(feature = "pem")]
105105
pub use der::pem::LineEnding;
106106

107+
#[cfg(all(feature = "alloc", feature = "pkcs5"))]
108+
pub use encrypted_private_key_info::EncryptedPrivateKeyInfoOwned;
107109
#[cfg(feature = "pkcs5")]
108-
pub use {encrypted_private_key_info::EncryptedPrivateKeyInfo, pkcs5};
110+
pub use {
111+
encrypted_private_key_info::{EncryptedPrivateKeyInfo, EncryptedPrivateKeyInfoRef},
112+
pkcs5,
113+
};
109114

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

pkcs8/src/private_key_info.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use {
1717

1818
#[cfg(feature = "encryption")]
1919
use {
20-
crate::EncryptedPrivateKeyInfo, der::zeroize::Zeroizing, pkcs5::pbes2, rand_core::CryptoRngCore,
20+
crate::EncryptedPrivateKeyInfoRef, der::zeroize::Zeroizing, pkcs5::pbes2,
21+
rand_core::CryptoRngCore,
2122
};
2223

2324
#[cfg(feature = "pem")]
@@ -129,7 +130,7 @@ impl<Params, Key> PrivateKeyInfoInner<Params, Key> {
129130
impl<'a, Params, Key> PrivateKeyInfoInner<Params, Key>
130131
where
131132
Params: der::Choice<'a, Error = der::Error> + Encode,
132-
Key: From<&'a [u8]> + AsRef<[u8]>,
133+
Key: From<&'a [u8]> + AsRef<[u8]> + 'a,
133134
{
134135
/// Encrypt this private key using a symmetric encryption key derived
135136
/// from the provided password.
@@ -147,7 +148,7 @@ where
147148
password: impl AsRef<[u8]>,
148149
) -> Result<SecretDocument> {
149150
let der = Zeroizing::new(self.to_der()?);
150-
EncryptedPrivateKeyInfo::encrypt(rng, password, der.as_ref())
151+
EncryptedPrivateKeyInfoRef::encrypt(rng, password, der.as_ref())
151152
}
152153

153154
/// Encrypt this private key using a symmetric encryption key derived
@@ -159,7 +160,7 @@ where
159160
password: impl AsRef<[u8]>,
160161
) -> Result<SecretDocument> {
161162
let der = Zeroizing::new(self.to_der()?);
162-
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, der.as_ref())
163+
EncryptedPrivateKeyInfoRef::encrypt_with(pbes2_params, password, der.as_ref())
163164
}
164165
}
165166

pkcs8/src/traits.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{Error, PrivateKeyInfo, Result};
66
use der::SecretDocument;
77

88
#[cfg(feature = "encryption")]
9-
use {crate::EncryptedPrivateKeyInfo, rand_core::CryptoRngCore};
9+
use {crate::EncryptedPrivateKeyInfoRef, rand_core::CryptoRngCore};
1010

1111
#[cfg(feature = "pem")]
1212
use {
@@ -31,7 +31,7 @@ pub trait DecodePrivateKey: Sized {
3131
/// (binary format) and attempt to decrypt it using the provided password.
3232
#[cfg(feature = "encryption")]
3333
fn from_pkcs8_encrypted_der(bytes: &[u8], password: impl AsRef<[u8]>) -> Result<Self> {
34-
let doc = EncryptedPrivateKeyInfo::try_from(bytes)?.decrypt(password)?;
34+
let doc = EncryptedPrivateKeyInfoRef::try_from(bytes)?.decrypt(password)?;
3535
Self::from_pkcs8_der(doc.as_bytes())
3636
}
3737

@@ -63,7 +63,7 @@ pub trait DecodePrivateKey: Sized {
6363
#[cfg(all(feature = "encryption", feature = "pem"))]
6464
fn from_pkcs8_encrypted_pem(s: &str, password: impl AsRef<[u8]>) -> Result<Self> {
6565
let (label, doc) = SecretDocument::from_pem(s)?;
66-
EncryptedPrivateKeyInfo::validate_pem_label(label)?;
66+
EncryptedPrivateKeyInfoRef::validate_pem_label(label)?;
6767
Self::from_pkcs8_encrypted_der(doc.as_bytes(), password)
6868
}
6969

@@ -106,7 +106,7 @@ pub trait EncodePrivateKey {
106106
rng: &mut impl CryptoRngCore,
107107
password: impl AsRef<[u8]>,
108108
) -> Result<SecretDocument> {
109-
EncryptedPrivateKeyInfo::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes())
109+
EncryptedPrivateKeyInfoRef::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes())
110110
}
111111

112112
/// Serialize this private key as PEM-encoded PKCS#8 with the given [`LineEnding`].
@@ -126,7 +126,7 @@ pub trait EncodePrivateKey {
126126
line_ending: LineEnding,
127127
) -> Result<Zeroizing<String>> {
128128
let doc = self.to_pkcs8_encrypted_der(rng, password)?;
129-
Ok(doc.to_pem(EncryptedPrivateKeyInfo::PEM_LABEL, line_ending)?)
129+
Ok(doc.to_pem(EncryptedPrivateKeyInfoRef::PEM_LABEL, line_ending)?)
130130
}
131131

132132
/// Write ASN.1 DER-encoded PKCS#8 private key to the given path

pkcs8/tests/encrypted_private_key.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![cfg(feature = "pkcs5")]
44

55
use hex_literal::hex;
6-
use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfo, PrivateKeyInfo};
6+
use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfoRef, PrivateKeyInfo};
77

88
#[cfg(feature = "alloc")]
99
use der::Encode;
@@ -101,7 +101,7 @@ const PASSWORD: &[u8] = b"hunter42"; // Bad password; don't actually use outside
101101

102102
#[test]
103103
fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() {
104-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap();
104+
let pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap();
105105

106106
assert_eq!(
107107
pk.encryption_algorithm.oid(),
@@ -133,7 +133,8 @@ fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() {
133133

134134
#[test]
135135
fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
136-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
136+
let pk =
137+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
137138

138139
assert_eq!(
139140
pk.encryption_algorithm.oid(),
@@ -167,15 +168,15 @@ fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
167168
#[test]
168169
fn decrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() {
169170
let enc_pk =
170-
EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
171+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
171172
let pk = enc_pk.decrypt(PASSWORD).unwrap();
172173
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
173174
}
174175

175176
#[cfg(feature = "encryption")]
176177
#[test]
177178
fn decrypt_ed25519_der_encpriv_aes256_scrypt() {
178-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap();
179+
let enc_pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap();
179180
let pk = enc_pk.decrypt(PASSWORD).unwrap();
180181
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
181182
}
@@ -280,7 +281,8 @@ fn encrypt_ed25519_der_encpriv_aes256_scrypt() {
280281
#[test]
281282
#[cfg(feature = "alloc")]
282283
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
283-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
284+
let pk =
285+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
284286
assert_eq!(
285287
ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE,
286288
&pk.to_der().unwrap()
@@ -290,7 +292,8 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
290292
#[test]
291293
#[cfg(feature = "pem")]
292294
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() {
293-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
295+
let pk =
296+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
294297
assert_eq!(
295298
ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE,
296299
pk.to_pem(Default::default()).unwrap()
@@ -300,15 +303,17 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() {
300303
#[test]
301304
#[cfg(feature = "3des")]
302305
fn decrypt_ed25519_der_encpriv_des3_pbkdf2_sha256() {
303-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap();
306+
let enc_pk =
307+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap();
304308
let pk = enc_pk.decrypt(PASSWORD).unwrap();
305309
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
306310
}
307311

308312
#[test]
309313
#[cfg(feature = "des-insecure")]
310314
fn decrypt_ed25519_der_encpriv_des_pbkdf2_sha256() {
311-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap();
315+
let enc_pk =
316+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap();
312317
let pk = enc_pk.decrypt(PASSWORD).unwrap();
313318
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
314319
}

0 commit comments

Comments
 (0)