spdb_sm2/
crypt.rs

1use base64::Engine;
2use base64::engine::general_purpose::STANDARD;
3use sha2::Digest;
4use smcrypto::{sm2, sm3, sm4};
5use crate::error::Sm2Error;
6
7/// # 生成密钥对
8///
9/// - 返回值:(私钥,公钥)
10pub fn generate_keypair() -> (String, String) {
11    let (sk, pk) = sm2::gen_keypair();
12    (sk, format!("04{}", pk))
13}
14
15/// # 加密
16///
17/// - data: 待加密数据
18/// - secret: 私钥( APP唯一秘钥:X_SPDB_CLIENT_SECRET, 秘钥有过期时间,注意存储方式 )
19pub fn encrypt(data: &str, secret: &str) -> Result<String, Sm2Error> {
20    let key = hex::decode(md5_key(secret))?;
21    let sm4_ecb = sm4::CryptSM4ECB::new(&key);
22    let encrypted = sm4_ecb.encrypt_ecb(data.as_bytes());
23    Ok(STANDARD.encode(hex::encode(encrypted)))
24}
25
26/// # 解密
27///
28/// - encrypt_data: 加密数据
29/// - secret: 私钥( APP唯一秘钥:X_SPDB_CLIENT_SECRET, 秘钥有过期时间,注意存储方式 )
30pub fn decrypt(encrypted: &str, secret: &str) -> Result<String, Sm2Error> {
31    let key = hex::decode(md5_key(secret))?;
32    let encrypt_data = hex::decode(STANDARD.decode(encrypted)?)?;
33    let sm4_ecb = sm4::CryptSM4ECB::new(&key);
34    let decrypted = sm4_ecb.decrypt_ecb(&encrypt_data);
35    Ok(String::from_utf8(decrypted)?)
36}
37
38/// # md5生成key
39///
40/// - 通过SHA-256生成X-SPDB-Client-Secret转16进制的摘要,得到sha256Secret
41/// - sm3做hash处理sha256Secret
42/// - 通过md5生成sm3Hex转16进制的32位摘要作为加解密key
43pub fn md5_key(secret: &str) -> String {
44    let mut sha2 = sha2::Sha256::new();
45    sha2.update(secret);
46    let hash = hex::encode(sha2.finalize());
47    let hash = sm3::sm3_hash(hash.as_bytes());
48    format!("{:x}", md5::compute(hash))
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_generate_keypair() {
57        let (sk, pk) = generate_keypair();
58        println!("sk: {}, pk: {}", sk, pk);
59    }
60
61    #[test]
62    fn test_encrypt() {
63        let msg = r#"hello world"#;
64        let secret = "ZTPkMS00ZNTP5NzPwNjAu";
65
66        // 加密
67        let encrypt_data = encrypt(msg, secret).unwrap();
68        assert_eq!(encrypt_data, "M2YyZWFlOTU4MzBkZTUxMGQyOTNjNmUzYzA1ODg2NjM=");
69
70        // 解密
71        let decrypt_data = decrypt(&encrypt_data, secret).unwrap();
72        assert_eq!(decrypt_data, msg);
73    }
74}