ate_crypto/crypto/
short_hash.rs

1use serde::{Deserialize, Serialize};
2use sha3::Digest;
3use std::convert::TryInto;
4#[allow(unused_imports)]
5use tracing::{debug, error, info, instrument, span, trace, warn, Level};
6
7use crate::crypto::HashRoutine;
8
9/// Represents a hash of a piece of data that is cryptographically secure enough
10/// that it can be used for integrity but small enough that it does not bloat
11/// the redo log metadata.
12#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
13pub struct ShortHash {
14    pub val: u32,
15}
16
17impl ShortHash {
18    pub fn from_bytes(input: &[u8]) -> ShortHash {
19        Self::from_bytes_by_routine(input, crate::HASH_ROUTINE)
20    }
21
22    pub fn from_bytes_twice(input1: &[u8], input2: &[u8]) -> ShortHash {
23        Self::from_bytes_twice_by_routine(input1, input2, crate::HASH_ROUTINE)
24    }
25
26    fn from_bytes_by_routine(input: &[u8], routine: HashRoutine) -> ShortHash {
27        match routine {
28            HashRoutine::Sha3 => ShortHash::from_bytes_sha3(input, 1),
29            HashRoutine::Blake3 => ShortHash::from_bytes_blake3(input),
30        }
31    }
32
33    fn from_bytes_twice_by_routine(
34        input1: &[u8],
35        input2: &[u8],
36        routine: HashRoutine,
37    ) -> ShortHash {
38        match routine {
39            HashRoutine::Sha3 => ShortHash::from_bytes_twice_sha3(input1, input2),
40            HashRoutine::Blake3 => ShortHash::from_bytes_twice_blake3(input1, input2),
41        }
42    }
43
44    pub fn from_bytes_blake3(input: &[u8]) -> ShortHash {
45        let hash = blake3::hash(input);
46        let bytes: [u8; 32] = hash.into();
47        let mut bytes4: [u8; 4] = Default::default();
48        bytes4.copy_from_slice(&bytes[0..4]);
49        ShortHash {
50            val: u32::from_be_bytes(bytes4),
51        }
52    }
53
54    fn from_bytes_twice_blake3(input1: &[u8], input2: &[u8]) -> ShortHash {
55        let mut hasher = blake3::Hasher::new();
56        hasher.update(input1);
57        hasher.update(input2);
58        let hash = hasher.finalize();
59        let bytes: [u8; 32] = hash.into();
60        let mut bytes4: [u8; 4] = Default::default();
61        bytes4.copy_from_slice(&bytes[0..4]);
62        ShortHash {
63            val: u32::from_be_bytes(bytes4),
64        }
65    }
66
67    pub fn from_bytes_sha3(input: &[u8], repeat: i32) -> ShortHash {
68        let mut hasher = sha3::Keccak384::new();
69        for _ in 0..repeat {
70            hasher.update(input);
71        }
72        let result = hasher.finalize();
73        let result: Vec<u8> = result.into_iter().take(4).collect();
74        let result: [u8; 4] = result
75            .try_into()
76            .expect("The hash should fit into 4 bytes!");
77        let result = u32::from_be_bytes(result);
78
79        ShortHash { val: result }
80    }
81
82    fn from_bytes_twice_sha3(input1: &[u8], input2: &[u8]) -> ShortHash {
83        let mut hasher = sha3::Keccak384::new();
84        hasher.update(input1);
85        hasher.update(input2);
86        let result = hasher.finalize();
87        let result = result.iter().take(4).map(|b| *b).collect::<Vec<_>>();
88        let result: [u8; 4] = result
89            .try_into()
90            .expect("The hash should fit into 4 bytes!");
91        let result = u32::from_be_bytes(result);
92
93        ShortHash { val: result }
94    }
95
96    pub fn to_hex_string(&self) -> String {
97        hex::encode(self.val.to_be_bytes())
98    }
99
100    pub fn to_string(&self) -> String {
101        self.to_hex_string()
102    }
103
104    pub fn to_bytes(&self) -> [u8; 4] {
105        self.val.to_be_bytes()
106    }
107}
108
109impl From<String> for ShortHash {
110    fn from(val: String) -> ShortHash {
111        ShortHash::from_bytes(val.as_bytes())
112    }
113}
114
115impl From<&'static str> for ShortHash {
116    fn from(val: &'static str) -> ShortHash {
117        ShortHash::from(val.to_string())
118    }
119}
120
121impl From<u64> for ShortHash {
122    fn from(val: u64) -> ShortHash {
123        ShortHash::from_bytes(&val.to_be_bytes())
124    }
125}
126
127impl std::fmt::Display for ShortHash {
128    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129        write!(f, "{}", self.to_string())
130    }
131}