diff --git a/Cargo.lock b/Cargo.lock index 12e72294..5c4cc698 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -334,15 +334,6 @@ dependencies = [ "streebog", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro2" version = "1.0.101" @@ -367,26 +358,6 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - [[package]] name = "rand_core" version = "0.9.3" @@ -457,7 +428,7 @@ name = "sha-crypt" version = "0.6.0-pre.1" dependencies = [ "base64ct", - "rand", + "rand_core", "sha2", "subtle", ] @@ -617,26 +588,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "zerocopy" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zeroize" version = "1.8.2" diff --git a/sha-crypt/Cargo.toml b/sha-crypt/Cargo.toml index 291de482..21b1cfe2 100644 --- a/sha-crypt/Cargo.toml +++ b/sha-crypt/Cargo.toml @@ -18,15 +18,15 @@ rust-version = "1.85" [dependencies] sha2 = { version = "0.11.0-rc.2", default-features = false } +base64ct = { version = "1.7.1", default-features = false } # optional dependencies -rand = { version = "0.9", optional = true } +rand_core = { version = "0.9", optional = true, default-features = false, features = ["os_rng"] } subtle = { version = "2", optional = true, default-features = false } -base64ct = "1.7.1" [features] default = ["simple"] -simple = ["rand", "subtle"] +simple = ["base64ct/alloc", "dep:rand_core", "dep:subtle"] [package.metadata.docs.rs] all-features = true diff --git a/sha-crypt/src/defs.rs b/sha-crypt/src/defs.rs index 4865205a..51e2b9d6 100644 --- a/sha-crypt/src/defs.rs +++ b/sha-crypt/src/defs.rs @@ -14,10 +14,6 @@ pub const PW_SIZE_SHA512: usize = 86; #[cfg(feature = "simple")] pub const SALT_MAX_LEN: usize = 16; -/// Encoding table. -#[cfg(feature = "simple")] -pub static TAB: &[u8] = b"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - /// Inverse encoding map for SHA512. #[rustfmt::skip] pub const MAP_SHA512: [u8; 64] = [ diff --git a/sha-crypt/src/lib.rs b/sha-crypt/src/lib.rs index abe624e2..8e32c25d 100644 --- a/sha-crypt/src/lib.rs +++ b/sha-crypt/src/lib.rs @@ -56,12 +56,10 @@ use sha2::{Digest, Sha256, Sha512}; #[cfg(feature = "simple")] use { - crate::{ - defs::{SALT_MAX_LEN, TAB}, - errors::CheckError, - }, + crate::{defs::SALT_MAX_LEN, errors::CheckError}, alloc::string::ToString, - rand::{Rng, distr::Distribution}, + base64ct::{Base64ShaCrypt, Encoding}, + rand_core::{OsRng, RngCore, TryRngCore}, }; #[cfg(feature = "simple")] @@ -317,13 +315,7 @@ pub fn sha256_crypt_b64(password: &[u8], salt: &[u8], params: &Sha256Params) -> /// [1]: https://www.akkadia.org/drepper/SHA-crypt.txt #[cfg(feature = "simple")] pub fn sha512_simple(password: &str, params: &Sha512Params) -> String { - let rng = rand::rng(); - - let salt: String = rng - .sample_iter(&ShaCryptDistribution) - .take(SALT_MAX_LEN) - .collect(); - + let salt = random_salt(); let out = sha512_crypt(password.as_bytes(), salt.as_bytes(), params); let mut result = String::new(); @@ -352,13 +344,7 @@ pub fn sha512_simple(password: &str, params: &Sha512Params) -> String { /// [1]: https://www.akkadia.org/drepper/SHA-crypt.txt #[cfg(feature = "simple")] pub fn sha256_simple(password: &str, params: &Sha256Params) -> String { - let rng = rand::rng(); - - let salt: String = rng - .sample_iter(&ShaCryptDistribution) - .take(SALT_MAX_LEN) - .collect(); - + let salt = random_salt(); let out = sha256_crypt(password.as_bytes(), salt.as_bytes(), params); let mut result = String::new(); @@ -528,21 +514,13 @@ pub fn sha256_check(password: &str, hashed_value: &str) -> Result<(), CheckError } } +/// Generate a random salt that is 16-bytes long. #[cfg(feature = "simple")] -#[derive(Debug)] -struct ShaCryptDistribution; - -#[cfg(feature = "simple")] -impl Distribution for ShaCryptDistribution { - fn sample(&self, rng: &mut R) -> char { - const RANGE: u32 = 26 + 26 + 10 + 2; // 2 == "./" - loop { - let var = rng.next_u32() >> (32 - 6); - if var < RANGE { - return TAB[var as usize] as char; - } - } - } +fn random_salt() -> String { + // Create buffer containing raw bytes to encode as Base64 + let mut buf = [0u8; (SALT_MAX_LEN * 3).div_ceil(4)]; + OsRng.unwrap_err().fill_bytes(&mut buf); + Base64ShaCrypt::encode_string(&buf) } fn produce_byte_seq(len: usize, fill_from: &[u8]) -> Vec {