pkcs8/
encrypted_private_key_info.rs1use crate::{Error, Result};
4use core::fmt;
5use der::{
6 Decode, DecodeValue, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, Writer,
7 asn1::OctetStringRef,
8};
9use pkcs5::EncryptionScheme;
10
11#[cfg(feature = "alloc")]
12use der::{SecretDocument, asn1::OctetString};
13
14#[cfg(feature = "encryption")]
15use {pkcs5::pbes2, rand_core::TryCryptoRng};
16
17#[cfg(feature = "pem")]
18use der::pem::PemLabel;
19
20#[derive(Clone, Eq, PartialEq)]
40pub struct EncryptedPrivateKeyInfo<Data> {
41 pub encryption_algorithm: EncryptionScheme,
44
45 pub encrypted_data: Data,
47}
48
49impl<'a, Data> EncryptedPrivateKeyInfo<Data>
50where
51 Data: DecodeValue<'a, Error = der::Error> + EncodeValue + FixedTag + 'a,
52 Data: AsRef<[u8]>,
53{
54 #[cfg(feature = "encryption")]
61 pub fn decrypt(&self, password: impl AsRef<[u8]>) -> Result<SecretDocument> {
62 Ok(self
63 .encryption_algorithm
64 .decrypt(password, self.encrypted_data.as_ref())?
65 .try_into()?)
66 }
67
68 #[cfg(feature = "getrandom")]
71 pub(crate) fn encrypt(password: impl AsRef<[u8]>, doc: &[u8]) -> Result<SecretDocument> {
72 Self::encrypt_with_rng(&mut getrandom::SysRng, password, doc)
73 }
74
75 #[cfg(feature = "encryption")]
78 pub(crate) fn encrypt_with_rng<R: TryCryptoRng>(
79 rng: &mut R,
80 password: impl AsRef<[u8]>,
81 doc: &[u8],
82 ) -> Result<SecretDocument> {
83 let pbes2_params = pbes2::Parameters::generate_recommended(rng)?;
84 EncryptedPrivateKeyInfoOwned::encrypt_with_params(pbes2_params, password, doc)
85 }
86
87 #[cfg(feature = "encryption")]
90 pub(crate) fn encrypt_with_params(
91 pbes2_params: pbes2::Parameters,
92 password: impl AsRef<[u8]>,
93 doc: &[u8],
94 ) -> Result<SecretDocument> {
95 let encrypted_data = pbes2_params.encrypt(password, doc)?;
96 let encrypted_data = OctetStringRef::new(&encrypted_data)?;
97
98 EncryptedPrivateKeyInfo {
99 encryption_algorithm: pbes2_params.into(),
100 encrypted_data,
101 }
102 .try_into()
103 }
104}
105
106impl<'a, Data> DecodeValue<'a> for EncryptedPrivateKeyInfo<Data>
107where
108 Data: DecodeValue<'a, Error = der::Error> + FixedTag + 'a,
109{
110 type Error = der::Error;
111
112 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: Header) -> der::Result<Self> {
113 Ok(Self {
114 encryption_algorithm: reader.decode()?,
115 encrypted_data: reader.decode()?,
116 })
117 }
118}
119
120impl<Data> EncodeValue for EncryptedPrivateKeyInfo<Data>
121where
122 Data: EncodeValue + FixedTag,
123{
124 fn value_len(&self) -> der::Result<Length> {
125 self.encryption_algorithm.encoded_len()? + self.encrypted_data.encoded_len()?
126 }
127
128 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
129 self.encryption_algorithm.encode(writer)?;
130 self.encrypted_data.encode(writer)?;
131 Ok(())
132 }
133}
134
135impl<'a, Data> Sequence<'a> for EncryptedPrivateKeyInfo<Data> where
136 Data: DecodeValue<'a, Error = der::Error> + EncodeValue + FixedTag + 'a
137{
138}
139
140impl<'a, Data> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<Data>
141where
142 Data: DecodeValue<'a, Error = der::Error> + EncodeValue + FixedTag + 'a,
143{
144 type Error = Error;
145
146 fn try_from(bytes: &'a [u8]) -> Result<Self> {
147 Ok(Self::from_der(bytes)?)
148 }
149}
150
151impl<Data> fmt::Debug for EncryptedPrivateKeyInfo<Data> {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 f.debug_struct("EncryptedPrivateKeyInfo")
154 .field("encryption_algorithm", &self.encryption_algorithm)
155 .finish_non_exhaustive()
156 }
157}
158
159#[cfg(feature = "alloc")]
160impl<'a, Data> TryFrom<EncryptedPrivateKeyInfo<Data>> for SecretDocument
161where
162 Data: DecodeValue<'a, Error = der::Error> + EncodeValue + FixedTag + 'a,
163{
164 type Error = Error;
165
166 fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
167 SecretDocument::try_from(&encrypted_private_key)
168 }
169}
170
171#[cfg(feature = "alloc")]
172impl<'a, Data> TryFrom<&EncryptedPrivateKeyInfo<Data>> for SecretDocument
173where
174 Data: DecodeValue<'a, Error = der::Error> + EncodeValue + FixedTag + 'a,
175{
176 type Error = Error;
177
178 fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<Data>) -> Result<SecretDocument> {
179 Ok(Self::encode_msg(encrypted_private_key)?)
180 }
181}
182
183#[cfg(feature = "pem")]
184impl<Data> PemLabel for EncryptedPrivateKeyInfo<Data> {
185 const PEM_LABEL: &'static str = "ENCRYPTED PRIVATE KEY";
186}
187
188pub type EncryptedPrivateKeyInfoRef<'a> = EncryptedPrivateKeyInfo<&'a OctetStringRef>;
190
191#[cfg(feature = "alloc")]
192pub type EncryptedPrivateKeyInfoOwned = EncryptedPrivateKeyInfo<OctetString>;