Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pkcs5/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ aes = { version = "0.9", optional = true, default-features = false }
cbc = { version = "0.2", optional = true }
des = { version = "0.9", optional = true, default-features = false }
pbkdf2 = { version = "0.13", optional = true, default-features = false, features = ["hmac"] }
getrandom = { version = "0.4", optional = true, features = ["sys_rng"] }
rand_core = { version = "0.10", optional = true, default-features = false }
scrypt = { version = "0.12", optional = true, default-features = false }
sha1 = { version = "0.11", optional = true, default-features = false }
Expand All @@ -37,7 +38,9 @@ alloc = []

3des = ["dep:des", "pbes2"]
des-insecure = ["dep:des", "pbes2"]
getrandom = ["dep:getrandom", "rand_core"]
pbes2 = ["dep:aes", "dep:cbc", "dep:pbkdf2", "dep:scrypt", "dep:sha2"]
rand_core = ["dep:rand_core"]
sha1-insecure = ["dep:sha1", "pbes2"]

[lints]
Expand Down
26 changes: 23 additions & 3 deletions pkcs5/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,15 @@ pub use scrypt;
#[cfg(all(feature = "alloc", feature = "pbes2"))]
use alloc::vec::Vec;

/// Supported PKCS#5 password-based encryption schemes.
/// Configuration for supported PKCS#5 password-based encryption schemes.
///
/// <div class="warning">
/// <strong>Security Warning</strong>
///
/// This type should not be used to encrypt multiple plaintexts under the same IV/salt values.
///
/// Instead, new values should be randomly generated for every usage.
/// </div>
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
#[allow(clippy::large_enum_variant)]
Expand All @@ -57,13 +65,25 @@ pub enum EncryptionScheme {
}

impl EncryptionScheme {
/// Generate PBES2 parameters using recommended algorithm settings and parameters (salt/IV)
/// generated using the system's secure random number generator.
///
/// # Panics
/// In the event the system's secure random generator experiences an internal failure.
#[cfg(all(feature = "pbes2", feature = "getrandom"))]
#[must_use]
#[track_caller]
pub fn generate() -> Self {
Self::Pbes2(pbes2::Parameters::generate())
}

/// Attempt to decrypt the given ciphertext, allocating and returning a byte vector containing
/// the plaintext.
///
/// # Errors
/// Returns an error if the algorithm specified in this scheme's parameters is unsupported
/// (e.g. PBES1 is completely unsupported), or if the ciphertext is malformed (e.g. not a
/// multiple of a block mode's padding).
/// (e.g. PBES1 is completely unsupported), or if the ciphertext is malformed (e.g. ciphertext
/// length is not a multiple of a block mode's padding).
#[cfg(all(feature = "alloc", feature = "pbes2"))]
pub fn decrypt(&self, password: impl AsRef<[u8]>, ciphertext: &[u8]) -> Result<Vec<u8>> {
match self {
Expand Down
36 changes: 30 additions & 6 deletions pkcs5/src/pbes2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use der::{
asn1::{AnyRef, ObjectIdentifier, OctetStringRef},
};

#[cfg(feature = "rand_core")]
#[cfg(all(feature = "pbes2", feature = "rand_core"))]
use rand_core::TryCryptoRng;

#[cfg(all(feature = "alloc", feature = "pbes2"))]
Expand Down Expand Up @@ -67,6 +67,18 @@ const DES_BLOCK_SIZE: usize = 8;
/// encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} }
/// ```
///
/// These define a set of algorithms for password-based key derivation, as well as a salt value
/// (typically randomly generated) to provide to the KDF algorithm, along with an encryption
/// algorithm and its associated IV/nonce (typically randomly generated).
///
/// <div class="warning">
/// <strong>Security Warning</strong>
///
/// This type should not be used to encrypt multiple plaintexts under the same IV/salt values.
///
/// Instead, new values should be randomly generated for every usage.
/// </div>
///
/// [RFC 8018 Appendix A.4]: https://tools.ietf.org/html/rfc8018#appendix-A.4
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Parameters {
Expand All @@ -79,15 +91,27 @@ pub struct Parameters {

impl Parameters {
/// Default length of an initialization vector.
#[cfg(feature = "rand_core")]
#[cfg(all(feature = "pbes2", feature = "rand_core"))]
const DEFAULT_IV_LEN: usize = AES_BLOCK_SIZE;

/// Default length of a salt for password hashing.
#[cfg(feature = "rand_core")]
#[cfg(all(feature = "pbes2", feature = "rand_core"))]
const DEFAULT_SALT_LEN: usize = 16;

/// Generate PBES2 parameters using the recommended algorithm settings and
/// a randomly generated salt and IV.
/// Generate PBES2 parameters using recommended algorithm settings and parameters (salt/IV)
/// generated using the system's secure random number generator.
///
/// # Panics
/// In the event the system's secure random generator experiences an internal failure.
#[cfg(all(feature = "pbes2", feature = "getrandom"))]
#[must_use]
#[track_caller]
pub fn generate() -> Self {
Self::generate_recommended(&mut getrandom::SysRng).expect("random generation failure")
}

/// Generate PBES2 parameters using the recommended algorithm settings and a randomly generated
/// salt and IV.
///
/// This is currently an alias for [`Parameters::generate_scrypt`]. See that method
/// for more information.
Expand All @@ -109,7 +133,7 @@ impl Parameters {
///
/// # Errors
/// Returns [`Error::Rng`] in the event the random number generator `R` fails.
#[cfg(feature = "rand_core")]
#[cfg(all(feature = "pbes2", feature = "rand_core"))]
pub fn generate_pbkdf2<R: TryCryptoRng>(rng: &mut R) -> Result<Self> {
let mut iv = [0u8; Self::DEFAULT_IV_LEN];
rng.try_fill_bytes(&mut iv).map_err(|_| Error::Rng)?;
Expand Down
Loading