ate_crypto/crypto/
hash.rs

1use crate::crypto::RandomGeneratorAccessor;
2use crate::utils::b16_deserialize;
3use crate::utils::b16_serialize;
4use serde::{Deserialize, Serialize};
5use sha3::Digest;
6use std::convert::TryInto;
7#[allow(unused_imports)]
8use tracing::{debug, error, info, instrument, span, trace, warn, Level};
9
10use super::InitializationVector;
11
12#[derive(Debug, Clone, Copy, PartialEq)]
13pub enum HashRoutine {
14    Sha3,
15    Blake3,
16}
17
18/// Represents a hash of a piece of data that is cryptographically secure enough
19/// that it can be used for integrity but small enough that it does not bloat
20/// the redo log metadata.
21#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
22pub struct AteHash {
23    #[serde(serialize_with = "b16_serialize", deserialize_with = "b16_deserialize")]
24    pub val: [u8; 16],
25}
26
27impl AteHash {
28    pub const LEN: usize = 16;
29
30    pub fn generate() -> AteHash {
31        RandomGeneratorAccessor::generate_hash()
32    }
33    pub fn from_hex_string(input: &str) -> Option<AteHash> {
34        hex::decode(input.trim())
35            .ok()
36            .map(|a| {
37                let bytes16: Option<[u8; 16]> = a.try_into().ok();
38                bytes16
39            })
40            .flatten()
41            .map(|a| AteHash { val: a })
42    }
43    pub fn from_bytes(input: &[u8]) -> AteHash {
44        Self::from_bytes_by_routine(input, crate::HASH_ROUTINE)
45    }
46    pub fn from_bytes_twice(input1: &[u8], input2: &[u8]) -> AteHash {
47        Self::from_bytes_twice_by_routine(input1, input2, crate::HASH_ROUTINE)
48    }
49    fn from_bytes_by_routine(input: &[u8], routine: HashRoutine) -> AteHash {
50        match routine {
51            HashRoutine::Sha3 => AteHash::from_bytes_sha3(input, 1),
52            HashRoutine::Blake3 => AteHash::from_bytes_blake3(input),
53        }
54    }
55    fn from_bytes_twice_by_routine(input1: &[u8], input2: &[u8], routine: HashRoutine) -> AteHash {
56        match routine {
57            HashRoutine::Sha3 => AteHash::from_bytes_twice_sha3(input1, input2),
58            HashRoutine::Blake3 => AteHash::from_bytes_twice_blake3(input1, input2),
59        }
60    }
61    pub fn from_bytes_blake3(input: &[u8]) -> AteHash {
62        let hash = blake3::hash(input);
63        let bytes: [u8; 32] = hash.into();
64        let mut bytes16: [u8; 16] = Default::default();
65        bytes16.copy_from_slice(&bytes[0..16]);
66        AteHash { val: bytes16 }
67    }
68    fn from_bytes_twice_blake3(input1: &[u8], input2: &[u8]) -> AteHash {
69        let mut hasher = blake3::Hasher::new();
70        hasher.update(input1);
71        hasher.update(input2);
72        let hash = hasher.finalize();
73        let bytes: [u8; 32] = hash.into();
74        let mut bytes16: [u8; 16] = Default::default();
75        bytes16.copy_from_slice(&bytes[0..16]);
76        AteHash { val: bytes16 }
77    }
78    pub fn from_bytes_sha3(input: &[u8], repeat: i32) -> AteHash {
79        let mut hasher = sha3::Keccak384::default();
80        for _ in 0..repeat {
81            hasher.update(input);
82        }
83        let result = hasher.finalize();
84        let result: Vec<u8> = result.into_iter().take(16).collect();
85        let result: [u8; 16] = result
86            .try_into()
87            .expect("The hash should fit into 16 bytes!");
88
89        AteHash { val: result }
90    }
91    fn from_bytes_twice_sha3(input1: &[u8], input2: &[u8]) -> AteHash {
92        let mut hasher = sha3::Keccak384::default();
93        hasher.update(input1);
94        hasher.update(input2);
95        let result = hasher.finalize();
96        let result: Vec<u8> = result.into_iter().take(16).collect();
97        let result: [u8; 16] = result
98            .try_into()
99            .expect("The hash should fit into 16 bytes!");
100
101        AteHash { val: result }
102    }
103
104    pub fn to_u64(&self) -> u64 {
105        let mut val = [0u8; 8];
106        val.copy_from_slice(&self.val[..8]);
107        u64::from_be_bytes(val)
108    }
109
110    pub fn to_hex_string(&self) -> String {
111        hex::encode(self.val)
112    }
113
114    pub fn to_4hex(&self) -> String {
115        let ret = hex::encode(self.val);
116        format!("{}", &ret[..4])
117    }
118
119    pub fn to_8hex(&self) -> String {
120        let ret = hex::encode(self.val);
121        format!("{}", &ret[..8])
122    }
123
124    pub fn to_string(&self) -> String {
125        self.to_hex_string()
126    }
127
128    pub fn to_base64(&self) -> String {
129        base64::encode(&self.val[..])
130    }
131
132    pub fn as_bytes(&self) -> &[u8; 16] {
133        &self.val
134    }
135
136    pub fn to_iv(&self) -> InitializationVector {
137        InitializationVector {
138            bytes: self.as_bytes().to_vec()
139        }
140    }
141
142    pub fn len(&self) -> usize {
143        self.val.len()
144    }
145}
146
147impl From<String> for AteHash {
148    fn from(val: String) -> AteHash {
149        AteHash::from_bytes(val.as_bytes())
150    }
151}
152
153impl From<&'static str> for AteHash {
154    fn from(val: &'static str) -> AteHash {
155        AteHash::from(val.to_string())
156    }
157}
158
159impl From<u64> for AteHash {
160    fn from(val: u64) -> AteHash {
161        AteHash::from_bytes(&val.to_be_bytes())
162    }
163}
164
165impl From<[u8; 16]> for AteHash {
166    fn from(val: [u8; 16]) -> AteHash {
167        AteHash {
168            val,
169        }
170    }
171}
172
173impl std::fmt::Display for AteHash {
174    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175        write!(f, "{}", self.to_string())
176    }
177}