sysmonk/squire/
secure.rs

1extern crate base64;
2extern crate sha2;
3
4use base64::{engine::general_purpose::URL_SAFE, Engine as _};
5use rand::{thread_rng, Rng};
6use sha2::{Digest, Sha512};
7
8/// Calculates the SHA-512 hash value for the given payload.
9///
10/// # Arguments
11///
12/// * `value` - The payload for which the hash is to be calculated.
13///
14/// # Returns
15///
16/// A hexadecimal string representing the SHA-512 hash value.
17///
18/// ## References
19/// - [Official docs](https://docs.rs/sha2/latest/sha2/#usage)
20pub fn calculate_hash(value: String) -> String {
21    let mut hasher = Sha512::new();
22    hasher.update(value);
23    let result = hasher.finalize();
24    format!("{:x}", result)
25}
26
27/// Encodes a binary string to a Base64-encoded ASCII string.
28///
29/// This function is similar to the built-in `btoa` function in native JavaScript,
30/// treating each character in the input string as a byte of binary data.
31///
32/// # Arguments
33///
34/// * `value` - The binary string to be encoded.
35///
36/// # Returns
37///
38/// A Base64-encoded ASCII string.
39///
40/// ## References
41/// - [Official docs](https://docs.rs/base64/latest/base64/#url-safe-alphabet)
42#[allow(dead_code)]  // Just for reference
43pub fn base64_encode(value: &str) -> String {
44    URL_SAFE.encode(value.as_bytes())
45}
46
47/// Decodes a Base64-encoded string to its original binary representation.
48///
49/// This function is similar to the built-in `atob` function in native JavaScript.
50///
51/// # Arguments
52///
53/// * `value` - The Base64-encoded string to be decoded.
54///
55/// # Returns
56///
57/// A `Result` containing the decoded string or an error message.
58///
59/// ## References
60/// - [Official Docs](https://docs.rs/base64/latest/base64/#url-safe-alphabet)
61pub fn base64_decode(value: &str) -> Result<String, &'static str> {
62    if let Ok(decoded_bytes) = URL_SAFE.decode(value) {
63        if let Ok(decoded_str) = String::from_utf8(decoded_bytes) {
64            return Ok(decoded_str);
65        } else {
66            log::error!("Error decoding UTF-8");
67        }
68    } else {
69        log::error!("Error decoding Base64");
70    }
71    Err("Server was unable to decrypt the credentials")
72}
73
74/// Encodes a string value into a hexadecimal representation.
75///
76/// # Arguments
77///
78/// * `value` - The string value to be encoded.
79///
80/// # Returns
81///
82/// A string representing the hexadecimal encoding of the input.
83pub fn hex_encode(value: &str) -> String {
84    let mut hex_values: Vec<String> = Vec::new();
85    for ch in value.chars() {
86        let hex_value = format!("{:04x}", ch as u32);
87        hex_values.push(hex_value);
88    }
89    format!("\\u{}", hex_values.join("\\u"))
90}
91
92/// Decodes a hexadecimal-encoded string into its original string representation.
93///
94/// # Arguments
95///
96/// * `value` - The hexadecimal-encoded string to be decoded.
97///
98/// # Returns
99///
100/// A string representing the decoded content.
101pub fn hex_decode(value: &str) -> String {
102    let mut result = String::new();
103    let hex_values: Vec<&str> = value.split("\\u").skip(1).collect();
104    for hex_value in hex_values {
105        if let Ok(code_point) = u32::from_str_radix(hex_value, 16) {
106            if let Some(ch) = char::from_u32(code_point) {
107                result.push(ch);
108            }
109        }
110    }
111    result
112}
113
114/// Generates a random key with a length of 64 characters from the specified character set.
115///
116/// # Returns
117///
118/// A randomly generated key.
119pub fn keygen() -> String {
120    const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
121    let mut rng = thread_rng();
122    let token: String = (0..64)
123        .map(|_| {
124            let idx = rng.gen_range(0..CHARSET.len());
125            CHARSET[idx] as char
126        })
127        .collect();
128    token
129}