Skip to content

Commit d3e42e5

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

5 files changed

+77
-42
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 {
@@ -40,23 +40,26 @@ use der::pem::PemLabel;
4040
///
4141
/// [RFC 5208 Section 6]: https://tools.ietf.org/html/rfc5208#section-6
4242
#[derive(Clone, Eq, PartialEq)]
43-
pub struct EncryptedPrivateKeyInfo<'a> {
43+
pub struct EncryptedPrivateKeyInfo<Data> {
4444
/// Algorithm identifier describing a password-based symmetric encryption
4545
/// scheme used to encrypt the `encrypted_data` field.
4646
pub encryption_algorithm: EncryptionScheme,
4747

4848
/// Private key data
49-
pub encrypted_data: &'a [u8],
49+
pub encrypted_data: Data,
5050
}
5151

52-
impl<'a> EncryptedPrivateKeyInfo<'a> {
52+
impl<'a, Data> EncryptedPrivateKeyInfo<Data>
53+
where
54+
Data: AsRef<[u8]> + From<&'a [u8]>,
55+
{
5356
/// Attempt to decrypt this encrypted private key using the provided
5457
/// password to derive an encryption key.
5558
#[cfg(feature = "encryption")]
5659
pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
5760
Ok(self
5861
.encryption_algorithm
59-
.decrypt(password, self.encrypted_data)?
62+
.decrypt(password, self.encrypted_data.as_ref())?
6063
.try_into()?)
6164
}
6265

@@ -75,7 +78,7 @@ impl<'a> EncryptedPrivateKeyInfo<'a> {
7578
rng.fill_bytes(&mut iv);
7679

7780
let pbes2_params = pbes2::Parameters::scrypt_aes256cbc(Default::default(), &salt, iv)?;
78-
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, doc)
81+
Self::encrypt_with(pbes2_params, password, doc)
7982
}
8083

8184
/// Encrypt this private key using a symmetric encryption key derived
@@ -90,50 +93,59 @@ impl<'a> EncryptedPrivateKeyInfo<'a> {
9093

9194
EncryptedPrivateKeyInfo {
9295
encryption_algorithm: pbes2_params.into(),
93-
encrypted_data: &encrypted_data,
96+
encrypted_data,
9497
}
9598
.try_into()
9699
}
97100
}
98101

99-
impl<'a> DecodeValue<'a> for EncryptedPrivateKeyInfo<'a> {
100-
fn decode_value<R: Reader<'a>>(
101-
reader: &mut R,
102-
header: Header,
103-
) -> der::Result<EncryptedPrivateKeyInfo<'a>> {
102+
impl<'a, Data> DecodeValue<'a> for EncryptedPrivateKeyInfo<Data>
103+
where
104+
Data: From<&'a [u8]>,
105+
{
106+
fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> der::Result<Self> {
104107
reader.read_nested(header.length, |reader| {
105108
Ok(Self {
106109
encryption_algorithm: reader.decode()?,
107-
encrypted_data: OctetStringRef::decode(reader)?.as_bytes(),
110+
encrypted_data: OctetStringRef::decode(reader)?.as_bytes().into(),
108111
})
109112
})
110113
}
111114
}
112115

113-
impl EncodeValue for EncryptedPrivateKeyInfo<'_> {
116+
impl<Data> EncodeValue for EncryptedPrivateKeyInfo<Data>
117+
where
118+
Data: AsRef<[u8]>,
119+
{
114120
fn value_len(&self) -> der::Result<Length> {
115121
self.encryption_algorithm.encoded_len()?
116-
+ OctetStringRef::new(self.encrypted_data)?.encoded_len()?
122+
+ OctetStringRef::new(self.encrypted_data.as_ref())?.encoded_len()?
117123
}
118124

119125
fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
120126
self.encryption_algorithm.encode(writer)?;
121-
OctetStringRef::new(self.encrypted_data)?.encode(writer)?;
127+
OctetStringRef::new(self.encrypted_data.as_ref())?.encode(writer)?;
122128
Ok(())
123129
}
124130
}
125131

126-
impl<'a> Sequence<'a> for EncryptedPrivateKeyInfo<'a> {}
132+
impl<'a, Data> Sequence<'a> for EncryptedPrivateKeyInfo<Data> where
133+
Data: AsRef<[u8]> + From<&'a [u8]>
134+
{
135+
}
127136

