kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs

crypto.rs (2198B)


      1 use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
      2 use rand::Rng;
      3 
      4 /// Generate cryptographically secure random bytes
      5 ///
      6 /// Returns a vector of random bytes of the specified length
      7 pub fn generate_random_bytes(length: usize) -> Vec<u8> {
      8     let mut rng = rand::thread_rng();
      9     let mut bytes = vec![0u8; length];
     10     rng.fill(&mut bytes[..]);
     11     bytes
     12 }
     13 
     14 /// Generate a cryptographically secure nonce
     15 ///
     16 /// Format: base64 encoded random bytes
     17 ///
     18 /// Example: "k7E9mZqYvXwPxR2nT8uL5sA6fH3jC1dG4bN0iM9oU2p"
     19 pub fn generate_nonce(bytes_len: usize) -> String {
     20     let bytes = generate_random_bytes(bytes_len);
     21     URL_SAFE_NO_PAD.encode(bytes)
     22 }
     23 
     24 /// Generate a cryptographically secure access token
     25 ///
     26 /// Format: base64 encoded random bytes
     27 ///
     28 /// Example: "xR2nT8uL5sA6fH3jC1dG4bN0iM9oU2pk7E9mZqYvXwP"
     29 pub fn generate_token(bytes_len: usize) -> String {
     30     let bytes = generate_random_bytes(bytes_len);
     31     URL_SAFE_NO_PAD.encode(bytes)
     32 }
     33 
     34 /// Generate a cryptographically secure authorization code
     35 ///
     36 /// Format: base64 encoded random bytes
     37 ///
     38 /// Example: "a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V"
     39 pub fn generate_authorization_code(bytes_len: usize) -> String {
     40     let bytes = generate_random_bytes(bytes_len);
     41     URL_SAFE_NO_PAD.encode(bytes)
     42 }
     43 
     44 #[cfg(test)]
     45 mod tests {
     46     use super::*;
     47     use std::collections::HashSet;
     48 
     49     #[test]
     50     fn test_nonce_generation() {
     51         let nonce = generate_nonce(32);
     52 
     53         // Check length (32 bytes base64 = 43 chars without padding)
     54         assert_eq!(nonce.len(), 43);
     55 
     56         // Check it's URL-safe (only contains valid characters)
     57         assert!(nonce.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_'));
     58     }
     59 
     60     #[test]
     61     fn test_nonces_are_unique() {
     62         let mut nonces = HashSet::new();
     63 
     64         // Generate 1000 nonces, all should be unique
     65         for _ in 0..1000 {
     66             let nonce = generate_nonce(32);
     67             assert!(nonces.insert(nonce), "Duplicate nonce generated!");
     68         }
     69     }
     70 
     71     #[test]
     72     fn test_no_padding_in_tokens() {
     73         // Ensure no '=' padding characters
     74         let nonce = generate_nonce(32);
     75 
     76         assert!(!nonce.contains('='));
     77     }
     78 }