#[cfg(feature = "crypto")]
pub fn hash_sha256(input: &str) -> String {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(input.as_bytes());
format!("{:x}", hasher.finalize())
}
#[cfg(feature = "crypto")]
pub fn verify_sha256(input: &str, expected: &str) -> bool {
hash_sha256(input) == expected
}
#[cfg(feature = "crypto")]
pub fn generate_token(bytes: usize) -> String {
use base64::Engine;
let random: Vec<u8> = (0..bytes).map(|_| rand::random::<u8>()).collect();
base64::engine::general_purpose::URL_SAFE.encode(&random)
}
#[cfg(feature = "crypto")]
pub fn secure_compare(a: &str, b: &str) -> bool {
use subtle::ConstantTimeEq;
if a.len() != b.len() {
return false;
}
a.as_bytes().ct_eq(b.as_bytes()).unwrap_u8() == 1
}
#[cfg(feature = "crypto")]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_sha256() {
let h = hash_sha256("hello");
assert_eq!(
h,
"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
);
}
#[test]
fn test_verify_sha256() {
let h = hash_sha256("hello");
assert!(verify_sha256("hello", &h));
assert!(!verify_sha256("world", &h));
}
#[test]
fn test_generate_token() {
let t = generate_token(32);
assert!(!t.is_empty());
}
#[test]
fn test_secure_compare() {
assert!(secure_compare("test", "test"));
assert!(!secure_compare("test", "Test"));
}
}