shared/utils/crypto/
secure_token.rs1use crate::error::{CoreError, InternalError, Result};
2use base64::{Engine, prelude::BASE64_URL_SAFE_NO_PAD};
3use rand::TryRngCore;
4use sha2::{Digest, Sha256};
5
6#[derive(Clone)]
7pub struct SecureToken {
8 size: usize,
9}
10
11impl Default for SecureToken {
12 fn default() -> Self {
13 Self::with_size32()
14 }
15}
16
17impl SecureToken {
18 pub fn with_size32() -> Self {
19 Self { size: 32 }
20 }
21 pub fn with_size64() -> Self {
22 Self { size: 64 }
23 }
24}
25
26impl SecureToken {
27 pub fn generate(&self) -> Result<String> {
28 let mut bytes = vec![0u8; self.size];
29
30 rand::rngs::OsRng
31 .try_fill_bytes(&mut bytes)
32 .map_err(|_| CoreError::Internal(InternalError::Hashing))?;
33
34 Ok(BASE64_URL_SAFE_NO_PAD.encode(&bytes))
35 }
36 pub fn hash(&self, token: &str) -> String {
37 let mut hasher = Sha256::new();
38 hasher.update(token.as_bytes());
39
40 format!("{:x}", hasher.finalize())
41 }
42
43 pub fn verify(&self, a: &str, b: &str) -> bool {
44 if a.len() != b.len() {
45 return false;
46 }
47
48 a.bytes()
49 .zip(b.bytes())
50 .fold(0, |acc, (a, b)| acc | (a ^ b))
51 == 0
52 }
53}