crypto.rs (1477B)
1 use data_encoding::Encoding; 2 use ring::{digest, pbkdf2}; 3 use std::num::NonZeroU32; 4 5 static DIGEST_ALG: pbkdf2::Algorithm = pbkdf2::PBKDF2_HMAC_SHA256; 6 const OUTPUT_LEN: usize = digest::SHA256_OUTPUT_LEN; 7 8 pub fn hash_password(secret: &[u8], salt: &[u8], iterations: u32) -> Vec<u8> { 9 let mut out = vec![0u8; OUTPUT_LEN]; // Initialize array with zeros 10 let iterations = NonZeroU32::new(iterations).expect("Iterations can't be zero"); 11 pbkdf2::derive(DIGEST_ALG, iterations, salt, secret, &mut out); 12 out 13 } 14 15 pub fn verify_password_hash(secret: &[u8], salt: &[u8], previous: &[u8], iterations: u32) -> bool { 16 let iterations = NonZeroU32::new(iterations).expect("Iterations can't be zero"); 17 pbkdf2::verify(DIGEST_ALG, iterations, salt, secret, previous).is_ok() 18 } 19 // 20 // Random values 21 // 22 23 /// Return an array holding `N` random bytes. 24 pub fn get_random_bytes<const N: usize>() -> [u8; N] { 25 use ring::rand::{SecureRandom, SystemRandom}; 26 let mut array = [0; N]; 27 SystemRandom::new() 28 .fill(&mut array) 29 .expect("Error generating random values"); 30 array 31 } 32 33 /// Encode random bytes using the provided function. 34 pub fn encode_random_bytes<const N: usize>(e: &Encoding) -> String { 35 e.encode(&get_random_bytes::<N>()) 36 } 37 38 // 39 // Constant time compare 40 // 41 pub fn ct_eq<T: AsRef<[u8]>, U: AsRef<[u8]>>(a: T, b: U) -> bool { 42 use ring::constant_time::verify_slices_are_equal; 43 verify_slices_are_equal(a.as_ref(), b.as_ref()).is_ok() 44 }