diff --git a/cms/tests/enveloped_data.rs b/cms/tests/enveloped_data.rs index 8d2886213..7fdf3ca6c 100644 --- a/cms/tests/enveloped_data.rs +++ b/cms/tests/enveloped_data.rs @@ -223,7 +223,7 @@ fn reencode_enveloped_data_pwri_test() { ); let enc_pbkdf2 = kdf_alg.parameters.as_ref().unwrap().to_der().unwrap(); let pbkdf2 = Pbkdf2Params::from_der(enc_pbkdf2.as_slice()).unwrap(); - assert_eq!(hex!("7F EE A8 FD 56 8E 8F 07"), pbkdf2.salt); + assert_eq!(hex!("7F EE A8 FD 56 8E 8F 07"), pbkdf2.salt.as_ref()); assert_eq!(2048, pbkdf2.iteration_count); assert_eq!( ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.16.3.9"), @@ -443,7 +443,7 @@ fn reencode_enveloped_data_multi_test() { ); let enc_pbkdf2 = kdf_alg.parameters.as_ref().unwrap().to_der().unwrap(); let pbkdf2 = Pbkdf2Params::from_der(enc_pbkdf2.as_slice()).unwrap(); - assert_eq!(hex!("39 04 A7 33 A0 6A 1B 27"), pbkdf2.salt); + assert_eq!(hex!("39 04 A7 33 A0 6A 1B 27"), pbkdf2.salt.as_ref()); assert_eq!(2048, pbkdf2.iteration_count); assert_eq!( ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.16.3.9"), diff --git a/cms/tests/tests_from_pkcs7_crate.rs b/cms/tests/tests_from_pkcs7_crate.rs index 8c75adf05..ccfebe31d 100644 --- a/cms/tests/tests_from_pkcs7_crate.rs +++ b/cms/tests/tests_from_pkcs7_crate.rs @@ -40,7 +40,7 @@ fn cms_decode_encrypted_key_example() { .to_der() .unwrap(); let pbkdf2 = Pbkdf2Params::from_der(enc_pbkdf2.as_slice()).unwrap(); - assert_eq!(hex!("ad2d4b4e87b34d67"), pbkdf2.salt); + assert_eq!(hex!("ad2d4b4e87b34d67"), pbkdf2.salt.as_ref()); assert_eq!(2048, pbkdf2.iteration_count); assert_eq!( 552u32, diff --git a/pkcs5/src/lib.rs b/pkcs5/src/lib.rs index 08993c245..f8439ad90 100644 --- a/pkcs5/src/lib.rs +++ b/pkcs5/src/lib.rs @@ -49,7 +49,7 @@ use alloc::vec::Vec; #[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] #[allow(clippy::large_enum_variant)] -pub enum EncryptionScheme<'a> { +pub enum EncryptionScheme { /// Password-Based Encryption Scheme 1 as defined in [RFC 8018 Section 6.1]. /// /// [RFC 8018 Section 6.1]: https://tools.ietf.org/html/rfc8018#section-6.1 @@ -58,10 +58,10 @@ pub enum EncryptionScheme<'a> { /// Password-Based Encryption Scheme 2 as defined in [RFC 8018 Section 6.2]. /// /// [RFC 8018 Section 6.2]: https://tools.ietf.org/html/rfc8018#section-6.2 - Pbes2(pbes2::Parameters<'a>), + Pbes2(pbes2::Parameters), } -impl<'a> EncryptionScheme<'a> { +impl EncryptionScheme { /// Attempt to decrypt the given ciphertext, allocating and returning a /// byte vector containing the plaintext. #[cfg(all(feature = "alloc", feature = "pbes2"))] @@ -79,11 +79,11 @@ impl<'a> EncryptionScheme<'a> { /// is unsupported, or if the ciphertext is malformed (e.g. not a multiple /// of a block mode's padding) #[cfg(feature = "pbes2")] - pub fn decrypt_in_place<'b>( + pub fn decrypt_in_place<'a>( &self, password: impl AsRef<[u8]>, - buffer: &'b mut [u8], - ) -> Result<&'b [u8]> { + buffer: &'a mut [u8], + ) -> Result<&'a [u8]> { match self { Self::Pbes2(params) => params.decrypt_in_place(password, buffer), Self::Pbes1(_) => Err(Error::NoPbes1CryptSupport), @@ -103,12 +103,12 @@ impl<'a> EncryptionScheme<'a> { /// Encrypt the given ciphertext in-place using a key derived from the /// provided password and this scheme's parameters. #[cfg(feature = "pbes2")] - pub fn encrypt_in_place<'b>( + pub fn encrypt_in_place<'a>( &self, password: impl AsRef<[u8]>, - buffer: &'b mut [u8], + buffer: &'a mut [u8], pos: usize, - ) -> Result<&'b [u8]> { + ) -> Result<&'a [u8]> { match self { Self::Pbes2(params) => params.encrypt_in_place(password, buffer, pos), Self::Pbes1(_) => Err(Error::NoPbes1CryptSupport), @@ -132,7 +132,7 @@ impl<'a> EncryptionScheme<'a> { } /// Get [`pbes2::Parameters`] if it is the selected algorithm. - pub fn pbes2(&self) -> Option<&pbes2::Parameters<'a>> { + pub fn pbes2(&self) -> Option<&pbes2::Parameters> { match self { Self::Pbes2(params) => Some(params), _ => None, @@ -140,13 +140,13 @@ impl<'a> EncryptionScheme<'a> { } } -impl<'a> DecodeValue<'a> for EncryptionScheme<'a> { +impl<'a> DecodeValue<'a> for EncryptionScheme { fn decode_value>(decoder: &mut R, header: Header) -> der::Result { AlgorithmIdentifierRef::decode_value(decoder, header)?.try_into() } } -impl EncodeValue for EncryptionScheme<'_> { +impl EncodeValue for EncryptionScheme { fn value_len(&self) -> der::Result { match self { Self::Pbes1(pbes1) => pbes1.oid().encoded_len()? + pbes1.parameters.encoded_len()?, @@ -170,24 +170,24 @@ impl EncodeValue for EncryptionScheme<'_> { } } -impl<'a> Sequence<'a> for EncryptionScheme<'a> {} +impl Sequence<'_> for EncryptionScheme {} -impl<'a> From for EncryptionScheme<'a> { - fn from(alg: pbes1::Algorithm) -> EncryptionScheme<'a> { +impl From for EncryptionScheme { + fn from(alg: pbes1::Algorithm) -> EncryptionScheme { Self::Pbes1(alg) } } -impl<'a> From> for EncryptionScheme<'a> { - fn from(params: pbes2::Parameters<'a>) -> EncryptionScheme<'a> { +impl From for EncryptionScheme { + fn from(params: pbes2::Parameters) -> EncryptionScheme { Self::Pbes2(params) } } -impl<'a> TryFrom> for EncryptionScheme<'a> { +impl TryFrom> for EncryptionScheme { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result> { + fn try_from(alg: AlgorithmIdentifierRef<'_>) -> der::Result { if alg.oid == pbes2::PBES2_OID { match alg.parameters { Some(params) => pbes2::Parameters::try_from(params).map(Into::into), @@ -199,10 +199,10 @@ impl<'a> TryFrom> for EncryptionScheme<'a> { } } -impl<'a> TryFrom<&'a [u8]> for EncryptionScheme<'a> { +impl TryFrom<&[u8]> for EncryptionScheme { type Error = der::Error; - fn try_from(bytes: &'a [u8]) -> der::Result> { + fn try_from(bytes: &[u8]) -> der::Result { AlgorithmIdentifierRef::from_der(bytes)?.try_into() } } diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index 301105cc2..095ae1ddb 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -8,7 +8,7 @@ mod kdf; mod encryption; pub use self::kdf::{ - Kdf, Pbkdf2Params, Pbkdf2Prf, ScryptParams, HMAC_WITH_SHA1_OID, HMAC_WITH_SHA256_OID, + Kdf, Pbkdf2Params, Pbkdf2Prf, Salt, ScryptParams, HMAC_WITH_SHA1_OID, HMAC_WITH_SHA256_OID, PBKDF2_OID, SCRYPT_OID, }; @@ -66,21 +66,21 @@ const DES_BLOCK_SIZE: usize = 8; /// /// [RFC 8018 Appendix A.4]: https://tools.ietf.org/html/rfc8018#appendix-A.4 #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Parameters<'a> { +pub struct Parameters { /// Key derivation function - pub kdf: Kdf<'a>, + pub kdf: Kdf, /// Encryption scheme - pub encryption: EncryptionScheme<'a>, + pub encryption: EncryptionScheme, } -impl<'a> Parameters<'a> { +impl Parameters { /// Initialize PBES2 parameters using PBKDF2-SHA256 as the password-based /// key derivation function and AES-128-CBC as the symmetric cipher. pub fn pbkdf2_sha256_aes128cbc( pbkdf2_iterations: u32, - pbkdf2_salt: &'a [u8], - aes_iv: &'a [u8; AES_BLOCK_SIZE], + pbkdf2_salt: &[u8], + aes_iv: [u8; AES_BLOCK_SIZE], ) -> Result { let kdf = Pbkdf2Params::hmac_with_sha256(pbkdf2_iterations, pbkdf2_salt)?.into(); let encryption = EncryptionScheme::Aes128Cbc { iv: aes_iv }; @@ -91,8 +91,8 @@ impl<'a> Parameters<'a> { /// key derivation function and AES-256-CBC as the symmetric cipher. pub fn pbkdf2_sha256_aes256cbc( pbkdf2_iterations: u32, - pbkdf2_salt: &'a [u8], - aes_iv: &'a [u8; AES_BLOCK_SIZE], + pbkdf2_salt: &[u8], + aes_iv: [u8; AES_BLOCK_SIZE], ) -> Result { let kdf = Pbkdf2Params::hmac_with_sha256(pbkdf2_iterations, pbkdf2_salt)?.into(); let encryption = EncryptionScheme::Aes256Cbc { iv: aes_iv }; @@ -108,8 +108,8 @@ impl<'a> Parameters<'a> { #[cfg(feature = "pbes2")] pub fn scrypt_aes128cbc( params: scrypt::Params, - salt: &'a [u8], - aes_iv: &'a [u8; AES_BLOCK_SIZE], + salt: &[u8], + aes_iv: [u8; AES_BLOCK_SIZE], ) -> Result { let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); let encryption = EncryptionScheme::Aes128Cbc { iv: aes_iv }; @@ -128,8 +128,8 @@ impl<'a> Parameters<'a> { #[cfg(feature = "pbes2")] pub fn scrypt_aes256cbc( params: scrypt::Params, - salt: &'a [u8], - aes_iv: &'a [u8; AES_BLOCK_SIZE], + salt: &[u8], + aes_iv: [u8; AES_BLOCK_SIZE], ) -> Result { let kdf = ScryptParams::from_params_and_salt(params, salt)?.into(); let encryption = EncryptionScheme::Aes256Cbc { iv: aes_iv }; @@ -153,11 +153,11 @@ impl<'a> Parameters<'a> { /// is unsupported, or if the ciphertext is malformed (e.g. not a multiple /// of a block mode's padding) #[cfg(feature = "pbes2")] - pub fn decrypt_in_place<'b>( + pub fn decrypt_in_place<'a>( &self, password: impl AsRef<[u8]>, - buffer: &'b mut [u8], - ) -> Result<&'b [u8]> { + buffer: &'a mut [u8], + ) -> Result<&'a [u8]> { encryption::decrypt_in_place(self, password, buffer) } @@ -182,23 +182,23 @@ impl<'a> Parameters<'a> { /// provided password and this scheme's parameters, writing the ciphertext /// into the same buffer. #[cfg(feature = "pbes2")] - pub fn encrypt_in_place<'b>( + pub fn encrypt_in_place<'a>( &self, password: impl AsRef<[u8]>, - buffer: &'b mut [u8], + buffer: &'a mut [u8], pos: usize, - ) -> Result<&'b [u8]> { + ) -> Result<&'a [u8]> { encryption::encrypt_in_place(self, password, buffer, pos) } } -impl<'a> DecodeValue<'a> for Parameters<'a> { +impl<'a> DecodeValue<'a> for Parameters { fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { AnyRef::decode_value(reader, header)?.try_into() } } -impl EncodeValue for Parameters<'_> { +impl EncodeValue for Parameters { fn value_len(&self) -> der::Result { self.kdf.encoded_len()? + self.encryption.encoded_len()? } @@ -210,12 +210,12 @@ impl EncodeValue for Parameters<'_> { } } -impl<'a> Sequence<'a> for Parameters<'a> {} +impl Sequence<'_> for Parameters {} -impl<'a> TryFrom> for Parameters<'a> { +impl TryFrom> for Parameters { type Error = der::Error; - fn try_from(any: AnyRef<'a>) -> der::Result { + fn try_from(any: AnyRef<'_>) -> der::Result { any.sequence(|params| { let kdf = AlgorithmIdentifierRef::decode(params)?; let encryption = AlgorithmIdentifierRef::decode(params)?; @@ -231,41 +231,41 @@ impl<'a> TryFrom> for Parameters<'a> { /// Symmetric encryption scheme used by PBES2. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] -pub enum EncryptionScheme<'a> { +pub enum EncryptionScheme { /// AES-128 in CBC mode Aes128Cbc { /// Initialization vector - iv: &'a [u8; AES_BLOCK_SIZE], + iv: [u8; AES_BLOCK_SIZE], }, /// AES-192 in CBC mode Aes192Cbc { /// Initialization vector - iv: &'a [u8; AES_BLOCK_SIZE], + iv: [u8; AES_BLOCK_SIZE], }, /// AES-256 in CBC mode Aes256Cbc { /// Initialization vector - iv: &'a [u8; AES_BLOCK_SIZE], + iv: [u8; AES_BLOCK_SIZE], }, /// 3-Key Triple DES in CBC mode #[cfg(feature = "3des")] DesEde3Cbc { /// Initialisation vector - iv: &'a [u8; DES_BLOCK_SIZE], + iv: [u8; DES_BLOCK_SIZE], }, /// DES in CBC mode #[cfg(feature = "des-insecure")] DesCbc { /// Initialisation vector - iv: &'a [u8; DES_BLOCK_SIZE], + iv: [u8; DES_BLOCK_SIZE], }, } -impl<'a> EncryptionScheme<'a> { +impl EncryptionScheme { /// Get the size of a key used by this algorithm in bytes. pub fn key_size(&self) -> usize { match self { @@ -300,19 +300,19 @@ impl<'a> EncryptionScheme<'a> { } } -impl<'a> Decode<'a> for EncryptionScheme<'a> { +impl<'a> Decode<'a> for EncryptionScheme { fn decode>(reader: &mut R) -> der::Result { AlgorithmIdentifierRef::decode(reader).and_then(TryInto::try_into) } } -impl<'a> TryFrom> for EncryptionScheme<'a> { +impl TryFrom> for EncryptionScheme { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'_>) -> der::Result { // TODO(tarcieri): support for non-AES algorithms? let iv = match alg.parameters { - Some(params) => params.decode_as::>()?.as_bytes(), + Some(params) => params.decode_as::>()?.as_bytes(), None => return Err(Tag::OctetString.value_error()), }; @@ -349,18 +349,18 @@ impl<'a> TryFrom> for EncryptionScheme<'a> { } } -impl<'a> TryFrom> for AlgorithmIdentifierRef<'a> { +impl<'a> TryFrom<&'a EncryptionScheme> for AlgorithmIdentifierRef<'a> { type Error = der::Error; - fn try_from(scheme: EncryptionScheme<'a>) -> der::Result { + fn try_from(scheme: &'a EncryptionScheme) -> der::Result { let parameters = OctetStringRef::new(match scheme { - EncryptionScheme::Aes128Cbc { iv } => iv, - EncryptionScheme::Aes192Cbc { iv } => iv, - EncryptionScheme::Aes256Cbc { iv } => iv, + EncryptionScheme::Aes128Cbc { iv } => iv.as_slice(), + EncryptionScheme::Aes192Cbc { iv } => iv.as_slice(), + EncryptionScheme::Aes256Cbc { iv } => iv.as_slice(), #[cfg(feature = "des-insecure")] - EncryptionScheme::DesCbc { iv } => iv, + EncryptionScheme::DesCbc { iv } => iv.as_slice(), #[cfg(feature = "3des")] - EncryptionScheme::DesEde3Cbc { iv } => iv, + EncryptionScheme::DesEde3Cbc { iv } => iv.as_slice(), })?; Ok(AlgorithmIdentifierRef { @@ -370,12 +370,12 @@ impl<'a> TryFrom> for AlgorithmIdentifierRef<'a> { } } -impl<'a> Encode for EncryptionScheme<'a> { +impl Encode for EncryptionScheme { fn encoded_len(&self) -> der::Result { - AlgorithmIdentifierRef::try_from(*self)?.encoded_len() + AlgorithmIdentifierRef::try_from(self)?.encoded_len() } fn encode(&self, writer: &mut impl Writer) -> der::Result<()> { - AlgorithmIdentifierRef::try_from(*self)?.encode(writer) + AlgorithmIdentifierRef::try_from(self)?.encode(writer) } } diff --git a/pkcs5/src/pbes2/encryption.rs b/pkcs5/src/pbes2/encryption.rs index ea029b66a..86349926d 100644 --- a/pkcs5/src/pbes2/encryption.rs +++ b/pkcs5/src/pbes2/encryption.rs @@ -20,7 +20,7 @@ use scrypt::scrypt; const MAX_KEY_LEN: usize = 32; fn cbc_encrypt<'a, C: BlockEncryptMut + BlockCipher + KeyInit>( - es: EncryptionScheme<'_>, + es: EncryptionScheme, key: EncryptionKey, iv: &[u8], buffer: &'a mut [u8], @@ -33,7 +33,7 @@ fn cbc_encrypt<'a, C: BlockEncryptMut + BlockCipher + KeyInit>( } fn cbc_decrypt<'a, C: BlockDecryptMut + BlockCipher + KeyInit>( - es: EncryptionScheme<'_>, + es: EncryptionScheme, key: EncryptionKey, iv: &[u8], buffer: &'a mut [u8], @@ -45,7 +45,7 @@ fn cbc_decrypt<'a, C: BlockDecryptMut + BlockCipher + KeyInit>( } pub fn encrypt_in_place<'b>( - params: &Parameters<'_>, + params: &Parameters, password: impl AsRef<[u8]>, buf: &'b mut [u8], pos: usize, @@ -58,11 +58,11 @@ pub fn encrypt_in_place<'b>( let key = EncryptionKey::derive_from_password(password.as_ref(), ¶ms.kdf, key_size)?; match es { - EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::(es, key, iv, buf, pos), - EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, iv, buf, pos), - EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, iv, buf, pos), + EncryptionScheme::Aes128Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), + EncryptionScheme::Aes192Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), + EncryptionScheme::Aes256Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), #[cfg(feature = "3des")] - EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, iv, buf, pos), + EncryptionScheme::DesEde3Cbc { iv } => cbc_encrypt::(es, key, &iv, buf, pos), #[cfg(feature = "des-insecure")] EncryptionScheme::DesCbc { .. } => Err(Error::UnsupportedAlgorithm { oid: super::DES_CBC_OID, @@ -72,7 +72,7 @@ pub fn encrypt_in_place<'b>( /// Decrypt a message encrypted with PBES2-based key derivation pub fn decrypt_in_place<'a>( - params: &Parameters<'_>, + params: &Parameters, password: impl AsRef<[u8]>, buf: &'a mut [u8], ) -> Result<&'a [u8]> { @@ -80,13 +80,13 @@ pub fn decrypt_in_place<'a>( let key = EncryptionKey::derive_from_password(password.as_ref(), ¶ms.kdf, es.key_size())?; match es { - EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::(es, key, iv, buf), - EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, iv, buf), - EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, iv, buf), + EncryptionScheme::Aes128Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), + EncryptionScheme::Aes192Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), + EncryptionScheme::Aes256Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), #[cfg(feature = "3des")] - EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, iv, buf), + EncryptionScheme::DesEde3Cbc { iv } => cbc_decrypt::(es, key, &iv, buf), #[cfg(feature = "des-insecure")] - EncryptionScheme::DesCbc { iv } => cbc_decrypt::(es, key, iv, buf), + EncryptionScheme::DesCbc { iv } => cbc_decrypt::(es, key, &iv, buf), } } @@ -99,7 +99,7 @@ struct EncryptionKey { impl EncryptionKey { /// Derive an encryption key using the supplied PBKDF parameters. - pub fn derive_from_password(password: &[u8], kdf: &Kdf<'_>, key_size: usize) -> Result { + pub fn derive_from_password(password: &[u8], kdf: &Kdf, key_size: usize) -> Result { // if the kdf params defined a key length, ensure it matches the required key size if let Some(len) = kdf.key_length() { if key_size != len.into() { @@ -153,7 +153,7 @@ impl EncryptionKey { } /// Derive key using PBKDF2. - fn derive_with_pbkdf2(password: &[u8], params: &Pbkdf2Params<'_>, length: usize) -> Self + fn derive_with_pbkdf2(password: &[u8], params: &Pbkdf2Params, length: usize) -> Self where D: CoreProxy, D::Core: Sync @@ -170,7 +170,7 @@ impl EncryptionKey { pbkdf2_hmac::( password, - params.salt, + params.salt.as_ref(), params.iteration_count, &mut buffer[..length], ); @@ -179,15 +179,11 @@ impl EncryptionKey { } /// Derive key using scrypt. - fn derive_with_scrypt( - password: &[u8], - params: &ScryptParams<'_>, - length: usize, - ) -> Result { + fn derive_with_scrypt(password: &[u8], params: &ScryptParams, length: usize) -> Result { let mut buffer = [0u8; MAX_KEY_LEN]; scrypt( password, - params.salt, + params.salt.as_ref(), ¶ms.try_into()?, &mut buffer[..length], ) diff --git a/pkcs5/src/pbes2/kdf.rs b/pkcs5/src/pbes2/kdf.rs index 63378cbcb..b16496351 100644 --- a/pkcs5/src/pbes2/kdf.rs +++ b/pkcs5/src/pbes2/kdf.rs @@ -1,8 +1,12 @@ //! Key derivation functions. +mod salt; + +pub use self::salt::Salt; + use crate::{AlgorithmIdentifierRef, Error, Result}; use der::{ - asn1::{AnyRef, ObjectIdentifier, OctetStringRef}, + asn1::{AnyRef, ObjectIdentifier}, Decode, DecodeValue, Encode, EncodeValue, ErrorKind, Length, Reader, Sequence, Tag, Tagged, Writer, }; @@ -40,15 +44,15 @@ type ScryptCost = u64; /// Password-based key derivation function. #[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] -pub enum Kdf<'a> { +pub enum Kdf { /// Password-Based Key Derivation Function 2 (PBKDF2). - Pbkdf2(Pbkdf2Params<'a>), + Pbkdf2(Pbkdf2Params), /// scrypt sequential memory-hard password hashing function. - Scrypt(ScryptParams<'a>), + Scrypt(ScryptParams), } -impl<'a> Kdf<'a> { +impl Kdf { /// Get derived key length in bytes, if defined. // TODO(tarcieri): rename to `key_size` to match `EncryptionScheme::key_size`? pub fn key_length(&self) -> Option { @@ -67,7 +71,7 @@ impl<'a> Kdf<'a> { } /// Get [`Pbkdf2Params`] if it is the selected algorithm. - pub fn pbkdf2(&self) -> Option<&Pbkdf2Params<'a>> { + pub fn pbkdf2(&self) -> Option<&Pbkdf2Params> { match self { Self::Pbkdf2(params) => Some(params), _ => None, @@ -75,7 +79,7 @@ impl<'a> Kdf<'a> { } /// Get [`ScryptParams`] if it is the selected algorithm. - pub fn scrypt(&self) -> Option<&ScryptParams<'a>> { + pub fn scrypt(&self) -> Option<&ScryptParams> { match self { Self::Scrypt(params) => Some(params), _ => None, @@ -99,13 +103,13 @@ impl<'a> Kdf<'a> { } } -impl<'a> DecodeValue<'a> for Kdf<'a> { +impl<'a> DecodeValue<'a> for Kdf { fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { AlgorithmIdentifierRef::decode_value(reader, header)?.try_into() } } -impl EncodeValue for Kdf<'_> { +impl EncodeValue for Kdf { fn value_len(&self) -> der::Result { self.oid().encoded_len()? + match self { @@ -126,24 +130,24 @@ impl EncodeValue for Kdf<'_> { } } -impl<'a> Sequence<'a> for Kdf<'a> {} +impl Sequence<'_> for Kdf {} -impl<'a> From> for Kdf<'a> { - fn from(params: Pbkdf2Params<'a>) -> Self { +impl From for Kdf { + fn from(params: Pbkdf2Params) -> Self { Kdf::Pbkdf2(params) } } -impl<'a> From> for Kdf<'a> { - fn from(params: ScryptParams<'a>) -> Self { +impl From for Kdf { + fn from(params: ScryptParams) -> Self { Kdf::Scrypt(params) } } -impl<'a> TryFrom> for Kdf<'a> { +impl TryFrom> for Kdf { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'_>) -> der::Result { if let Some(params) = alg.parameters { match alg.oid { PBKDF2_OID => params.try_into().map(Self::Pbkdf2), @@ -172,11 +176,11 @@ impl<'a> TryFrom> for Kdf<'a> { /// ``` /// /// [RFC 8018 Appendix A.2]: https://tools.ietf.org/html/rfc8018#appendix-A.2 -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Pbkdf2Params<'a> { +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Pbkdf2Params { /// PBKDF2 salt // TODO(tarcieri): support `CHOICE` with `otherSource` - pub salt: &'a [u8], + pub salt: Salt, /// PBKDF2 iteration count pub iteration_count: u32, @@ -188,7 +192,7 @@ pub struct Pbkdf2Params<'a> { pub prf: Pbkdf2Prf, } -impl<'a> Pbkdf2Params<'a> { +impl Pbkdf2Params { /// Implementation defined maximum iteration count of 100,000,000. /// /// > For especially critical keys, or @@ -203,12 +207,13 @@ impl<'a> Pbkdf2Params<'a> { const INVALID_ERR: Error = Error::AlgorithmParametersInvalid { oid: PBKDF2_OID }; /// Initialize PBKDF2-SHA256 with the given iteration count and salt - pub fn hmac_with_sha256(iteration_count: u32, salt: &'a [u8]) -> Result { + pub fn hmac_with_sha256(iteration_count: u32, salt: &[u8]) -> Result { if iteration_count > Self::MAX_ITERATION_COUNT { return Err(Self::INVALID_ERR); } + Ok(Self { - salt, + salt: salt.try_into().map_err(|_| Self::INVALID_ERR)?, iteration_count, key_length: None, prf: Pbkdf2Prf::HmacWithSha256, @@ -216,15 +221,15 @@ impl<'a> Pbkdf2Params<'a> { } } -impl<'a> DecodeValue<'a> for Pbkdf2Params<'a> { +impl<'a> DecodeValue<'a> for Pbkdf2Params { fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { AnyRef::decode_value(reader, header)?.try_into() } } -impl EncodeValue for Pbkdf2Params<'_> { +impl EncodeValue for Pbkdf2Params { fn value_len(&self) -> der::Result { - let len = OctetStringRef::new(self.salt)?.encoded_len()? + let len = self.salt.encoded_len()? + self.iteration_count.encoded_len()? + self.key_length.encoded_len()?; @@ -236,7 +241,7 @@ impl EncodeValue for Pbkdf2Params<'_> { } fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> { - OctetStringRef::new(self.salt)?.encode(writer)?; + self.salt.encode(writer)?; self.iteration_count.encode(writer)?; self.key_length.encode(writer)?; @@ -248,16 +253,16 @@ impl EncodeValue for Pbkdf2Params<'_> { } } -impl<'a> Sequence<'a> for Pbkdf2Params<'a> {} +impl Sequence<'_> for Pbkdf2Params {} -impl<'a> TryFrom> for Pbkdf2Params<'a> { +impl TryFrom> for Pbkdf2Params { type Error = der::Error; - fn try_from(any: AnyRef<'a>) -> der::Result { + fn try_from(any: AnyRef<'_>) -> der::Result { any.sequence(|reader| { // TODO(tarcieri): support salt `CHOICE` w\ `AlgorithmIdentifier` Ok(Self { - salt: OctetStringRef::decode(reader)?.as_bytes(), + salt: reader.decode()?, iteration_count: reader.decode()?, key_length: reader.decode()?, prf: Option::>::decode(reader)? @@ -316,10 +321,10 @@ impl Default for Pbkdf2Prf { } } -impl<'a> TryFrom> for Pbkdf2Prf { +impl TryFrom> for Pbkdf2Prf { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'_>) -> der::Result { if let Some(params) = alg.parameters { // TODO(tarcieri): support non-NULL parameters? if !params.is_null() { @@ -341,7 +346,7 @@ impl<'a> TryFrom> for Pbkdf2Prf { } } -impl<'a> From for AlgorithmIdentifierRef<'a> { +impl From for AlgorithmIdentifierRef<'_> { fn from(prf: Pbkdf2Prf) -> Self { // TODO(tarcieri): support non-NULL parameters? let parameters = der::asn1::Null; @@ -376,10 +381,10 @@ impl Encode for Pbkdf2Prf { /// ``` /// /// [RFC 7914 Section 7.1]: https://datatracker.ietf.org/doc/html/rfc7914#section-7.1 -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct ScryptParams<'a> { +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ScryptParams { /// scrypt salt - pub salt: &'a [u8], + pub salt: Salt, /// CPU/Memory cost parameter `N`. pub cost_parameter: ScryptCost, @@ -394,7 +399,7 @@ pub struct ScryptParams<'a> { pub key_length: Option, } -impl<'a> ScryptParams<'a> { +impl ScryptParams { #[cfg(feature = "pbes2")] const INVALID_ERR: Error = Error::AlgorithmParametersInvalid { oid: SCRYPT_OID }; @@ -402,9 +407,9 @@ impl<'a> ScryptParams<'a> { /// and a provided salt string. // TODO(tarcieri): encapsulate `scrypt::Params`? #[cfg(feature = "pbes2")] - pub fn from_params_and_salt(params: scrypt::Params, salt: &'a [u8]) -> Result { + pub fn from_params_and_salt(params: scrypt::Params, salt: &[u8]) -> Result { Ok(Self { - salt, + salt: salt.try_into().map_err(|_| Self::INVALID_ERR)?, cost_parameter: 1 << params.log_n(), block_size: params.r().try_into().map_err(|_| Self::INVALID_ERR)?, parallelization: params.p().try_into().map_err(|_| Self::INVALID_ERR)?, @@ -413,15 +418,15 @@ impl<'a> ScryptParams<'a> { } } -impl<'a> DecodeValue<'a> for ScryptParams<'a> { +impl<'a> DecodeValue<'a> for ScryptParams { fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { AnyRef::decode_value(reader, header)?.try_into() } } -impl EncodeValue for ScryptParams<'_> { +impl EncodeValue for ScryptParams { fn value_len(&self) -> der::Result { - OctetStringRef::new(self.salt)?.encoded_len()? + self.salt.encoded_len()? + self.cost_parameter.encoded_len()? + self.block_size.encoded_len()? + self.parallelization.encoded_len()? @@ -429,7 +434,7 @@ impl EncodeValue for ScryptParams<'_> { } fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> { - OctetStringRef::new(self.salt)?.encode(writer)?; + self.salt.encode(writer)?; self.cost_parameter.encode(writer)?; self.block_size.encode(writer)?; self.parallelization.encode(writer)?; @@ -438,15 +443,15 @@ impl EncodeValue for ScryptParams<'_> { } } -impl<'a> Sequence<'a> for ScryptParams<'a> {} +impl Sequence<'_> for ScryptParams {} -impl<'a> TryFrom> for ScryptParams<'a> { +impl TryFrom> for ScryptParams { type Error = der::Error; - fn try_from(any: AnyRef<'a>) -> der::Result { + fn try_from(any: AnyRef<'_>) -> der::Result { any.sequence(|reader| { Ok(Self { - salt: OctetStringRef::decode(reader)?.as_bytes(), + salt: reader.decode()?, cost_parameter: reader.decode()?, block_size: reader.decode()?, parallelization: reader.decode()?, @@ -457,19 +462,19 @@ impl<'a> TryFrom> for ScryptParams<'a> { } #[cfg(feature = "pbes2")] -impl<'a> TryFrom> for scrypt::Params { +impl TryFrom for scrypt::Params { type Error = Error; - fn try_from(params: ScryptParams<'a>) -> Result { + fn try_from(params: ScryptParams) -> Result { scrypt::Params::try_from(¶ms) } } #[cfg(feature = "pbes2")] -impl<'a> TryFrom<&ScryptParams<'a>> for scrypt::Params { +impl TryFrom<&ScryptParams> for scrypt::Params { type Error = Error; - fn try_from(params: &ScryptParams<'a>) -> Result { + fn try_from(params: &ScryptParams) -> Result { let n = params.cost_parameter; // Compute log2 and verify its correctness diff --git a/pkcs5/src/pbes2/kdf/salt.rs b/pkcs5/src/pbes2/kdf/salt.rs new file mode 100644 index 000000000..75c5a0758 --- /dev/null +++ b/pkcs5/src/pbes2/kdf/salt.rs @@ -0,0 +1,102 @@ +//! Salt storage buffer which works on heapless `no_std` targets. +// TODO(tarcieri): use `ArrayVec` when it's available in `core`. + +use core::fmt; +use der::{DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag, Writer}; + +/// Salt as used by the PBES2 KDF. +#[derive(Clone, Eq, PartialEq)] +pub struct Salt { + inner: [u8; Self::MAX_LEN], + length: Length, +} + +impl Salt { + /// Maximum length of a salt that can be stored. + pub const MAX_LEN: usize = 32; + + /// Create a new salt from the given byte slice. + pub fn new(slice: impl AsRef<[u8]>) -> Result { + let slice = slice.as_ref(); + + if slice.len() > Self::MAX_LEN { + return Err(Self::TAG.length_error()); + } + + let mut inner = [0u8; Self::MAX_LEN]; + let mut i = 0; + + while i < slice.len() { + inner[i] = slice[i]; + i += 1; + } + + Ok(Self { + inner, + length: Length::new(slice.len() as u16), + }) + } + + /// Borrow the salt data as a byte slice. + pub fn as_bytes(&self) -> &[u8] { + let length = usize::try_from(self.length).expect("should be less than Self::MAX_LEN"); + &self.inner[..length] + } + + /// Get the length of the salt data. + pub fn len(&self) -> Length { + self.length + } +} + +impl AsRef<[u8]> for Salt { + fn as_ref(&self) -> &[u8] { + self.as_bytes() + } +} + +impl<'a> DecodeValue<'a> for Salt { + fn decode_value>(reader: &mut R, header: Header) -> Result { + let length = usize::try_from(header.length)?; + + if length > Self::MAX_LEN { + return Err(Self::TAG.length_error()); + } + + let mut inner = [0u8; Self::MAX_LEN]; + reader.read_into(&mut inner[..length])?; + + Ok(Self { + inner, + length: header.length, + }) + } +} + +impl EncodeValue for Salt { + fn value_len(&self) -> Result { + Ok(self.length) + } + + fn encode_value(&self, writer: &mut impl Writer) -> Result<()> { + writer.write(self.as_bytes()) + } +} + +impl FixedTag for Salt { + const TAG: Tag = Tag::OctetString; +} + +impl TryFrom<&[u8]> for Salt { + type Error = Error; + + fn try_from(slice: &[u8]) -> Result { + Self::new(slice) + } +} + +impl fmt::Debug for Salt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Salt").field(&self.as_bytes()).finish() + } +} diff --git a/pkcs5/tests/pbes2.rs b/pkcs5/tests/pbes2.rs index bb280d031..53a463881 100644 --- a/pkcs5/tests/pbes2.rs +++ b/pkcs5/tests/pbes2.rs @@ -63,14 +63,14 @@ fn decode_pbes2_pbkdf2_sha1_aes128cbc() { let params = scheme.pbes2().unwrap(); let pbkdf2_params = params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, &hex!("e8765e01e43b6bad")); + assert_eq!(pbkdf2_params.salt.as_bytes(), &hex!("e8765e01e43b6bad")); assert_eq!(pbkdf2_params.iteration_count, 2048); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha1); match params.encryption { pbes2::EncryptionScheme::Aes128Cbc { iv } => { - assert_eq!(iv, &hex!("223080a71bcd2b9a256d876c924979d2")); + assert_eq!(iv, hex!("223080a71bcd2b9a256d876c924979d2")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -83,14 +83,14 @@ fn decode_pbes2_pbkdf2_sha256_aes256cbc() { let params = scheme.pbes2().unwrap(); let pbkdf2_params = params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, &hex!("79d982e70df91a88")); + assert_eq!(pbkdf2_params.salt.as_bytes(), &hex!("79d982e70df91a88")); assert_eq!(pbkdf2_params.iteration_count, 2048); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256); match params.encryption { pbes2::EncryptionScheme::Aes256Cbc { iv } => { - assert_eq!(iv, &hex!("b2d02d78b2efd9dff694cf8e0af40925")); + assert_eq!(iv, hex!("b2d02d78b2efd9dff694cf8e0af40925")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -103,7 +103,7 @@ fn decode_pbes2_scrypt_aes256cbc() { let params = scheme.pbes2().unwrap(); let scrypt_params = params.kdf.scrypt().unwrap(); - assert_eq!(scrypt_params.salt, &hex!("E6211E2348AD69E0")); + assert_eq!(scrypt_params.salt.as_bytes(), &hex!("E6211E2348AD69E0")); assert_eq!(scrypt_params.cost_parameter, 16384); assert_eq!(scrypt_params.block_size, 8); assert_eq!(scrypt_params.parallelization, 1); @@ -111,7 +111,7 @@ fn decode_pbes2_scrypt_aes256cbc() { match params.encryption { pbes2::EncryptionScheme::Aes256Cbc { iv } => { - assert_eq!(iv, &hex!("9BD0A6251F2254F9FD5963887C27CF01")); + assert_eq!(iv, hex!("9BD0A6251F2254F9FD5963887C27CF01")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -125,14 +125,14 @@ fn decode_pbes2_pbkdf2_sha256_desede3cbc() { let params = scheme.pbes2().unwrap(); let pbkdf2_params = params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, &hex!("32A0AE2E01BBE329")); + assert_eq!(pbkdf2_params.salt.as_bytes(), &hex!("32A0AE2E01BBE329")); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256); assert_eq!(pbkdf2_params.iteration_count, 2048); match params.encryption { pbes2::EncryptionScheme::DesEde3Cbc { iv } => { - assert_eq!(iv, &hex!("97E8F53AB0ACA359")); + assert_eq!(iv, hex!("97E8F53AB0ACA359")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -146,14 +146,14 @@ fn decode_pbes2_pbkdf2_sha256_descbc() { let params = scheme.pbes2().unwrap(); let pbkdf2_params = params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, &hex!("09E7EDFBD9F21E2B")); + assert_eq!(pbkdf2_params.salt.as_bytes(), &hex!("09E7EDFBD9F21E2B")); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256); assert_eq!(pbkdf2_params.iteration_count, 2048); match params.encryption { pbes2::EncryptionScheme::DesCbc { iv } => { - assert_eq!(iv, &hex!("F4AAF206A18DE7AD")); + assert_eq!(iv, hex!("F4AAF206A18DE7AD")); } other => panic!("unexpected encryption scheme: {:?}", other), } diff --git a/pkcs8/Cargo.toml b/pkcs8/Cargo.toml index 9d591f53f..63f59c0a8 100644 --- a/pkcs8/Cargo.toml +++ b/pkcs8/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" rust-version = "1.65" [dependencies] -der = { version = "0.7", features = ["oid"] } +der = { version = "0.7.8", features = ["oid"] } spki = { version = "0.7.1" } # optional dependencies diff --git a/pkcs8/src/encrypted_private_key_info.rs b/pkcs8/src/encrypted_private_key_info.rs index d55949cad..bad1df6a8 100644 --- a/pkcs8/src/encrypted_private_key_info.rs +++ b/pkcs8/src/encrypted_private_key_info.rs @@ -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 { @@ -40,23 +40,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 { /// Algorithm identifier describing a password-based symmetric encryption /// scheme used to encrypt the `encrypted_data` field. - pub encryption_algorithm: EncryptionScheme<'a>, + pub encryption_algorithm: EncryptionScheme, /// Private key data - pub encrypted_data: &'a [u8], + pub encrypted_data: Data, } -impl<'a> EncryptedPrivateKeyInfo<'a> { +impl<'a, Data> EncryptedPrivateKeyInfo +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 { Ok(self .encryption_algorithm - .decrypt(password, self.encrypted_data)? + .decrypt(password, self.encrypted_data.as_ref())? .try_into()?) } @@ -74,15 +77,15 @@ impl<'a> EncryptedPrivateKeyInfo<'a> { let mut iv = [0u8; 16]; rng.fill_bytes(&mut iv); - let pbes2_params = pbes2::Parameters::scrypt_aes256cbc(Default::default(), &salt, &iv)?; - EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, doc) + let pbes2_params = pbes2::Parameters::scrypt_aes256cbc(Default::default(), &salt, iv)?; + Self::encrypt_with(pbes2_params, password, doc) } /// Encrypt this private key using a symmetric encryption key derived /// from the provided password and [`pbes2::Parameters`]. #[cfg(feature = "encryption")] pub(crate) fn encrypt_with( - pbes2_params: pbes2::Parameters<'a>, + pbes2_params: pbes2::Parameters, password: impl AsRef<[u8]>, doc: &[u8], ) -> Result { @@ -90,42 +93,51 @@ 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> { - fn decode_value>( - reader: &mut R, - header: Header, - ) -> der::Result> { +impl<'a, Data> DecodeValue<'a> for EncryptedPrivateKeyInfo +where + Data: From<&'a [u8]>, +{ + fn decode_value>(reader: &mut R, header: Header) -> der::Result { 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 EncodeValue for EncryptedPrivateKeyInfo +where + Data: AsRef<[u8]>, +{ fn value_len(&self) -> der::Result { 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 where + Data: AsRef<[u8]> + From<&'a [u8]> +{ +} -impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> { +impl<'a, Data> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo +where + Data: AsRef<[u8]> + From<&'a [u8]>, +{ type Error = Error; fn try_from(bytes: &'a [u8]) -> Result { @@ -133,7 +145,7 @@ impl<'a> TryFrom<&'a [u8]> for EncryptedPrivateKeyInfo<'a> { } } -impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> { +impl fmt::Debug for EncryptedPrivateKeyInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("EncryptedPrivateKeyInfo") .field("encryption_algorithm", &self.encryption_algorithm) @@ -142,24 +154,37 @@ impl<'a> fmt::Debug for EncryptedPrivateKeyInfo<'a> { } #[cfg(feature = "alloc")] -impl TryFrom> for SecretDocument { +impl<'a, Data> TryFrom> for SecretDocument +where + Data: AsRef<[u8]> + From<&'a [u8]>, +{ type Error = Error; - fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo<'_>) -> Result { + fn try_from(encrypted_private_key: EncryptedPrivateKeyInfo) -> Result { SecretDocument::try_from(&encrypted_private_key) } } #[cfg(feature = "alloc")] -impl TryFrom<&EncryptedPrivateKeyInfo<'_>> for SecretDocument { +impl<'a, Data> TryFrom<&EncryptedPrivateKeyInfo> for SecretDocument +where + Data: AsRef<[u8]> + From<&'a [u8]>, +{ type Error = Error; - fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo<'_>) -> Result { + fn try_from(encrypted_private_key: &EncryptedPrivateKeyInfo) -> Result { Ok(Self::encode_msg(encrypted_private_key)?) } } #[cfg(feature = "pem")] -impl PemLabel for EncryptedPrivateKeyInfo<'_> { +impl PemLabel for EncryptedPrivateKeyInfo { 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>; diff --git a/pkcs8/src/lib.rs b/pkcs8/src/lib.rs index 33ceef8e2..f7980d670 100644 --- a/pkcs8/src/lib.rs +++ b/pkcs8/src/lib.rs @@ -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; @@ -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, }; @@ -96,7 +96,7 @@ pub use spki::{ #[cfg(feature = "alloc")] pub use { - crate::traits::EncodePrivateKey, + crate::{private_key_info::PrivateKeyInfoOwned, traits::EncodePrivateKey}, der::{Document, SecretDocument}, spki::EncodePublicKey, }; @@ -104,8 +104,13 @@ pub use { #[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; diff --git a/pkcs8/src/private_key_info.rs b/pkcs8/src/private_key_info.rs index ecae624df..05048f97c 100644 --- a/pkcs8/src/private_key_info.rs +++ b/pkcs8/src/private_key_info.rs @@ -1,19 +1,23 @@ //! PKCS#8 `PrivateKeyInfo`. -use crate::{AlgorithmIdentifierRef, Error, Result, Version}; +use crate::{Error, Result, Version}; use core::fmt; use der::{ asn1::{AnyRef, BitStringRef, ContextSpecific, OctetStringRef}, Decode, DecodeValue, Encode, EncodeValue, Header, Length, Reader, Sequence, TagMode, TagNumber, Writer, }; +use spki::AlgorithmIdentifier; #[cfg(feature = "alloc")] -use der::SecretDocument; +use { + alloc::boxed::Box, + der::{asn1::Any, SecretDocument}, +}; #[cfg(feature = "encryption")] use { - crate::EncryptedPrivateKeyInfo, + crate::EncryptedPrivateKeyInfoRef, der::zeroize::Zeroizing, pkcs5::pbes2, rand_core::{CryptoRng, RngCore}, @@ -90,23 +94,23 @@ const PUBLIC_KEY_TAG: TagNumber = TagNumber::N1; /// [RFC 5208 Section 5]: https://tools.ietf.org/html/rfc5208#section-5 /// [RFC 5958 Section 2]: https://datatracker.ietf.org/doc/html/rfc5958#section-2 #[derive(Clone)] -pub struct PrivateKeyInfo<'a> { +pub struct PrivateKeyInfoInner { /// X.509 `AlgorithmIdentifier` for the private key type. - pub algorithm: AlgorithmIdentifierRef<'a>, + pub algorithm: AlgorithmIdentifier, /// Private key data. - pub private_key: &'a [u8], + pub private_key: Key, /// Public key data, optionally available if version is V2. - pub public_key: Option<&'a [u8]>, + pub public_key: Option, } -impl<'a> PrivateKeyInfo<'a> { - /// Create a new PKCS#8 [`PrivateKeyInfo`] message. +impl PrivateKeyInfoInner { + /// Create a new PKCS#8 [`PrivateKeyInfoInner`] message. /// /// This is a helper method which initializes `attributes` and `public_key` /// to `None`, helpful if you aren't using those. - pub fn new(algorithm: AlgorithmIdentifierRef<'a>, private_key: &'a [u8]) -> Self { + pub fn new(algorithm: AlgorithmIdentifier, private_key: Key) -> Self { Self { algorithm, private_key, @@ -124,7 +128,12 @@ impl<'a> PrivateKeyInfo<'a> { Version::V1 } } - +} +impl<'a, Params, Key> PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]> + AsRef<[u8]>, +{ /// Encrypt this private key using a symmetric encryption key derived /// from the provided password. /// @@ -141,7 +150,7 @@ impl<'a> PrivateKeyInfo<'a> { password: impl AsRef<[u8]>, ) -> Result { let der = Zeroizing::new(self.to_der()?); - EncryptedPrivateKeyInfo::encrypt(rng, password, der.as_ref()) + EncryptedPrivateKeyInfoRef::encrypt(rng, password, der.as_ref()) } /// Encrypt this private key using a symmetric encryption key derived @@ -149,18 +158,25 @@ impl<'a> PrivateKeyInfo<'a> { #[cfg(feature = "encryption")] pub fn encrypt_with_params( &self, - pbes2_params: pbes2::Parameters<'_>, + pbes2_params: pbes2::Parameters, password: impl AsRef<[u8]>, ) -> Result { let der = Zeroizing::new(self.to_der()?); - EncryptedPrivateKeyInfo::encrypt_with(pbes2_params, password, der.as_ref()) + EncryptedPrivateKeyInfoRef::encrypt_with(pbes2_params, password, der.as_ref()) } +} +impl<'a, Params, Key> PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: AsRef<[u8]>, +{ /// Get a `BIT STRING` representation of the public key, if present. - fn public_key_bit_string(&self) -> der::Result>>> { + fn public_key_bit_string(&self) -> der::Result>>> { self.public_key + .as_ref() .map(|pk| { - BitStringRef::from_bytes(pk).map(|value| ContextSpecific { + BitStringRef::from_bytes(pk.as_ref()).map(|value| ContextSpecific { tag_number: PUBLIC_KEY_TAG, tag_mode: TagMode::Implicit, value, @@ -170,21 +186,24 @@ impl<'a> PrivateKeyInfo<'a> { } } -impl<'a> DecodeValue<'a> for PrivateKeyInfo<'a> { - fn decode_value>( - reader: &mut R, - header: Header, - ) -> der::Result> { +impl<'a, Params, Key> DecodeValue<'a> for PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]>, +{ + fn decode_value>(reader: &mut R, header: Header) -> der::Result { reader.read_nested(header.length, |reader| { // Parse and validate `version` INTEGER. let version = Version::decode(reader)?; let algorithm = reader.decode()?; - let private_key = OctetStringRef::decode(reader)?.into(); + let private_key: &[u8] = OctetStringRef::decode(reader)?.into(); + let private_key = Key::try_from(private_key)?; let public_key = reader .context_specific::>(PUBLIC_KEY_TAG, TagMode::Implicit)? .map(|bs| { bs.as_bytes() .ok_or_else(|| der::Tag::BitString.value_error()) + .map(Key::from) }) .transpose()?; @@ -213,26 +232,39 @@ impl<'a> DecodeValue<'a> for PrivateKeyInfo<'a> { } } -impl EncodeValue for PrivateKeyInfo<'_> { +impl<'a, Params, Key> EncodeValue for PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: AsRef<[u8]>, +{ fn value_len(&self) -> der::Result { self.version().encoded_len()? + self.algorithm.encoded_len()? - + OctetStringRef::new(self.private_key)?.encoded_len()? + + OctetStringRef::new(self.private_key.as_ref())?.encoded_len()? + self.public_key_bit_string()?.encoded_len()? } fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> { self.version().encode(writer)?; self.algorithm.encode(writer)?; - OctetStringRef::new(self.private_key)?.encode(writer)?; + OctetStringRef::new(self.private_key.as_ref())?.encode(writer)?; self.public_key_bit_string()?.encode(writer)?; Ok(()) } } -impl<'a> Sequence<'a> for PrivateKeyInfo<'a> {} +impl<'a, Params, Key> Sequence<'a> for PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]> + AsRef<[u8]>, +{ +} -impl<'a> TryFrom<&'a [u8]> for PrivateKeyInfo<'a> { +impl<'a, Params, Key> TryFrom<&'a [u8]> for PrivateKeyInfoInner +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]> + AsRef<[u8]>, +{ type Error = Error; fn try_from(bytes: &'a [u8]) -> Result { @@ -240,9 +272,13 @@ impl<'a> TryFrom<&'a [u8]> for PrivateKeyInfo<'a> { } } -impl<'a> fmt::Debug for PrivateKeyInfo<'a> { +impl fmt::Debug for PrivateKeyInfoInner +where + Params: fmt::Debug, + Key: fmt::Debug, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("PrivateKeyInfo") + f.debug_struct("PrivateKeyInfoInner") .field("version", &self.version()) .field("algorithm", &self.algorithm) .field("public_key", &self.public_key) @@ -251,45 +287,102 @@ impl<'a> fmt::Debug for PrivateKeyInfo<'a> { } #[cfg(feature = "alloc")] -impl TryFrom> for SecretDocument { +impl<'a, Params, Key> TryFrom> for SecretDocument +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]> + AsRef<[u8]>, +{ type Error = Error; - fn try_from(private_key: PrivateKeyInfo<'_>) -> Result { + fn try_from(private_key: PrivateKeyInfoInner) -> Result { SecretDocument::try_from(&private_key) } } #[cfg(feature = "alloc")] -impl TryFrom<&PrivateKeyInfo<'_>> for SecretDocument { +impl<'a, Params, Key> TryFrom<&PrivateKeyInfoInner> for SecretDocument +where + Params: der::Choice<'a> + Encode, + Key: From<&'a [u8]> + AsRef<[u8]>, +{ type Error = Error; - fn try_from(private_key: &PrivateKeyInfo<'_>) -> Result { + fn try_from(private_key: &PrivateKeyInfoInner) -> Result { Ok(Self::encode_msg(private_key)?) } } #[cfg(feature = "pem")] -impl PemLabel for PrivateKeyInfo<'_> { +impl PemLabel for PrivateKeyInfoInner { const PEM_LABEL: &'static str = "PRIVATE KEY"; } #[cfg(feature = "subtle")] -impl<'a> ConstantTimeEq for PrivateKeyInfo<'a> { +impl ConstantTimeEq for PrivateKeyInfoInner +where + Params: Eq, + Key: PartialEq + AsRef<[u8]>, +{ fn ct_eq(&self, other: &Self) -> Choice { // NOTE: public fields are not compared in constant time let public_fields_eq = self.algorithm == other.algorithm && self.public_key == other.public_key; - self.private_key.ct_eq(other.private_key) & Choice::from(public_fields_eq as u8) + self.private_key.as_ref().ct_eq(other.private_key.as_ref()) + & Choice::from(public_fields_eq as u8) } } #[cfg(feature = "subtle")] -impl<'a> Eq for PrivateKeyInfo<'a> {} +impl Eq for PrivateKeyInfoInner +where + Params: Eq, + Key: AsRef<[u8]> + Eq, +{ +} #[cfg(feature = "subtle")] -impl<'a> PartialEq for PrivateKeyInfo<'a> { +impl PartialEq for PrivateKeyInfoInner +where + Params: Eq, + Key: PartialEq + AsRef<[u8]>, +{ fn eq(&self, other: &Self) -> bool { self.ct_eq(other).into() } } + +/// [`PrivateKeyInfoInner`] with [`AnyRef`] algorithm parameters, and `&[u8]` key. +pub type PrivateKeyInfo<'a> = PrivateKeyInfoInner, &'a [u8]>; + +/// [`PrivateKeyInfo`] with [`Any`] algorithm parameters, and `Box<[u8]>` key. +#[cfg(feature = "alloc")] +pub type PrivateKeyInfoOwned = PrivateKeyInfoInner>; + +#[cfg(feature = "alloc")] +mod allocating { + use super::*; + use der::referenced::*; + + impl<'a> RefToOwned<'a> for PrivateKeyInfo<'a> { + type Owned = PrivateKeyInfoOwned; + fn ref_to_owned(&self) -> Self::Owned { + PrivateKeyInfoOwned { + algorithm: self.algorithm.ref_to_owned(), + private_key: self.private_key.ref_to_owned(), + public_key: self.public_key.ref_to_owned(), + } + } + } + + impl OwnedToRef for PrivateKeyInfoOwned { + type Borrowed<'a> = PrivateKeyInfo<'a>; + fn owned_to_ref(&self) -> Self::Borrowed<'_> { + PrivateKeyInfo { + algorithm: self.algorithm.owned_to_ref(), + private_key: self.private_key.owned_to_ref(), + public_key: self.public_key.owned_to_ref(), + } + } + } +} diff --git a/pkcs8/src/traits.rs b/pkcs8/src/traits.rs index f6165f696..62d85f1d3 100644 --- a/pkcs8/src/traits.rs +++ b/pkcs8/src/traits.rs @@ -7,7 +7,7 @@ use der::SecretDocument; #[cfg(feature = "encryption")] use { - crate::EncryptedPrivateKeyInfo, + crate::EncryptedPrivateKeyInfoRef, rand_core::{CryptoRng, RngCore}, }; @@ -34,7 +34,7 @@ pub trait DecodePrivateKey: Sized { /// (binary format) and attempt to decrypt it using the provided password. #[cfg(feature = "encryption")] fn from_pkcs8_encrypted_der(bytes: &[u8], password: impl AsRef<[u8]>) -> Result { - let doc = EncryptedPrivateKeyInfo::try_from(bytes)?.decrypt(password)?; + let doc = EncryptedPrivateKeyInfoRef::try_from(bytes)?.decrypt(password)?; Self::from_pkcs8_der(doc.as_bytes()) } @@ -66,7 +66,7 @@ pub trait DecodePrivateKey: Sized { #[cfg(all(feature = "encryption", feature = "pem"))] fn from_pkcs8_encrypted_pem(s: &str, password: impl AsRef<[u8]>) -> Result { let (label, doc) = SecretDocument::from_pem(s)?; - EncryptedPrivateKeyInfo::validate_pem_label(label)?; + EncryptedPrivateKeyInfoRef::validate_pem_label(label)?; Self::from_pkcs8_encrypted_der(doc.as_bytes(), password) } @@ -109,7 +109,7 @@ pub trait EncodePrivateKey { rng: impl CryptoRng + RngCore, password: impl AsRef<[u8]>, ) -> Result { - EncryptedPrivateKeyInfo::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes()) + EncryptedPrivateKeyInfoRef::encrypt(rng, password, self.to_pkcs8_der()?.as_bytes()) } /// Serialize this private key as PEM-encoded PKCS#8 with the given [`LineEnding`]. @@ -129,7 +129,7 @@ pub trait EncodePrivateKey { line_ending: LineEnding, ) -> Result> { let doc = self.to_pkcs8_encrypted_der(rng, password)?; - Ok(doc.to_pem(EncryptedPrivateKeyInfo::PEM_LABEL, line_ending)?) + Ok(doc.to_pem(EncryptedPrivateKeyInfoRef::PEM_LABEL, line_ending)?) } /// Write ASN.1 DER-encoded PKCS#8 private key to the given path diff --git a/pkcs8/tests/encrypted_private_key.rs b/pkcs8/tests/encrypted_private_key.rs index dbe0a18e7..7582dcf2b 100644 --- a/pkcs8/tests/encrypted_private_key.rs +++ b/pkcs8/tests/encrypted_private_key.rs @@ -3,7 +3,7 @@ #![cfg(feature = "pkcs5")] use hex_literal::hex; -use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfo, PrivateKeyInfo}; +use pkcs8::{pkcs5::pbes2, EncryptedPrivateKeyInfoRef, PrivateKeyInfo}; #[cfg(feature = "alloc")] use der::Encode; @@ -79,7 +79,7 @@ const PASSWORD: &[u8] = b"hunter42"; // Bad password; don't actually use outside #[test] fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() { - let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap(); + let pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES128_PBKDF2_SHA1_EXAMPLE).unwrap(); assert_eq!( pk.encryption_algorithm.oid(), @@ -89,14 +89,14 @@ fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() { let pbes2_params = pk.encryption_algorithm.pbes2().unwrap(); let pbkdf2_params = pbes2_params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, hex!("e8765e01e43b6bad")); + assert_eq!(pbkdf2_params.salt.as_ref(), hex!("e8765e01e43b6bad")); assert_eq!(pbkdf2_params.iteration_count, 2048); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha1); match pbes2_params.encryption { pbes2::EncryptionScheme::Aes128Cbc { iv } => { - assert_eq!(iv, &hex!("223080a71bcd2b9a256d876c924979d2")); + assert_eq!(iv, hex!("223080a71bcd2b9a256d876c924979d2")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -111,7 +111,8 @@ fn decode_ed25519_encpriv_aes128_pbkdf2_sha1_der() { #[test] fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() { - let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); + let pk = + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); assert_eq!( pk.encryption_algorithm.oid(), @@ -121,14 +122,14 @@ fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() { let pbes2_params = pk.encryption_algorithm.pbes2().unwrap(); let pbkdf2_params = pbes2_params.kdf.pbkdf2().unwrap(); - assert_eq!(pbkdf2_params.salt, hex!("79d982e70df91a88")); + assert_eq!(pbkdf2_params.salt.as_ref(), hex!("79d982e70df91a88")); assert_eq!(pbkdf2_params.iteration_count, 2048); assert_eq!(pbkdf2_params.key_length, None); assert_eq!(pbkdf2_params.prf, pbes2::Pbkdf2Prf::HmacWithSha256); match pbes2_params.encryption { pbes2::EncryptionScheme::Aes256Cbc { iv } => { - assert_eq!(iv, &hex!("b2d02d78b2efd9dff694cf8e0af40925")); + assert_eq!(iv, hex!("b2d02d78b2efd9dff694cf8e0af40925")); } other => panic!("unexpected encryption scheme: {:?}", other), } @@ -145,7 +146,7 @@ fn decode_ed25519_encpriv_aes256_pbkdf2_sha256_der() { #[test] fn decrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() { let enc_pk = - EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); let pk = enc_pk.decrypt(PASSWORD).unwrap(); assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); } @@ -153,7 +154,7 @@ fn decrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() { #[cfg(feature = "encryption")] #[test] fn decrypt_ed25519_der_encpriv_aes256_scrypt() { - let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap(); + let enc_pk = EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_SCRYPT_EXAMPLE).unwrap(); let pk = enc_pk.decrypt(PASSWORD).unwrap(); assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); } @@ -164,7 +165,7 @@ fn encrypt_ed25519_der_encpriv_aes256_pbkdf2_sha256() { let pbes2_params = pkcs5::pbes2::Parameters::pbkdf2_sha256_aes256cbc( 2048, &hex!("79d982e70df91a88"), - &hex!("b2d02d78b2efd9dff694cf8e0af40925"), + hex!("b2d02d78b2efd9dff694cf8e0af40925"), ) .unwrap(); @@ -185,7 +186,7 @@ fn encrypt_ed25519_der_encpriv_aes256_scrypt() { let scrypt_params = pkcs5::pbes2::Parameters::scrypt_aes256cbc( pkcs5::scrypt::Params::new(15, 8, 1, 32).unwrap(), &hex!("E6211E2348AD69E0"), - &hex!("9BD0A6251F2254F9FD5963887C27CF01"), + hex!("9BD0A6251F2254F9FD5963887C27CF01"), ) .unwrap(); @@ -200,7 +201,8 @@ fn encrypt_ed25519_der_encpriv_aes256_scrypt() { #[test] #[cfg(feature = "alloc")] fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() { - let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); + let pk = + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); assert_eq!( ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE, &pk.to_der().unwrap() @@ -210,7 +212,8 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_der() { #[test] #[cfg(feature = "pem")] fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() { - let pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); + let pk = + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_AES256_PBKDF2_SHA256_EXAMPLE).unwrap(); assert_eq!( ED25519_PEM_AES256_PBKDF2_SHA256_EXAMPLE, pk.to_pem(Default::default()).unwrap() @@ -220,7 +223,8 @@ fn encode_ed25519_encpriv_aes256_pbkdf2_sha256_pem() { #[test] #[cfg(feature = "3des")] fn decrypt_ed25519_der_encpriv_des3_pbkdf2_sha256() { - let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap(); + let enc_pk = + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES3_PBKDF2_SHA256_EXAMPLE).unwrap(); let pk = enc_pk.decrypt(PASSWORD).unwrap(); assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); } @@ -228,7 +232,8 @@ fn decrypt_ed25519_der_encpriv_des3_pbkdf2_sha256() { #[test] #[cfg(feature = "des-insecure")] fn decrypt_ed25519_der_encpriv_des_pbkdf2_sha256() { - let enc_pk = EncryptedPrivateKeyInfo::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap(); + let enc_pk = + EncryptedPrivateKeyInfoRef::try_from(ED25519_DER_DES_PBKDF2_SHA256_EXAMPLE).unwrap(); let pk = enc_pk.decrypt(PASSWORD).unwrap(); assert_eq!(pk.as_bytes(), ED25519_DER_PLAINTEXT_EXAMPLE); } diff --git a/pkcs8/tests/private_key.rs b/pkcs8/tests/private_key.rs index 1ef0f7361..22b8e4bec 100644 --- a/pkcs8/tests/private_key.rs +++ b/pkcs8/tests/private_key.rs @@ -59,7 +59,7 @@ fn decode_ec_p256_der() { // Extracted with: // $ openssl asn1parse -inform der -in tests/examples/p256-priv.der - assert_eq!(pk.private_key, &hex!("306B020101042069624171561A63340DE0E7D869F2A05492558E1A04868B6A9F854A866788188DA144034200041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]); + assert_eq!(pk.private_key.as_ref(), &hex!("306B020101042069624171561A63340DE0E7D869F2A05492558E1A04868B6A9F854A866788188DA144034200041CACFFB55F2F2CEFD89D89EB374B2681152452802DEEA09916068137D839CF7FC481A44492304D7EF66AC117BEFE83A8D08F155F2B52F9F618DD447029048E0F")[..]); } // Test vector from RFC8410 Section 10.3: @@ -74,7 +74,7 @@ fn decode_ed25519_der_v1() { // Extracted with: // $ openssl asn1parse -inform der -in tests/examples/ed25519-priv.der assert_eq!( - pk.private_key, + pk.private_key.as_ref(), &hex!("042017ED9C73E9DB649EC189A612831C5FC570238207C1AA9DFBD2C53E3FF5E5EA85")[..] ); } @@ -94,8 +94,11 @@ fn decode_ed25519_der_v2() { assert_eq!(pk.version(), Version::V2); assert_eq!(pk.algorithm.oid, "1.3.101.112".parse().unwrap()); assert_eq!(pk.algorithm.parameters, None); - assert_eq!(pk.private_key, PRIV_KEY); - assert_eq!(pk.public_key, Some(&PUB_KEY[..])); + assert_eq!(pk.private_key.as_ref(), PRIV_KEY); + assert_eq!( + pk.public_key.as_ref().map(|p| p.as_ref()), + Some(&PUB_KEY[..]) + ); } #[test] @@ -107,7 +110,7 @@ fn decode_rsa_2048_der() { // Extracted with: // $ openssl asn1parse -inform der -in tests/examples/rsa2048-priv.der - assert_eq!(pk.private_key, &hex!("308204A30201000282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001028201007ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C102818100DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D6702818100D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F902818100CE68B7AC1B0D100D636E55488753C5C09843FDB390E2705DF7689457C9BD8D9765E30978617E2EFC8048F4C324206DB86087B654E97BB3D464E7EE3F8CD83FE10436F7DF18E9A963C4E64911D67EDE34042F2E26E3D3A1AD346ADAD6B9B7F67708CB094E62DEE9FF4D5D6669AF988AF2255D1CE8ED317C6A7D8691DA354D12DB02818025F6E5944220286B4DFBBF4235C0EE5843D2198091895120D6CA7B200B826D3ECE738E2E00498FAC0A2A6CA969C7F0C3CA1AB0BC40297132BE7538D7BEDF4CB0EFC6B98EF7DBA54F56AA99AABCE534C49C27947D4678C51C63C78C7CE1687231B4C8EB587AE6EF0480CBAF4FC0173CFD587A7E67AF515FB9B9DE75111839722902818031995406D406207CADEAEA35B38D040C5F8A9A1AE0827E9ED06B153D83B6821935B4B36A82BE9D56C791B58C27271A5793D53A1D657C08997960B1433E5171987F452F144A7C72306D63E1D3FFC0B71B75AB08F2E45A482E988451CBE478E12EB228D07456C924B66F6CED048D853F533E31A68614F1C3CE6D8EC9983CE72AF7")[..]); + assert_eq!(pk.private_key.as_ref(), &hex!("308204A30201000282010100B6C42C515F10A6AAF282C63EDBE24243A170F3FA2633BD4833637F47CA4F6F36E03A5D29EFC3191AC80F390D874B39E30F414FCEC1FCA0ED81E547EDC2CD382C76F61C9018973DB9FA537972A7C701F6B77E0982DFC15FC01927EE5E7CD94B4F599FF07013A7C8281BDF22DCBC9AD7CABB7C4311C982F58EDB7213AD4558B332266D743AED8192D1884CADB8B14739A8DADA66DC970806D9C7AC450CB13D0D7C575FB198534FC61BC41BC0F0574E0E0130C7BBBFBDFDC9F6A6E2E3E2AFF1CBEAC89BA57884528D55CFB08327A1E8C89F4E003CF2888E933241D9D695BCBBACDC90B44E3E095FA37058EA25B13F5E295CBEAC6DE838AB8C50AF61E298975B872F0203010001028201007ECC8362C0EDB0741164215E22F74AB9D91BA06900700CF63690E5114D8EE6BDCFBB2E3F9614692A677A083F168A5E52E5968E6407B9D97C6E0E4064F82DA0B758A14F17B9B7D41F5F48E28D6551704F56E69E7AA9FA630FC76428C06D25E455DCFC55B7AC2B4F76643FDED3FE15FF78ABB27E65ACC4AAD0BDF6DB27EF60A6910C5C4A085ED43275AB19C1D997A32C6EFFCE7DF2D1935F6E601EEDE161A12B5CC27CA21F81D2C99C3D1EA08E90E3053AB09BEFA724DEF0D0C3A3C1E9740C0D9F76126A149EC0AA7D8078205484254D951DB07C4CF91FB6454C096588FD5924DBABEB359CA2025268D004F9D66EB3D6F7ADC1139BAD40F16DDE639E11647376C102818100DCC061242D4E92AFAEE72AC513CA65B9F77036F9BD7E0E6E61461A7EF7654225EC153C7E5C31A6157A6E5A13FF6E178E8758C1CB33D9D6BBE3179EF18998E422ECDCBED78F4ECFDBE5F4FCD8AEC2C9D0DC86473CA9BD16D9D238D21FB5DDEFBEB143CA61D0BD6AA8D91F33A097790E9640DBC91085DC5F26343BA3138F6B2D6702818100D3F314757E40E954836F92BE24236AF2F0DA04A34653C180AF67E960086D93FDE65CB23EFD9D09374762F5981E361849AF68CDD75394FF6A4E06EB69B209E4228DB2DFA70E40F7F9750A528176647B788D0E5777A2CB8B22E3CD267FF70B4F3B02D3AAFB0E18C590A564B03188B0AA5FC48156B07622214243BD1227EFA7F2F902818100CE68B7AC1B0D100D636E55488753C5C09843FDB390E2705DF7689457C9BD8D9765E30978617E2EFC8048F4C324206DB86087B654E97BB3D464E7EE3F8CD83FE10436F7DF18E9A963C4E64911D67EDE34042F2E26E3D3A1AD346ADAD6B9B7F67708CB094E62DEE9FF4D5D6669AF988AF2255D1CE8ED317C6A7D8691DA354D12DB02818025F6E5944220286B4DFBBF4235C0EE5843D2198091895120D6CA7B200B826D3ECE738E2E00498FAC0A2A6CA969C7F0C3CA1AB0BC40297132BE7538D7BEDF4CB0EFC6B98EF7DBA54F56AA99AABCE534C49C27947D4678C51C63C78C7CE1687231B4C8EB587AE6EF0480CBAF4FC0173CFD587A7E67AF515FB9B9DE75111839722902818031995406D406207CADEAEA35B38D040C5F8A9A1AE0827E9ED06B153D83B6821935B4B36A82BE9D56C791B58C27271A5793D53A1D657C08997960B1433E5171987F452F144A7C72306D63E1D3FFC0B71B75AB08F2E45A482E988451CBE478E12EB228D07456C924B66F6CED048D853F533E31A68614F1C3CE6D8EC9983CE72AF7")[..]); } #[test] @@ -120,7 +123,7 @@ fn decode_x25519_der() { // Extracted with: // $ openssl asn1parse -inform der -in tests/examples/x25519-priv.der assert_eq!( - pk.private_key, + pk.private_key.as_ref(), &hex!("04207060252933AC6E7A4A9B0EB2632C5A040A87257ADB869A3ECCC3D16B724F2647")[..] ); }