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#[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 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 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#[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}