1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
use crate::HexUtil;
use base64::{prelude::BASE64_STANDARD, DecodeError, Engine};
use base64ct::LineEnding;
use hmac::{Hmac, Mac};
use rsa::{
pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey},
Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey,
};
use sha1::Sha1;
use sha2::{Digest, Sha256};
use soft_aes::aes::{aes_enc_ecb, aes_dec_ecb};
/// Encryption and decryption tools, which also include digest algorithms, etc.
pub struct SecureUtil;
impl SecureUtil {
/// 进行aes加密
///
/// 当前使用的是AES ECB Mode(简单模式),
/// 其他使用方式,见 https://crates.io/crates/soft-aes
///
/// # 参数说明
/// - data
/// - key 要求16位 或 24位
///
/// # 返回值
/// - 返回的数据是bytes经过hex编码之后的字符串
pub fn aes_encode(data: &str, key: &str) -> String {
let plaintext = data.as_bytes();
let key = key.as_bytes();
let padding = Some("PKCS7");
let encrypted = aes_enc_ecb(plaintext, key, padding).expect("Encryption failed");
HexUtil::to_hex(&encrypted)
}
/// 进行aes解密
///
/// # 参数说明
/// - data 是一个hex编码的字符串
/// - key 要求16位 或 24位
pub fn aes_decode(data: &str, key: &str) -> String {
let plaintext = HexUtil::to_bytes(data).unwrap();
let key = key.as_bytes();
let padding = Some("PKCS7");
let decrypted = aes_dec_ecb(&plaintext, key, padding).expect("Decryption failed");
String::from_utf8(decrypted).unwrap()
}
/// 生成RSA随机密钥对
///
/// 该函数使用系统随机数生成器创建一个2048位的RSA密钥对。
///
/// # 返回值
/// * `RsaPublicKey` - RSA公钥
/// * `RsaPrivateKey` - RSA私钥
///
/// # Panics
/// 当密钥生成失败时会panic
pub fn rsa_random_key() -> (RsaPublicKey, RsaPrivateKey) {
let mut rng = rand::thread_rng(); // rand@0.8
let bits = 2048;
// 生成RSA私钥
let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
// 从私钥导出公钥
let pub_key = RsaPublicKey::from(&priv_key);
(pub_key, priv_key)
}
/// 使用RSA公钥对字节数据进行加密
///
/// 该函数使用PKCS#1 v1.5填充方案对输入的字节数据进行RSA加密操作。
/// 加密过程中会使用随机数生成器来确保加密的安全性。
///
/// # 参数
/// * `pub_key` - RSA公钥引用,用于执行加密操作
/// * `bytes` - 需要加密的原始字节数据
///
/// # 返回值
/// 返回加密后的字节数据向量
///
/// # Panics
/// 当加密操作失败时会panic,例如输入数据过长等情况
pub fn rsa_encode(pub_key: &RsaPublicKey, bytes: &[u8]) -> Vec<u8> {
let mut rng = rand::thread_rng(); // rand@0.8
let enc_data = pub_key
.encrypt(&mut rng, Pkcs1v15Encrypt, bytes)
.expect("failed to encrypt");
enc_data
}
/// 使用RSA私钥解密数据
///
/// # 参数
/// * `priv_key` - RSA私钥引用,用于解密操作
/// * `enc_data` - 待解密的加密数据字节切片
///
/// # 返回值
/// 返回解密后的原始数据字节向量
///
/// # Panics
/// 当解密操作失败时会panic
pub fn rsa_decode(priv_key: &RsaPrivateKey, enc_data: &[u8]) -> Vec<u8> {
// 使用PKCS#1 v1.5填充方案进行RSA解密
let dec_data = priv_key
.decrypt(Pkcs1v15Encrypt, &enc_data)
.expect("failed to decrypt");
dec_data
}
/// 将RSA私钥转换为PKCS#8格式的PEM字符串
///
/// 该函数接收一个RSA私钥对象,将其序列化为PKCS#8格式的PEM编码字符串。
/// PKCS#8是一种标准的私钥存储格式,使用PEM编码便于文本传输和存储。
///
/// # 参数
/// * `priv_key` - 要转换的RSA私钥引用
///
/// # 返回值
/// 返回PKCS#8格式的PEM编码字符串
///
/// # Panics
/// 当私钥转换失败时会panic,因为使用了unwrap()
pub fn rsa_private_key_to_pkcs8(priv_key: &RsaPrivateKey) -> String {
let x = priv_key.to_pkcs8_pem(LineEnding::LF).unwrap();
x.to_string()
}
/// 将RSA公钥转换为PKCS#8格式的PEM字符串
///
/// 该函数接收一个RSA公钥对象,将其序列化为PEM格式的字符串,
/// 使用LF作为换行符
///
/// # 参数
/// * `pub_key` - 要转换的RSA公钥引用
///
/// # 返回值
/// 返回PEM格式的PKCS#8公钥字符串
///
/// # Panics
/// 当公钥转换失败时会panic(通过unwrap调用)
pub fn rsa_public_key_to_pkcs8(pub_key: &RsaPublicKey) -> String {
let x = pub_key.to_public_key_pem(LineEnding::LF).unwrap();
x
}
/// 从PKCS#8格式的PEM字符串中解析RSA私钥
///
/// 该函数接收一个PKCS#8格式的PEM编码字符串,将其解析为RsaPrivateKey对象。
///
/// # 参数
/// * `pkcs8_string` - 包含PKCS#8格式RSA私钥的PEM编码字符串
///
/// # 返回值
/// 返回解析得到的RsaPrivateKey对象
///
/// # Panics
/// 当PEM字符串格式不正确或无法解析时,函数会panic
pub fn rsa_private_key_from_pkcs8(pkcs8_string: &str) -> RsaPrivateKey {
// 从PKCS#8 PEM字符串解析RSA私钥
let res = RsaPrivateKey::from_pkcs8_pem(pkcs8_string).unwrap();
res
}
/// 从PKCS8格式的字符串创建RSA公钥
///
/// 该函数接收一个PKCS8格式的PEM编码字符串,将其解析为RSA公钥对象。
///
/// # 参数
/// * `pkcs8_string` - PKCS8格式的PEM编码字符串
///
/// # 返回值
/// * `RsaPublicKey` - 解析得到的RSA公钥对象
///
/// # 注意
/// 该函数使用unwrap()处理结果,如果解析失败会panic
pub fn rsa_public_key_from_pkcs8(pkcs8_string: &str) -> RsaPublicKey {
let res = RsaPublicKey::from_public_key_pem(pkcs8_string).unwrap();
res
}
/// 计算字节数组的SHA256哈希值并返回十六进制字符串
///
/// 固定生成256 位(32 字节) 的哈希值,以 64 位十六进制字符串形式展示
///
/// # 参数
/// * `bytes` - 需要计算哈希值的字节数组切片
///
/// # 返回值
/// 返回SHA256哈希值的十六进制字符串表示
pub fn sha256_string(bytes: &[u8]) -> String {
// 计算SHA256哈希值
let result = Sha256::digest(bytes);
let result = &result[..];
// 将哈希值转换为十六进制字符串
HexUtil::to_hex(result)
}
pub fn md5_string(bytes: &[u8]) -> String {
// 计算输入数据的MD5哈希值
let data_md5 = md5::compute(bytes);
// 将MD5哈希值格式化为十六进制字符串
let md5_string = format!("{:x}", data_md5);
md5_string
}
/// 对字节数组进行Base64编码
///
/// # 参数
/// * `bytes` - 需要编码的字节数组切片
///
/// # 返回值
/// 返回编码后的Base64字符串
pub fn base64_encode(bytes: &[u8]) -> String {
BASE64_STANDARD.encode(bytes)
}
/// 对Base64编码的字符串进行解码
///
/// # 参数
/// * `base64_str` - 需要解码的Base64编码字符串
///
/// # 返回值
/// * `Ok(Vec<u8>)` - 解码成功,返回解码后的字节数据
/// * `Err(DecodeError)` - 解码失败,返回错误信息
///
/// # 示例
/// ```
/// let decoded = base64_decode("SGVsbG8=").unwrap();
/// assert_eq!(decoded, b"Hello");
/// ```
pub fn base64_decode(base64_str: &str) -> Result<Vec<u8>, DecodeError> {
BASE64_STANDARD.decode(base64_str)
}
/// 使用HMAC-SHA1算法对数据进行签名
///
/// 该函数接收待签名的数据和密钥,使用HMAC-SHA1算法生成数字签名。
///
/// # 参数
/// * `data` - 待签名的字节数据切片
/// * `key` - 用于签名的密钥字符串
///
/// # 返回值
/// 返回HMAC-SHA1签名结果的字节向量
///
/// # Panics
/// 当密钥长度无效时会panic,但在实际中HMAC可以接受任意长度的密钥
pub fn hmac_sha1(data: &[u8], key: &str) -> Vec<u8> {
let key = key.as_bytes();
// 创建HMAC-SHA1实例并初始化
let mut hmac = Hmac::<Sha1>::new_from_slice(key).expect("HMAC can take key of any size");
// 更新HMAC状态,处理输入数据
hmac.update(data);
// 完成HMAC计算并获取结果
let result = hmac.finalize();
let hmac_bytes = result.into_bytes();
hmac_bytes.to_vec()
}
/// 将字节数组转换为MD5哈希字符串
///
/// 该函数接收一个字节切片,计算其MD5哈希值,并将结果格式化为十六进制字符串。
///
/// # 参数
/// * `bytes` - 需要计算MD5哈希的字节数据切片
///
/// # 返回值
/// 返回表示MD5哈希值的十六进制字符串
///
/// # 示例
/// ```
/// let data = b"hello world";
/// let md5_str = to_md5_str(data);
/// assert_eq!(md5_str, "5eb63bbbe01eeed093cb22bb8f5acdc3");
/// ```
#[deprecated(note = "This function is deprecated, please use md5_string instead")]
pub fn to_md5_str(bytes: &[u8]) -> String {
Self::md5_string(bytes)
}
/// 计算字节数组的MD5哈希值
///
/// # 参数
/// * `bytes` - 需要计算MD5哈希值的字节数组切片
///
/// # 返回值
/// 返回计算得到的MD5哈希值,以字节数组形式表示
///
/// # 示例
/// ```
/// let data = b"hello world";
/// let hash = to_md5(data);
/// ```
pub fn to_md5(bytes: &[u8]) -> Vec<u8> {
// 使用md5库计算输入数据的哈希值并转换为Vec<u8>
let data_md5 = md5::compute(bytes).to_vec();
data_md5
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aes() {
let origin = "Hello, this is TheoryDance!";
let key = "hello123hbjnk8h1";
let encode_string = SecureUtil::aes_encode(origin, key);
println!("1=>{}", encode_string);
let decode_string = SecureUtil::aes_decode(&encode_string, key);
println!("2=>{}", decode_string);
}
#[test]
fn test_base64() {
let bytes = "hello, rust!".as_bytes();
let base64_str = SecureUtil::base64_encode(bytes);
println!("{}", base64_str);
}
#[test]
fn test_sha256() {
let sha256_string = SecureUtil::sha256_string(b"hello world");
println!("{}", sha256_string);
assert_eq!(
sha256_string,
"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
);
}
#[test]
fn test_rsa() {
let (pub_key, priv_key) = SecureUtil::rsa_random_key();
// let data = "hello world";
// let enc_data = SecureUtil::rsa_encode(&pub_key, data.as_bytes());
// let dec_data = SecureUtil::rsa_decode(&priv_key, &enc_data);
// assert_eq!(data, std::str::from_utf8(&dec_data).unwrap());
// println!("{:?}", pub_key);
// let x = priv_key.to_pkcs8_pem(LineEnding::LF).unwrap();
// let y = (*x).clone();
// let x = x.to_string();
// println!("{}", y);
let pub_pkcs8_string = SecureUtil::rsa_public_key_to_pkcs8(&pub_key);
let priv_pkcs8_string = SecureUtil::rsa_private_key_to_pkcs8(&priv_key);
println!("pub_pkcs8_string => {}", pub_pkcs8_string);
println!("priv_pkcs8_string => {}", priv_pkcs8_string);
let pub_key = SecureUtil::rsa_public_key_from_pkcs8(&pub_pkcs8_string);
let priv_key = SecureUtil::rsa_private_key_from_pkcs8(&priv_pkcs8_string);
let data = "hello world";
let enc_data = SecureUtil::rsa_encode(&pub_key, data.as_bytes());
let dec_data = SecureUtil::rsa_decode(&priv_key, &enc_data);
println!("解密后{}", std::str::from_utf8(&dec_data).unwrap())
}
#[test]
fn test_rsa2() {
// https://www.metools.info/code/c80.html 生成RSA密钥对
let pub_pkcs8_string = r#"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6HvM5v45WMgCVCM7gLyU
q8Xi0fqwvfge7JU9C6niP+liQHyMALr9n+IQm76v/CnvfAYYnDJ1VYhLpGkPKJ2Q
56InmEOSAcx9vfgGQcPkkTSqpH/vDHEgPysFsBAGVBvXfBxa9FBF8afrAmdqM3DO
ygnWWCaSux0js2hkQB0+wUk3Lkw9yxcT+cK9D7aNaB3vVjxRVvGOuFVMuTFzLjis
/1INfltSSvnCB4QPxA/h9YUrZ26itw7yQgGIiUbNydLx3X+qvWCGVOnYwX9z6wsF
4Ch3VwlYF+H/y0zyjIuCpdJDy80D36lErcwmRpJhMciT4lXnLMTyZvlN0UFl492L
1wIDAQAB
-----END PUBLIC KEY-----"#;
let priv_pkcs8_string = r#"-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDoe8zm/jlYyAJU
IzuAvJSrxeLR+rC9+B7slT0LqeI/6WJAfIwAuv2f4hCbvq/8Ke98BhicMnVViEuk
aQ8onZDnoieYQ5IBzH29+AZBw+SRNKqkf+8McSA/KwWwEAZUG9d8HFr0UEXxp+sC
Z2ozcM7KCdZYJpK7HSOzaGRAHT7BSTcuTD3LFxP5wr0Pto1oHe9WPFFW8Y64VUy5
MXMuOKz/Ug1+W1JK+cIHhA/ED+H1hStnbqK3DvJCAYiJRs3J0vHdf6q9YIZU6djB
f3PrCwXgKHdXCVgX4f/LTPKMi4Kl0kPLzQPfqUStzCZGkmExyJPiVecsxPJm+U3R
QWXj3YvXAgMBAAECggEATgrBDgnpVlRN89Cf+OdVQRR8v+BX1G2mc+TlSTUOLkY6
JUup89TRrwpEaQPqL8wkCI5DVKvbl4rZWaeq3weFzTwx7ntAWDo9O7g24XzRDa2Q
WwhXRuXy3UGj9yZp+XIfNBqQrdMEp8qmqXftvrbvtAL5YT4Ro550jZVNkfg/SMKX
VptR+ZGpjSWsQfLM+Q8i9GEo3FV1dpT41Uea96cfX2siaaNNhCUM3MYgVDRjp7gj
N9qxHOil3ZmvJU2yRLBlwgtLO+5fQzGET/yOeoXJ9iCeyAz5MNweljdra4wNtriV
9ECYR/d7R3Bz2DtaJ5ALyD80AeJ+1TTrLxa4exkHgQKBgQD7UXolf0J5qFMEn7yw
0F7LNANX/Fx6T/ayf7MJEegHK0UYDc9wjyIQDcIdgauvqImseq7R5sQQbnAHdsZW
f6bzb+1HjoUZr2c43QY4sBRDW7wfibtlgtaiMpIophlBwbvdcJRW65s7Ox8Czcl/
JNqMdjXjHLSiEFND6v8Of68LFQKBgQDs0IByiZm7qJQaR8WOoXku5C0XLA5zCLyh
jXTqla5m0qAFZU8abrvBl/o0+nhmGsMkQR0ssvLJLX/a0t1IWBq+WmIDB3YC4IVU
eKoHY7AlDhMa0dJ+nbuvrPQdFsRAfH9CRhtMmQPCVsx41AXsQa/OKwUQJuNvhwMg
AioMthWGOwKBgG6tvTtSRjZJuPXqWzELMxQOfgJ7s0ZyfNSzhGdUKXkuxykGu/p4
LqofRQO1naSodqktBlyOYn5SBKhk2Igzg5TmD/tZeqiLJMxYGmtQsDvR5JGHGK5l
5pxb5R5dt/XLmi61a76z2BNHwCp98mU6F72QOb8hXzOYOPNKRLVf6fjZAoGBAJD2
2YpDvT3o5jBoOwEiy4Hu38NNjtLQSFhEtYtccVQ0HwzuhUvS+VB67gk8QjOOsmIh
EfDo4kJQffHAHwFIHabkwRbFnHIKatPYwYygc5VbVkqWotorSFcz8oNUCnLHQ0eY
juGG0YxHggd9EtsbIrl8EC9g/tyoszsG2CLL28U9AoGAbZsQM7989SiKtLJ652uw
6kaRWItbBdVKPr5galsBhbe/eEEE6ePbJTeLroQ31u/jGZJNSyUjwfBq9k1OBfpL
s7+EjYm9Yg5hcep499C2eRyqoX+2j8am2CYYy3rDPj8lYt+u/99oUyAyGYVKAByb
j27x2gyifpYUwtDqYU5DwDU=
-----END PRIVATE KEY-----"#;
println!("pub_pkcs8_string => {}", pub_pkcs8_string);
println!("priv_pkcs8_string => {}", priv_pkcs8_string);
let pub_key = SecureUtil::rsa_public_key_from_pkcs8(&pub_pkcs8_string);
let priv_key = SecureUtil::rsa_private_key_from_pkcs8(&priv_pkcs8_string);
let data = "hello world";
let enc_data = SecureUtil::rsa_encode(&pub_key, data.as_bytes());
let dec_data = SecureUtil::rsa_decode(&priv_key, &enc_data);
println!("解密后{}", std::str::from_utf8(&dec_data).unwrap())
}
}