cyfs_base/crypto/
hash.rs

1use crate::*;
2
3use base58::{FromBase58, ToBase58};
4use generic_array::typenum::{marker_traits::Unsigned, U32};
5use generic_array::GenericArray;
6use std::fmt;
7use std::hash::{Hash, Hasher};
8use std::str::FromStr;
9
10// Hash
11#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq)]
12pub struct HashValue(GenericArray<u8, U32>);
13pub const HASH_VALUE_LEN: usize = 32;
14
15impl std::fmt::Debug for HashValue {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        write!(f, "HashValue: {}", hex::encode(self.0.as_slice()))
18    }
19}
20
21impl From<GenericArray<u8, U32>> for HashValue {
22    fn from(hash: GenericArray<u8, U32>) -> Self {
23        Self(hash)
24    }
25}
26
27impl From<HashValue> for GenericArray<u8, U32> {
28    fn from(hash: HashValue) -> Self {
29        hash.0
30    }
31}
32
33impl AsRef<GenericArray<u8, U32>> for HashValue {
34    fn as_ref(&self) -> &GenericArray<u8, U32> {
35        &self.0
36    }
37}
38
39impl Default for HashValue {
40    fn default() -> Self {
41        Self(GenericArray::default())
42    }
43}
44
45impl RawFixedBytes for HashValue {
46    fn raw_bytes() -> Option<usize> {
47        Some(U32::to_usize())
48    }
49}
50
51impl RawEncode for HashValue {
52    fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
53        Ok(U32::to_usize())
54    }
55    fn raw_encode<'a>(
56        &self,
57        buf: &'a mut [u8],
58        _purpose: &Option<RawEncodePurpose>,
59    ) -> BuckyResult<&'a mut [u8]> {
60        let bytes = Self::raw_bytes().unwrap();
61        if buf.len() < bytes {
62            let msg = format!(
63                "not enough buffer for encode HashValue, except={}, got={}",
64                bytes,
65                buf.len()
66            );
67            error!("{}", msg);
68
69            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
70        }
71        unsafe {
72            std::ptr::copy(self.0.as_slice().as_ptr(), buf.as_mut_ptr(), bytes);
73        }
74
75        Ok(&mut buf[bytes..])
76    }
77}
78
79impl<'de> RawDecode<'de> for HashValue {
80    fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> {
81        let bytes = Self::raw_bytes().unwrap();
82        if buf.len() < bytes {
83            let msg = format!(
84                "not enough buffer for decode HashValue, except={}, got={}",
85                bytes,
86                buf.len()
87            );
88            error!("{}", msg);
89
90            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
91        }
92        let mut hash = GenericArray::default();
93        unsafe {
94            std::ptr::copy(buf.as_ptr(), hash.as_mut_slice().as_mut_ptr(), bytes);
95        }
96        Ok((Self(hash), &buf[bytes..]))
97    }
98}
99
100impl From<&[u8; 32]> for HashValue {
101    fn from(hash: &[u8; 32]) -> Self {
102        Self(GenericArray::clone_from_slice(hash))
103    }
104}
105
106impl TryFrom<&[u8]> for HashValue {
107    type Error = BuckyError;
108    fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
109        if v.len() != 32 {
110            let msg = format!(
111                "HashValue expected bytes of length {} but it was {}",
112                32,
113                v.len()
114            );
115            error!("{}", msg);
116            return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg));
117        }
118
119        let ar: [u8; 32] = v.try_into().unwrap();
120        Ok(Self(GenericArray::from(ar)))
121    }
122}
123
124impl TryFrom<Vec<u8>> for HashValue {
125    type Error = BuckyError;
126    fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
127        if v.len() != 32 {
128            let msg = format!(
129                "HashValue expected bytes of length {} but it was {}",
130                32,
131                v.len()
132            );
133            error!("{}", msg);
134            return Err(BuckyError::new(BuckyErrorCode::InvalidData, msg));
135        }
136
137        let ar: [u8; 32] = v.try_into().unwrap();
138        Ok(Self(GenericArray::from(ar)))
139    }
140}
141
142impl HashValue {
143    pub fn as_slice(&self) -> &[u8] {
144        self.0.as_slice()
145    }
146
147    pub fn as_mut_slice(&mut self) -> &mut [u8] {
148        self.0.as_mut_slice()
149    }
150
151    pub fn len() -> usize {
152        HASH_VALUE_LEN
153    }
154
155    pub fn to_hex_string(&self) -> String {
156        hex::encode(self.0.as_slice())
157    }
158
159    pub fn from_hex_string(s: &str) -> BuckyResult<Self> {
160        let ret = hex::decode(s).map_err(|e| {
161            let msg = format!("invalid hash value hex string: {}, {}", s, e);
162            error!("{}", msg);
163            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
164        })?;
165
166        Self::clone_from_slice(&ret)
167    }
168
169    pub fn to_base58(&self) -> String {
170        self.0.to_base58()
171    }
172
173    pub fn from_base58(s: &str) -> BuckyResult<Self> {
174        let buf = s.from_base58().map_err(|e| {
175            let msg = format!("convert base58 str to hashvalue failed, str={}, {:?}", s, e);
176            error!("{}", msg);
177            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
178        })?;
179
180        if buf.len() != 32 {
181            let msg = format!(
182                "convert base58 str to hashvalue failed, len unmatch: str={}",
183                s
184            );
185            return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
186        }
187
188        Ok(Self::try_from(buf).unwrap())
189    }
190
191    pub fn clone_from_slice(hash: &[u8]) -> BuckyResult<Self> {
192        Self::try_from(hash)
193    }
194}
195
196impl std::fmt::Display for HashValue {
197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198        write!(f, "{}", self.to_hex_string())
199    }
200}
201
202impl FromStr for HashValue {
203    type Err = BuckyError;
204    fn from_str(s: &str) -> BuckyResult<Self> {
205        if s.len() == 64 {
206            Self::from_hex_string(s)
207        } else {
208            Self::from_base58(s)
209        }
210    }
211}
212
213impl Hash for HashValue {
214    fn hash<H: Hasher>(&self, state: &mut H) {
215        let mut buff = [0 as u8; 32];
216        let _ = self.raw_encode(buff.as_mut(), &None).unwrap();
217        state.write(buff.as_ref());
218    }
219}
220
221impl ProtobufTransform<HashValue> for Vec<u8> {
222    fn transform(value: HashValue) -> BuckyResult<Self> {
223        Ok(Vec::from(value.0.as_slice()))
224    }
225}
226
227impl ProtobufTransform<&HashValue> for Vec<u8> {
228    fn transform(value: &HashValue) -> BuckyResult<Self> {
229        Ok(Vec::from(value.0.as_slice()))
230    }
231}
232
233impl ProtobufTransform<Vec<u8>> for HashValue {
234    fn transform(value: Vec<u8>) -> BuckyResult<Self> {
235        if value.len() != HASH_VALUE_LEN {
236            return Err(BuckyError::new(
237                BuckyErrorCode::InvalidParam,
238                format!(
239                    "try convert from vec<u8> to named object id failed, invalid len {}",
240                    value.len()
241                ),
242            ));
243        }
244        let mut id = Self::default();
245        unsafe {
246            std::ptr::copy(value.as_ptr(), id.as_mut_slice().as_mut_ptr(), value.len());
247        }
248
249        Ok(id)
250    }
251}
252
253#[cfg(test)]
254mod test {
255    use std::str::FromStr;
256
257    use crate::*;
258
259    #[test]
260    fn test() {
261        let hash = hash_data("xxxx".as_bytes());
262        let hex_id = hash.to_hex_string();
263        let base58_id = hash.to_base58();
264
265        println!("{}, {}", hex_id, base58_id);
266
267        let ret = HashValue::from_str(&hex_id).unwrap();
268        let ret2 = HashValue::from_str(&base58_id).unwrap();
269
270        assert_eq!(ret, ret2);
271    }
272}