1use crate::HexUtil;
2use base64::{prelude::BASE64_STANDARD, DecodeError, Engine};
3use base64ct::LineEnding;
4use hmac::{Hmac, Mac};
5use rsa::{
6 pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey},
7 Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey,
8};
9use sha1::Sha1;
10use sha2::{Digest, Sha256};
11
12pub struct SecureUtil;
14
15impl SecureUtil {
16
17 pub fn rsa_random_key() -> (RsaPublicKey, RsaPrivateKey) {
28 let mut rng = rand::thread_rng(); let bits = 2048;
30 let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
32 let pub_key = RsaPublicKey::from(&priv_key);
34 (pub_key, priv_key)
35 }
36
37 pub fn rsa_encode(pub_key: &RsaPublicKey, bytes: &[u8]) -> Vec<u8> {
52 let mut rng = rand::thread_rng(); let enc_data = pub_key
54 .encrypt(&mut rng, Pkcs1v15Encrypt, bytes)
55 .expect("failed to encrypt");
56 enc_data
57 }
58
59 pub fn rsa_decode(priv_key: &RsaPrivateKey, enc_data: &[u8]) -> Vec<u8> {
71 let dec_data = priv_key
73 .decrypt(Pkcs1v15Encrypt, &enc_data)
74 .expect("failed to decrypt");
75 dec_data
76 }
77
78 pub fn rsa_private_key_to_pkcs8(priv_key: &RsaPrivateKey) -> String {
92 let x = priv_key.to_pkcs8_pem(LineEnding::LF).unwrap();
93 x.to_string()
94 }
95
96 pub fn rsa_public_key_to_pkcs8(pub_key: &RsaPublicKey) -> String {
110 let x = pub_key.to_public_key_pem(LineEnding::LF).unwrap();
111 x
112 }
113
114 pub fn rsa_private_key_from_pkcs8(pkcs8_string: &str) -> RsaPrivateKey {
127 let res = RsaPrivateKey::from_pkcs8_pem(pkcs8_string).unwrap();
129 res
130 }
131 pub fn rsa_public_key_from_pkcs8(pkcs8_string: &str) -> RsaPublicKey {
144 let res = RsaPublicKey::from_public_key_pem(pkcs8_string).unwrap();
145 res
146 }
147
148 pub fn sha256_string(bytes: &[u8]) -> String {
158 let result = Sha256::digest(bytes);
160 let result = &result[..];
161 HexUtil::to_hex(result)
163 }
164
165 pub fn md5_string(bytes: &[u8]) -> String {
166 let data_md5 = md5::compute(bytes);
168 let md5_string = format!("{:x}", data_md5);
170 md5_string
171 }
172
173 pub fn base64_encode(bytes: &[u8]) -> String {
181 BASE64_STANDARD.encode(bytes)
182 }
183
184 pub fn base64_decode(base64_str: &str) -> Result<Vec<u8>, DecodeError> {
199 BASE64_STANDARD.decode(base64_str)
200 }
201
202 pub fn hmac_sha1(data: &[u8], key: &str) -> Vec<u8> {
216 let key = key.as_bytes();
217 let mut hmac = Hmac::<Sha1>::new_from_slice(key).expect("HMAC can take key of any size");
219 hmac.update(data);
221 let result = hmac.finalize();
223 let hmac_bytes = result.into_bytes();
224 hmac_bytes.to_vec()
225 }
226
227 #[deprecated(note = "This function is deprecated, please use md5_string instead")]
244 pub fn to_md5_str(bytes: &[u8]) -> String {
245 Self::md5_string(bytes)
246 }
247
248 pub fn to_md5(bytes: &[u8]) -> Vec<u8> {
262 let data_md5 = md5::compute(bytes).to_vec();
264 data_md5
265 }
266}
267
268#[cfg(test)]
269mod tests {
270
271 use super::*;
272
273 #[test]
274 fn test_base64() {
275 let bytes = "hello, rust!".as_bytes();
276 let base64_str = SecureUtil::base64_encode(bytes);
277 println!("{}", base64_str);
278 }
279
280 #[test]
281 fn test_sha256() {
282 let sha256_string = SecureUtil::sha256_string(b"hello world");
283 println!("{}", sha256_string);
284 assert_eq!(
285 sha256_string,
286 "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
287 );
288 }
289
290 #[test]
291 fn test_rsa() {
292 let (pub_key, priv_key) = SecureUtil::rsa_random_key();
293 let pub_pkcs8_string = SecureUtil::rsa_public_key_to_pkcs8(&pub_key);
304 let priv_pkcs8_string = SecureUtil::rsa_private_key_to_pkcs8(&priv_key);
305
306 println!("pub_pkcs8_string => {}", pub_pkcs8_string);
307 println!("priv_pkcs8_string => {}", priv_pkcs8_string);
308
309 let pub_key = SecureUtil::rsa_public_key_from_pkcs8(&pub_pkcs8_string);
310 let priv_key = SecureUtil::rsa_private_key_from_pkcs8(&priv_pkcs8_string);
311
312 let data = "hello world";
313 let enc_data = SecureUtil::rsa_encode(&pub_key, data.as_bytes());
314 let dec_data = SecureUtil::rsa_decode(&priv_key, &enc_data);
315 println!("解密后{}", std::str::from_utf8(&dec_data).unwrap())
316 }
317
318 #[test]
319 fn test_rsa2() {
320 let pub_pkcs8_string = r#"-----BEGIN PUBLIC KEY-----
322MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6HvM5v45WMgCVCM7gLyU
323q8Xi0fqwvfge7JU9C6niP+liQHyMALr9n+IQm76v/CnvfAYYnDJ1VYhLpGkPKJ2Q
32456InmEOSAcx9vfgGQcPkkTSqpH/vDHEgPysFsBAGVBvXfBxa9FBF8afrAmdqM3DO
325ygnWWCaSux0js2hkQB0+wUk3Lkw9yxcT+cK9D7aNaB3vVjxRVvGOuFVMuTFzLjis
326/1INfltSSvnCB4QPxA/h9YUrZ26itw7yQgGIiUbNydLx3X+qvWCGVOnYwX9z6wsF
3274Ch3VwlYF+H/y0zyjIuCpdJDy80D36lErcwmRpJhMciT4lXnLMTyZvlN0UFl492L
3281wIDAQAB
329-----END PUBLIC KEY-----"#;
330 let priv_pkcs8_string = r#"-----BEGIN PRIVATE KEY-----
331MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDoe8zm/jlYyAJU
332IzuAvJSrxeLR+rC9+B7slT0LqeI/6WJAfIwAuv2f4hCbvq/8Ke98BhicMnVViEuk
333aQ8onZDnoieYQ5IBzH29+AZBw+SRNKqkf+8McSA/KwWwEAZUG9d8HFr0UEXxp+sC
334Z2ozcM7KCdZYJpK7HSOzaGRAHT7BSTcuTD3LFxP5wr0Pto1oHe9WPFFW8Y64VUy5
335MXMuOKz/Ug1+W1JK+cIHhA/ED+H1hStnbqK3DvJCAYiJRs3J0vHdf6q9YIZU6djB
336f3PrCwXgKHdXCVgX4f/LTPKMi4Kl0kPLzQPfqUStzCZGkmExyJPiVecsxPJm+U3R
337QWXj3YvXAgMBAAECggEATgrBDgnpVlRN89Cf+OdVQRR8v+BX1G2mc+TlSTUOLkY6
338JUup89TRrwpEaQPqL8wkCI5DVKvbl4rZWaeq3weFzTwx7ntAWDo9O7g24XzRDa2Q
339WwhXRuXy3UGj9yZp+XIfNBqQrdMEp8qmqXftvrbvtAL5YT4Ro550jZVNkfg/SMKX
340VptR+ZGpjSWsQfLM+Q8i9GEo3FV1dpT41Uea96cfX2siaaNNhCUM3MYgVDRjp7gj
341N9qxHOil3ZmvJU2yRLBlwgtLO+5fQzGET/yOeoXJ9iCeyAz5MNweljdra4wNtriV
3429ECYR/d7R3Bz2DtaJ5ALyD80AeJ+1TTrLxa4exkHgQKBgQD7UXolf0J5qFMEn7yw
3430F7LNANX/Fx6T/ayf7MJEegHK0UYDc9wjyIQDcIdgauvqImseq7R5sQQbnAHdsZW
344f6bzb+1HjoUZr2c43QY4sBRDW7wfibtlgtaiMpIophlBwbvdcJRW65s7Ox8Czcl/
345JNqMdjXjHLSiEFND6v8Of68LFQKBgQDs0IByiZm7qJQaR8WOoXku5C0XLA5zCLyh
346jXTqla5m0qAFZU8abrvBl/o0+nhmGsMkQR0ssvLJLX/a0t1IWBq+WmIDB3YC4IVU
347eKoHY7AlDhMa0dJ+nbuvrPQdFsRAfH9CRhtMmQPCVsx41AXsQa/OKwUQJuNvhwMg
348AioMthWGOwKBgG6tvTtSRjZJuPXqWzELMxQOfgJ7s0ZyfNSzhGdUKXkuxykGu/p4
349LqofRQO1naSodqktBlyOYn5SBKhk2Igzg5TmD/tZeqiLJMxYGmtQsDvR5JGHGK5l
3505pxb5R5dt/XLmi61a76z2BNHwCp98mU6F72QOb8hXzOYOPNKRLVf6fjZAoGBAJD2
3512YpDvT3o5jBoOwEiy4Hu38NNjtLQSFhEtYtccVQ0HwzuhUvS+VB67gk8QjOOsmIh
352EfDo4kJQffHAHwFIHabkwRbFnHIKatPYwYygc5VbVkqWotorSFcz8oNUCnLHQ0eY
353juGG0YxHggd9EtsbIrl8EC9g/tyoszsG2CLL28U9AoGAbZsQM7989SiKtLJ652uw
3546kaRWItbBdVKPr5galsBhbe/eEEE6ePbJTeLroQ31u/jGZJNSyUjwfBq9k1OBfpL
355s7+EjYm9Yg5hcep499C2eRyqoX+2j8am2CYYy3rDPj8lYt+u/99oUyAyGYVKAByb
356j27x2gyifpYUwtDqYU5DwDU=
357-----END PRIVATE KEY-----"#;
358
359 println!("pub_pkcs8_string => {}", pub_pkcs8_string);
360 println!("priv_pkcs8_string => {}", priv_pkcs8_string);
361
362 let pub_key = SecureUtil::rsa_public_key_from_pkcs8(&pub_pkcs8_string);
363 let priv_key = SecureUtil::rsa_private_key_from_pkcs8(&priv_pkcs8_string);
364
365 let data = "hello world";
366 let enc_data = SecureUtil::rsa_encode(&pub_key, data.as_bytes());
367 let dec_data = SecureUtil::rsa_decode(&priv_key, &enc_data);
368 println!("解密后{}", std::str::from_utf8(&dec_data).unwrap())
369 }
370}