Skip to main content

auth_framework/utils/
crypto.rs

1//! Cryptographic utility functions for the AuthFramework.
2
3use crate::errors::Result;
4use rand::{RngExt, rng};
5
6/// Generate a random alphanumeric token of specified length.
7///
8/// Delegates to [`generate_secure_token`] internally — both use the same
9/// cryptographically secure RNG (`rand::rng()`).  Prefer
10/// `generate_secure_token` in new code so callers handle errors explicitly.
11pub fn generate_token(length: usize) -> String {
12    // Unwrap is safe: generate_secure_token currently cannot fail,
13    // but if it ever does we want to surface the panic rather than
14    // silently returning a short/empty token.
15    generate_secure_token(length).expect("CSPRNG token generation failed")
16}
17
18/// Generate a cryptographically secure random string
19pub fn generate_secure_token(length: usize) -> Result<String> {
20    const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
21                             abcdefghijklmnopqrstuvwxyz\
22                             0123456789";
23    let token: String = (0..length)
24        .map(|_| {
25            let idx = rng().random_range(0..CHARSET.len());
26            CHARSET[idx] as char
27        })
28        .collect();
29
30    Ok(token)
31}
32/// Generate a hex-encoded random token
33pub fn generate_hex_token(byte_length: usize) -> Result<String> {
34    let mut bytes = vec![0u8; byte_length];
35    rng().fill(&mut bytes[..]);
36    Ok(hex::encode(bytes))
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn test_generate_token() {
45        let token = generate_token(32);
46        assert_eq!(token.len(), 32);
47        assert!(token.chars().all(|c| c.is_alphanumeric()));
48    }
49
50    #[test]
51    fn test_generate_secure_token() {
52        let token = generate_secure_token(32).unwrap();
53        assert_eq!(token.len(), 32);
54        assert!(token.chars().all(|c| c.is_alphanumeric()));
55    }
56
57    #[test]
58    fn test_generate_hex_token() {
59        let token = generate_hex_token(16).unwrap();
60        assert_eq!(token.len(), 32); // 16 bytes = 32 hex chars
61        assert!(token.chars().all(|c| c.is_ascii_hexdigit()));
62    }
63}