cyfs_base/crypto/
aes.rs

1use crate::*;
2
3use aes::{Aes256, BlockCipher};
4use block_modes::block_padding::Pkcs7;
5use block_modes::{BlockMode, Cbc};
6use generic_array::typenum::{marker_traits::Unsigned, U48, U8};
7use generic_array::GenericArray;
8use sha2::Digest;
9use std::fmt;
10use std::fmt::{Display, Formatter};
11use std::hash::Hash;
12use std::str::FromStr;
13
14// aes key used to crypto data
15#[derive(Clone, Eq, PartialEq)]
16pub struct AesKey(GenericArray<u8, U48>);
17
18impl std::fmt::Debug for AesKey {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        write!(f, "{}", self.to_base58())
21    }
22}
23impl std::fmt::Display for AesKey {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "{}", self.to_base58())
26    }
27}
28
29impl From<GenericArray<u8, U48>> for AesKey {
30    fn from(aes_key: GenericArray<u8, U48>) -> Self {
31        Self(aes_key)
32    }
33}
34
35impl From<AesKey> for GenericArray<u8, U48> {
36    fn from(aes_key: AesKey) -> Self {
37        aes_key.0
38    }
39}
40
41impl AsRef<GenericArray<u8, U48>> for AesKey {
42    fn as_ref(&self) -> &GenericArray<u8, U48> {
43        &self.0
44    }
45}
46
47impl RawFixedBytes for AesKey {
48    fn raw_bytes() -> Option<usize> {
49        Some(U48::to_usize())
50    }
51}
52
53impl RawEncode for AesKey {
54    fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
55        Ok(U48::to_usize())
56    }
57    fn raw_encode<'a>(
58        &self,
59        buf: &'a mut [u8],
60        _purpose: &Option<RawEncodePurpose>,
61    ) -> BuckyResult<&'a mut [u8]> {
62        let bytes = Self::raw_bytes().unwrap();
63        if buf.len() < bytes {
64            let msg = format!(
65                "not enough buffer for encode AesKey, except={}, got={}",
66                bytes,
67                buf.len()
68            );
69            error!("{}", msg);
70
71            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
72        }
73        unsafe {
74            std::ptr::copy(self.0.as_slice().as_ptr(), buf.as_mut_ptr(), bytes);
75        }
76
77        Ok(&mut buf[bytes..])
78    }
79}
80
81impl<'de> RawDecode<'de> for AesKey {
82    fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> {
83        let bytes = Self::raw_bytes().unwrap();
84        if buf.len() < bytes {
85            let msg = format!(
86                "not enough buffer for decode AesKey, except={}, got={}",
87                bytes,
88                buf.len()
89            );
90            error!("{}", msg);
91
92            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
93        }
94        let mut hash = GenericArray::default();
95        unsafe {
96            std::ptr::copy(buf.as_ptr(), hash.as_mut_slice().as_mut_ptr(), bytes);
97        }
98        Ok((Self(hash), &buf[bytes..]))
99    }
100}
101
102impl From<&[u8; 48]> for AesKey {
103    fn from(v: &[u8; 48]) -> Self {
104        Self(GenericArray::clone_from_slice(v))
105    }
106}
107
108impl From<Vec<u8>> for AesKey {
109    fn from(v: Vec<u8>) -> Self {
110        let ar: [u8; 48] = v.try_into().unwrap_or_else(|v: Vec<u8>| {
111            panic!(
112                "AesKey expected a Vec of length {} but it was {}",
113                48,
114                v.len()
115            )
116        });
117
118        Self(GenericArray::clone_from_slice(&ar))
119    }
120}
121
122impl Default for AesKey {
123    fn default() -> Self {
124        Self(GenericArray::default())
125    }
126}
127
128impl AesKey {
129    pub fn len(&self) -> usize {
130        self.0.len()
131    }
132
133    pub fn to_base58(&self) -> String {
134        self.0.as_slice().to_base58()
135    }
136
137    pub fn from_base58(s: &str) -> BuckyResult<Self> {
138        let buf = s.from_base58().map_err(|e| {
139            let msg = format!(
140                "convert base58 str to AesKey buf failed, str={}, {:?}",
141                s, e
142            );
143            error!("{}", msg);
144            BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
145        })?;
146
147        if buf.len() != 48 {
148            let msg = format!(
149                "convert base58 str to AesKey failed, len unmatch: str={}",
150                s
151            );
152            return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
153        }
154
155        Ok(Self::from(buf))
156    }
157
158    pub fn proxy(n: u64) -> AesKey {
159        let mut key = [0u8; 48];
160        for i in 0..3 {
161            key[i * 8..(i + 1) * 8].copy_from_slice(&n.to_be_bytes());
162        }
163        for i in 3..6 {
164            let r = rand::random::<u64>();
165            key[i * 8..(i + 1) * 8].copy_from_slice(&r.to_be_bytes());
166        }
167        AesKey::from(&key)
168    }
169
170    pub fn random() -> AesKey {
171        let mut key = [0u8; 48];
172        for i in 0..6 {
173            let r = rand::random::<u64>();
174            key[i * 8..(i + 1) * 8].copy_from_slice(&r.to_be_bytes());
175        }
176        AesKey::from(&key)
177    }
178
179    pub fn mix_hash(&self, salt: Option<u64>) -> KeyMixHash {
180        let mut sha = sha2::Sha256::new();
181        sha.input(self.0.as_slice());
182        if let Some(salt) = salt {
183            sha.input(&salt.to_le_bytes());
184        }
185
186        let hash = sha.result();
187        let mut mix_hash =
188            GenericArray::from_slice(&hash.as_slice()[..KeyMixHash::raw_bytes().unwrap()]).clone();
189        mix_hash[0] = mix_hash[0] & 0x7f;
190        KeyMixHash(mix_hash)
191    }
192
193    pub fn padded_len(in_len: usize) -> usize {
194        let block_size = <Aes256 as BlockCipher>::BlockSize::to_usize();
195        block_size * ((in_len / block_size) + 1)
196    }
197
198    pub fn encrypt(
199        &self,
200        in_buf: &[u8],
201        out: &mut [u8],
202        in_len: usize,
203    ) -> Result<usize, BuckyError> {
204        out[..in_len].copy_from_slice(&in_buf[..in_len]);
205        self.inplace_encrypt(out, in_len)
206    }
207
208    pub fn decrypt(
209        &self,
210        in_buf: &[u8],
211        out: &mut [u8],
212        in_len: usize,
213    ) -> Result<usize, BuckyError> {
214        out[..in_len].copy_from_slice(&in_buf[..in_len]);
215        self.inplace_decrypt(out, in_len)
216    }
217
218    pub fn inplace_encrypt(&self, inout: &mut [u8], in_len: usize) -> Result<usize, BuckyError> {
219        // let iv: [u8;16] = [0;16];
220
221        // let buf_len = inout.len();
222        // let target_len = (in_len/16 + 1) * 16;
223        // if buf_len < target_len {
224        //     return Err(BuckyError::from(BuckyErrorCode::OpensslError));
225        // }
226        // let padding = (target_len - in_len) as u8;
227        // for i in in_len..target_len {
228        //     inout[i] = padding;
229        // }
230        let key = self.0.as_slice();
231        let cipher = Cbc::<Aes256, Pkcs7>::new_from_slices(&key[0..32], &key[32..]).unwrap();
232
233        match cipher.encrypt(inout, in_len) {
234            Ok(buf) => Ok(buf.len()),
235            Err(e) => {
236                let msg = format!(
237                    "AesKey::inplace_encrypt error, inout={}, in_len={}, {}",
238                    inout.len(),
239                    in_len,
240                    e
241                );
242                error!("{}", msg);
243
244                Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg))
245            }
246        }
247    }
248
249    pub fn inplace_decrypt(&self, inout: &mut [u8], in_len: usize) -> Result<usize, BuckyError> {
250        // let iv: [u8;16] = [0;16];
251
252        let key = self.0.as_slice();
253        let cipher = Cbc::<Aes256, Pkcs7>::new_from_slices(&key[0..32], &key[32..]).unwrap();
254        match cipher.decrypt(&mut inout[..in_len]) {
255            Ok(buf) => Ok(buf.len()),
256            Err(e) => {
257                let msg = format!(
258                    "AesKey::inplace_decrypt error, inout={}, in_len={}, {}",
259                    inout.len(),
260                    in_len,
261                    e
262                );
263                error!("{}", msg);
264
265                Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg))
266            }
267        }
268    }
269
270    pub fn as_slice(&self) -> &[u8] {
271        self.0.as_slice()
272    }
273
274    pub fn as_mut_slice(&mut self) -> &mut [u8] {
275        self.0.as_mut_slice()
276    }
277}
278
279impl FromStr for AesKey {
280    type Err = BuckyError;
281    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
282        Self::from_base58(s)
283    }
284}
285// aes key 的mixhash
286#[derive(Eq, PartialEq, Hash, Clone, Ord, PartialOrd, Debug)]
287pub struct KeyMixHash(GenericArray<u8, U8>);
288
289impl AsRef<GenericArray<u8, U8>> for KeyMixHash {
290    fn as_ref(&self) -> &GenericArray<u8, U8> {
291        &self.0
292    }
293}
294
295impl AsMut<GenericArray<u8, U8>> for KeyMixHash {
296    fn as_mut(&mut self) -> &mut GenericArray<u8, U8> {
297        &mut self.0
298    }
299}
300
301impl Display for KeyMixHash {
302    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
303        write!(f, "{}", hex::encode(self.0.as_slice()))
304    }
305}
306
307impl RawFixedBytes for KeyMixHash {
308    fn raw_bytes() -> Option<usize> {
309        Some(U8::to_usize())
310    }
311}
312
313impl RawEncode for KeyMixHash {
314    fn raw_measure(&self, _purpose: &Option<RawEncodePurpose>) -> BuckyResult<usize> {
315        Ok(U8::to_usize())
316    }
317    fn raw_encode<'a>(
318        &self,
319        buf: &'a mut [u8],
320        _purpose: &Option<RawEncodePurpose>,
321    ) -> BuckyResult<&'a mut [u8]> {
322        let bytes = Self::raw_bytes().unwrap();
323        if buf.len() < bytes {
324            let msg = format!(
325                "not enough buffer for encode KeyMixHash, except={}, got={}",
326                bytes,
327                buf.len()
328            );
329            error!("{}", msg);
330
331            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
332        }
333        unsafe {
334            std::ptr::copy(self.0.as_slice().as_ptr(), buf.as_mut_ptr(), bytes);
335        }
336
337        Ok(&mut buf[bytes..])
338    }
339}
340
341impl<'de> RawDecode<'de> for KeyMixHash {
342    fn raw_decode(buf: &'de [u8]) -> BuckyResult<(Self, &'de [u8])> {
343        let bytes = Self::raw_bytes().unwrap();
344        if buf.len() < bytes {
345            let msg = format!(
346                "not enough buffer for decode KeyMixHash, except={}, got={}",
347                bytes,
348                buf.len()
349            );
350            error!("{}", msg);
351
352            return Err(BuckyError::new(BuckyErrorCode::OutOfLimit, msg));
353        }
354        let mut hash = GenericArray::default();
355        unsafe {
356            std::ptr::copy(buf.as_ptr(), hash.as_mut_slice().as_mut_ptr(), bytes);
357        }
358        Ok((Self(hash), &buf[bytes..]))
359    }
360}
361
362#[cfg(test)]
363mod test_aes {
364    use super::AesKey;
365    use generic_array::typenum::U48;
366    use generic_array::GenericArray;
367
368    #[test]
369    fn test() {
370        let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0E";
371        let array = GenericArray::<u8, U48>::clone_from_slice(key);
372        let aes_key = AesKey(array);
373        let mut data: [u8; 128] = [30; 128];
374        let d = b"Some Crypto Text11111dsfasdfsdsdSome Crypto Text1111";
375        data[..d.len()].copy_from_slice(d);
376
377        assert!(aes_key.inplace_encrypt(data.as_mut(), d.len()).is_ok());
378        assert!(aes_key
379            .inplace_decrypt(data.as_mut(), (d.len() / 16 + 1) * 16)
380            .is_ok());
381        assert_eq!(
382            String::from_utf8(data[..d.len()].to_vec()),
383            String::from_utf8(d.to_vec())
384        );
385    }
386}