diff --git a/libs/crypto/src/lib.rs b/libs/crypto/src/lib.rs index 1ca99d5..8edc071 100644 --- a/libs/crypto/src/lib.rs +++ b/libs/crypto/src/lib.rs @@ -295,6 +295,27 @@ impl TryFrom<&str> for Password { }); } + if let Some(ds_pbkdf2_b64) = value.strip_prefix("{PBKDF2_SHA256}") { + let base64_decoder_config = general_purpose::GeneralPurposeConfig::new() + .with_decode_allow_trailing_bits(true); + let base64_decoder = + GeneralPurpose::new(&alphabet::STANDARD, base64_decoder_config); + let ds_pbkdf2 = base64_decoder.decode(ds_pbkdf2_b64).map_err(|e| { + error!(?e, "Invalid base64 in 389ds PBKDF2_SHA256"); + })?; + let cost = u32::from_be_bytes(ds_pbkdf2[0..4].try_into().unwrap()); + let c: usize = cost.try_into().unwrap(); + let s: Vec = ds_pbkdf2[4..68].try_into().unwrap(); + let h: Vec = ds_pbkdf2[68..ds_pbkdf2.len()].try_into().unwrap(); + if h.len() < PBKDF2_MIN_NIST_KEY_LEN { + warn!("389ds PBKDF2_SHA256: hash length {} too short vs. {}!", h.len(), PBKDF2_MIN_NIST_KEY_LEN); + return Err(()); + } + return Ok(Password { + material: Kdf::PBKDF2(c, s, h) + }) + } + // Test for OpenLDAP formats if value.starts_with("{PBKDF2}") || value.starts_with("{PBKDF2-SHA1}")