Skip to main content

crypto_core/
hash.rs

1//! Hashing primitives - SHA-256, SHA-512, BLAKE3
2
3use crate::{CryptoError, HashAlgorithm, Result};
4use digest::Digest;
5
6/// Compute SHA-256 hash
7pub fn sha256(data: &[u8]) -> Vec<u8> {
8    let mut hasher = sha2::Sha256::new();
9    hasher.update(data);
10    hasher.finalize().to_vec()
11}
12
13/// Compute SHA-512 hash
14pub fn sha512(data: &[u8]) -> Vec<u8> {
15    let mut hasher = sha2::Sha512::new();
16    hasher.update(data);
17    hasher.finalize().to_vec()
18}
19
20/// Compute BLAKE3 hash (high performance)
21pub fn blake3(data: &[u8]) -> Vec<u8> {
22    let mut hasher = blake3::Hasher::new();
23    hasher.update(data);
24    hasher.finalize().as_bytes().to_vec()
25}
26
27/// Compute hash using specified algorithm
28pub fn hash(data: &[u8], algorithm: HashAlgorithm) -> Result<Vec<u8>> {
29    match algorithm {
30        HashAlgorithm::Sha256 => Ok(sha256(data)),
31        HashAlgorithm::Sha512 => Ok(sha512(data)),
32        HashAlgorithm::Blake3 => Ok(blake3(data)),
33    }
34}
35
36/// Hash data and return hex string
37pub fn hash_hex(data: &[u8], algorithm: HashAlgorithm) -> Result<String> {
38    let hash = hash(data, algorithm)?;
39    Ok(hex_encode(&hash))
40}
41
42/// Encode bytes to hex
43pub fn hex_encode(data: &[u8]) -> String {
44    data.iter().map(|b| format!("{:02x}", b)).collect()
45}
46
47/// Decode hex to bytes
48pub fn hex_decode(s: &str) -> Result<Vec<u8>> {
49    if !s.len().is_multiple_of(2) {
50        return Err(CryptoError::HashError("Invalid hex string".to_string()));
51    }
52
53    (0..s.len())
54        .step_by(2)
55        .map(|i| {
56            u8::from_str_radix(&s[i..i + 2], 16)
57                .map_err(|_| CryptoError::HashError("Invalid hex".to_string()))
58        })
59        .collect()
60}
61
62/// Compute HMAC-SHA256
63pub fn hmac_sha256(key: &[u8], data: &[u8]) -> Vec<u8> {
64    use hmac::{Hmac, Mac};
65    use sha2::Sha256;
66
67    let mut mac =
68        Hmac::<Sha256>::new_from_slice(key).expect("HMAC-SHA256 supports arbitrary key sizes");
69    mac.update(data);
70    mac.finalize().into_bytes().to_vec()
71}
72
73/// Compute hash of multiple data chunks (for Merkle tree)
74pub fn hash_concat(data: &[&[u8]], algorithm: HashAlgorithm) -> Result<Vec<u8>> {
75    match algorithm {
76        HashAlgorithm::Sha256 => {
77            let mut h = sha2::Sha256::new();
78            for d in data {
79                h.update(d);
80            }
81            Ok(h.finalize().to_vec())
82        }
83        HashAlgorithm::Sha512 => {
84            let mut h = sha2::Sha512::new();
85            for d in data {
86                h.update(d);
87            }
88            Ok(h.finalize().to_vec())
89        }
90        HashAlgorithm::Blake3 => {
91            let mut h = blake3::Hasher::new();
92            for d in data {
93                h.update(d);
94            }
95            Ok(h.finalize().as_bytes().to_vec())
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn test_sha256() {
106        let data = b"hello world";
107        let hash = sha256(data);
108        assert_eq!(hash.len(), 32);
109    }
110
111    #[test]
112    fn test_sha512() {
113        let data = b"hello world";
114        let hash = sha512(data);
115        assert_eq!(hash.len(), 64);
116    }
117
118    #[test]
119    fn test_blake3() {
120        let data = b"hello world";
121        let hash = blake3(data);
122        assert_eq!(hash.len(), 32);
123    }
124
125    #[test]
126    fn test_hex_encode_decode() {
127        let original = b"test data";
128        let encoded = hex_encode(original);
129        let decoded = hex_decode(&encoded).unwrap();
130        assert_eq!(original.as_slice(), decoded.as_slice());
131    }
132
133    #[test]
134    fn test_hmac_sha256() {
135        let key = b"secret_key";
136        let data = b"message";
137        let hmac = hmac_sha256(key, data);
138        assert_eq!(hmac.len(), 32);
139    }
140}