futureauth 0.5.0

OTP authentication SDK — local session management with FutureAuth OTP delivery
Documentation
//! Hashing helpers for secrets stored at rest (session tokens, OTP codes,
//! magic-link tokens).
//!
//! We use SHA-256 with hex encoding. The values are high-entropy random tokens
//! generated by this crate — a simple digest is sufficient, we don't need an
//! expensive password hash (bcrypt/argon2) because there is nothing to
//! brute-force if the original value is already uniformly random.

use sha2::{Digest, Sha256};

/// Hash a secret for storage. Returns a lowercase hex string (64 chars).
pub fn hash_secret(secret: &str) -> String {
    let digest = Sha256::digest(secret.as_bytes());
    hex::encode(digest)
}

/// Constant-time byte comparison. Always compares the full length of both
/// slices to avoid leaking the matching prefix through timing.
pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
    if a.len() != b.len() {
        return false;
    }
    let mut diff: u8 = 0;
    for (x, y) in a.iter().zip(b.iter()) {
        diff |= x ^ y;
    }
    diff == 0
}