modo-rs 0.8.1

Rust web framework for small monolithic apps
Documentation
//! Crate-private helpers shared across `auth` submodules.

use subtle::ConstantTimeEq;

/// Constant-time SHA-256 hex comparison: `sha256_hex(plain) == stored_hex`.
pub(crate) fn verify_sha256_hex(plain: impl AsRef<[u8]>, stored_hex: &str) -> bool {
    let computed = crate::encoding::hex::sha256(plain.as_ref());
    computed.as_bytes().ct_eq(stored_hex.as_bytes()).into()
}

/// Generate a random string by sampling `len` characters from `alphabet` using
/// rejection sampling to avoid modulo bias.
///
/// Panics if `alphabet` is empty.
pub(crate) fn random_string(alphabet: &[u8], len: usize) -> String {
    assert!(!alphabet.is_empty(), "alphabet must not be empty");
    let n = alphabet.len();
    // Keep the comparison in usize: when n divides 256 evenly the limit is 256,
    // which would wrap to 0 if cast to u8 and hang the loop forever.
    let bias_limit: usize = (256 / n) * n;
    let mut out = String::with_capacity(len);
    let mut buf = [0u8; 1];
    while out.len() < len {
        rand::fill(&mut buf[..]);
        let b = buf[0] as usize;
        if b < bias_limit {
            out.push(alphabet[b % n] as char);
        }
    }
    out
}