128-
impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> {
137+
impl<'a, Data> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<Data>
138+
where
139+
Data: AsRef<[u8]> + From<&'a [u8]>,
140+
{
129141
type Error = Error;
130142

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

136-
impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> {
148+
impl<Data> fmt::Debug for EncryptedPrivateKeyInfo<Data> {
137149
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138150
f.debug_struct("EncryptedPrivateKeyInfo")
139151
.field("encryption_algorithm", &self.encryption_algorithm)
@@ -142,24 +154,37 @@ impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> {
142154
}
143155

144156
#[cfg(feature = "alloc")]
145-
impl TryFrom<EncryptedPrivateKeyInfo<'_>> for SecretDocument {
157+
impl<'a, Data> TryFrom<EncryptedPrivateKeyInfo<Data>> for SecretDocument
158+
where
159+
Data: AsRef<[u8]> + From<&'a [u8]>,
160+
{
146161
type Error = Error;
147162

148-
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
163+
fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
149164
SecretDocument::try_from(&encrypted_private_key)
150165
}
151166
}
152167

153168
#[cfg(feature = "alloc")]
154-
impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument {
169+
impl<'a, Data> TryFrom<&EncryptedPrivateKeyInfo<Data>> for SecretDocument
170+
where
171+
Data: AsRef<[u8]> + From<&'a [u8]>,
172+
{
155173
type Error = Error;
156174

157-
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<'_>) -> Result<SecretDocument> {
175+
fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
158176
Ok(Self::encode_msg(encrypted_private_key)?)
159177
}
160178
}
161179

162180
#[cfg(feature = "pem")]
163-
impl PemLabel for EncryptedPrivateKeyInfo<'_> {
181+
impl<Data> PemLabel for EncryptedPrivateKeyInfo<Data> {
164182
const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
165183
}
184+
185+
/// [`EncryptedPrivateKeyInfo`] with `&[u8]` encrypted data.
186+
pub type EncryptedPrivateKeyInfoRef<'a> = EncryptedPrivateKeyInfo<&'a [u8]>;
187+
188+
#[cfg(feature = "alloc")]
189+
/// [`EncryptedPrivateKeyInfo`] with `Box<[u8]>` encrypted data.
190+
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

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use {
1717

1818
#[cfg(feature = "encryption")]
1919
use {
20-
crate::EncryptedPrivateKeyInfo,
20+
crate::EncryptedPrivateKeyInfoRef,
2121
der::zeroize::Zeroizing,
2222
pkcs5::pbes2,
2323
rand_core::{CryptoRng, RngCore},
@@ -150,7 +150,7 @@ where
150150
password: impl AsRef<[u8]>,
151151
) -> Result<SecretDocument> {
152152
let der = Zeroizing::new(self.to_der()?);
153-
EncryptedPrivateKeyInfo::encrypt(rng, password, der.as_ref())
153+
EncryptedPrivateKeyInfoRef::encrypt(rng, password, der.as_ref())
154154
}
155155

156156
/// Encrypt this private key using a symmetric encryption key derived
@@ -162,7 +162,7 @@ where
162162
password: impl AsRef<[u8]>,
163163
) -> Result<SecretDocument> {
164164
let der = Zeroizing::new(self.to_der()?);
165-
EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, der.as_ref())
165+
EncryptedPrivateKeyInfoRef::encrypt_with(pbes2_params, password, der.as_ref())
166166
}
167167
}
168168

pkcs8/src/traits.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use der::SecretDocument;
77

88
#[cfg(feature = "encryption")]
99
use {
10-
crate::EncryptedPrivateKeyInfo,
10+
crate::EncryptedPrivateKeyInfoRef,
1111
rand_core::{CryptoRng, RngCore},
1212
};
1313

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

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

@@ -109,7 +109,7 @@ pub trait EncodePrivateKey {
109109
rng: impl CryptoRng + RngCore,
110110
password: impl AsRef<[u8]>,
111111
) -> Result<SecretDocument> {
112-
EncryptedPrivateKeyInfo::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes())
112+
EncryptedPrivateKeyInfoRef::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes())
113113
}
114114

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

135135
/// 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;
@@ -79,7 +79,7 @@ const PASSWORD: &[u8] = b"hunter42"; // Bad password; don't actually use outside
7979

8080
#[test]
8181
fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() {
82-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap();
82+
let pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap();
8383

8484
assert_eq!(
8585
pk.encryption_algorithm.oid(),
@@ -111,7 +111,8 @@ fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() {
111111

112112
#[test]
113113
fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
114-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
114+
let pk =
115+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
115116

116117
assert_eq!(
117118
pk.encryption_algorithm.oid(),
@@ -145,15 +146,15 @@ fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
145146
#[test]
146147
fn decrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() {
147148
let enc_pk =
148-
EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
149+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
149150
let pk = enc_pk.decrypt(PASSWORD).unwrap();
150151
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
151152
}
152153

153154
#[cfg(feature = "encryption")]
154155
#[test]
155156
fn decrypt_ed25519_der_encpriv_aes256_scrypt() {
156-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap();
157+
let enc_pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap();
157158
let pk = enc_pk.decrypt(PASSWORD).unwrap();
158159
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
159160
}
@@ -200,7 +201,8 @@ fn encrypt_ed25519_der_encpriv_aes256_scrypt() {
200201
#[test]
201202
#[cfg(feature = "alloc")]
202203
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
203-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
204+
let pk =
205+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
204206
assert_eq!(
205207
ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE,
206208
&pk.to_der().unwrap()
@@ -210,7 +212,8 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() {
210212
#[test]
211213
#[cfg(feature = "pem")]
212214
fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() {
213-
let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
215+
let pk =
216+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap();
214217
assert_eq!(
215218
ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE,
216219
pk.to_pem(Default::default()).unwrap()
@@ -220,15 +223,17 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() {
220223
#[test]
221224
#[cfg(feature = "3des")]
222225
fn decrypt_ed25519_der_encpriv_des3_pbkdf2_sha256() {
223-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap();
226+
let enc_pk =
227+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap();
224228
let pk = enc_pk.decrypt(PASSWORD).unwrap();
225229
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
226230
}
227231

228232
#[test]
229233
#[cfg(feature = "des-insecure")]
230234
fn decrypt_ed25519_der_encpriv_des_pbkdf2_sha256() {
231-
let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap();
235+
let enc_pk =
236+
EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap();
232237
let pk = enc_pk.decrypt(PASSWORD).unwrap();
233238
assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE);
234239
}

0 commit comments

Comments
 (0)