7c159343f8
新增功能: - rustls CryptoProvider:完整 rustls 0.23.x 支持 - SM3 Hash/Context trait 实现 - SM3 HMAC trait 实现 - SM4-GCM/CCM AEAD 密码套件 - SM2 ECDHE 密钥交换 - SM2 签名/验签算法 - SM3 流式 HMAC(HmacSm3) - SM2 SPKI DER 编码 - SM2 DEFAULT_ID 常量 文档更新: - README 依赖版本更新为 0.3 - CHANGELOG 添加 v0.3.0 变更记录 - SECURITY 更新版本支持表
7.6 KiB
7.6 KiB
libsmx
纯 Rust、#![no_std] 实现的中国商用密码算法库,全程常量时间操作。
| 算法 | 标准 | 说明 |
|---|---|---|
| SM2 | GB/T 32918.1-5-2016 | 椭圆曲线公钥密码 |
| SM3 | GB/T 32905-2016 | 密码杂凑算法(256 位) |
| SM4 | GB/T 32907-2016 | 分组密码(128 位密钥,ECB/CBC/CTR/GCM/CCM/XTS) |
| SM9 | GB/T 38635.1-2-2020 | 标识密码(BN256 双线性配对) |
| BLS | IETF RFC 9380 | BLS 签名与门限签名(BN256) |
| FPE | NIST SP 800-38G | 格式保留加密(FF1 类) |
特性
#![no_std]— 支持嵌入式、WASM 及裸机环境#![forbid(unsafe_code)]— 零unsafe块- 常量时间 — 所有涉密操作均使用
subtle原语,防时序侧信道 - 自动清零 — 私钥离开作用域后经由
zeroize自动清零 - SM4 S 盒抗侧信道 — 布尔电路位切片实现,无任何内存表查询,免疫缓存时序攻击
- SM2 完备加法公式 — 点加法使用无分支完备公式,杜绝特殊情况侧信道
快速开始
在 Cargo.toml 中添加依赖:
[dependencies]
libsmx = "0.3"
SM3 哈希
use libsmx::sm3::Sm3Hasher;
// 一次性哈希
let digest = Sm3Hasher::digest(b"abc");
assert_eq!(digest.len(), 32);
// 流式哈希
let mut h = Sm3Hasher::new();
h.update(b"ab");
h.update(b"c");
assert_eq!(h.finalize(), digest);
SM3 HMAC
use libsmx::sm3::hmac_sm3;
let mac = hmac_sm3(b"secret-key", b"message");
assert_eq!(mac.len(), 32);
SM2 签名 / 验签
use libsmx::sm2::{generate_keypair, get_z, get_e, sign, verify};
let mut rng = rand::rngs::OsRng;
// 生成密钥对
let (pri_key, pub_key) = generate_keypair(&mut rng);
// 签名:按 GB/T 32918.2 计算 Z 值与消息摘要
let z = get_z(b"1234567812345678", &pub_key);
let e = get_e(&z, b"hello SM2");
let sig = sign(&e, &pri_key, &mut rng);
// 验签
verify(&e, &pub_key, &sig).expect("签名有效");
SM2 加密 / 解密
use libsmx::sm2::{generate_keypair, sm2_encrypt, sm2_decrypt};
let mut rng = rand::rngs::OsRng;
let (pri_key, pub_key) = generate_keypair(&mut rng);
let plaintext = b"hello SM2 encrypt";
let ciphertext = sm2_encrypt(&pub_key, plaintext, &mut rng).unwrap();
let decrypted = sm2_decrypt(&pri_key, &ciphertext).unwrap();
assert_eq!(decrypted, plaintext);
SM4-GCM(AEAD 认证加密)
use libsmx::sm4::{sm4_encrypt_gcm, sm4_decrypt_gcm};
let key = [0u8; 16];
let nonce = [0u8; 12];
let aad = b"附加认证数据";
let plaintext = b"机密消息";
let (ciphertext, tag) = sm4_encrypt_gcm(&key, &nonce, aad, plaintext);
let decrypted = sm4_decrypt_gcm(&key, &nonce, aad, &ciphertext, &tag).unwrap();
assert_eq!(decrypted, plaintext);
SM4-CBC
use libsmx::sm4::{sm4_encrypt_cbc, sm4_decrypt_cbc};
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = [0u8; 32]; // 须为 16 字节对齐
let ciphertext = sm4_encrypt_cbc(&key, &iv, &plaintext);
let decrypted = sm4_decrypt_cbc(&key, &iv, &ciphertext);
assert_eq!(decrypted, plaintext);
SM9 标识签名 / 验签
use libsmx::sm9::{generate_sign_master_keypair, generate_sign_user_key};
use libsmx::sm9::{sm9_sign, sm9_verify};
let mut rng = rand::rngs::OsRng;
// 密钥生成中心(KGC)生成主密钥对
let (master_priv, sign_pub) = generate_sign_master_keypair(&mut rng);
// KGC 为用户标识派生签名私钥
let user_id = b"alice@example.com";
let user_key = generate_sign_user_key(&master_priv, user_id).unwrap();
// 用户签名
let msg = b"hello SM9";
let (h, s) = sm9_sign(msg, &user_key, &sign_pub, &mut rng).unwrap();
// 任意方可凭用户标识 + 主公钥验签
sm9_verify(msg, &h, &s, user_id, &sign_pub).unwrap();
SM9 标识加密 / 解密
use libsmx::sm9::{generate_enc_master_keypair, generate_enc_user_key};
use libsmx::sm9::{sm9_encrypt, sm9_decrypt};
let mut rng = rand::rngs::OsRng;
let (master_priv, enc_pub) = generate_enc_master_keypair(&mut rng);
let user_id = b"bob@example.com";
let user_key = generate_enc_user_key(&master_priv, user_id).unwrap();
let plaintext = b"机密消息";
let ciphertext = sm9_encrypt(user_id, plaintext, &enc_pub, &mut rng).unwrap();
let decrypted = sm9_decrypt(user_id, &ciphertext, &user_key).unwrap();
assert_eq!(decrypted, plaintext);
SM4 支持的工作模式
| 模式 | 加密 | 解密 |
|---|---|---|
| ECB | sm4_encrypt_ecb |
sm4_decrypt_ecb |
| CBC | sm4_encrypt_cbc |
sm4_decrypt_cbc |
| OFB | sm4_crypt_ofb |
sm4_crypt_ofb |
| CFB | sm4_encrypt_cfb |
sm4_decrypt_cfb |
| CTR | sm4_crypt_ctr |
sm4_crypt_ctr |
| GCM | sm4_encrypt_gcm |
sm4_decrypt_gcm |
| CCM | sm4_encrypt_ccm |
sm4_decrypt_ccm |
| XTS | sm4_encrypt_xts |
sm4_decrypt_xts |
Feature 开关
| Feature | 默认启用 | 说明 |
|---|---|---|
alloc |
是 | 启用返回 Vec 的 API(SM2/SM9 加解密、SM4 各模式) |
std |
否 | 启用 std::error::Error trait 实现及 rand_core/std 重导出 |
在无 alloc 的 no_std 环境中使用:
[dependencies]
libsmx = { version = "0.3", default-features = false }
无 alloc 时,SM3 哈希、SM3 HMAC、SM2 签名/验签、SM4 ECB 仍可用(固定大小数组 API)。
基准性能
测试环境:Linux x86_64(单核)。所有操作均为常量时间。
吞吐量
| 算法 | 数据量 | 耗时 | 吞吐量 |
|---|---|---|---|
| SM3 哈希 | 64 B | 349 ns | — |
| SM3 哈希 | 1 KiB | 2.80 µs | — |
| SM3 哈希 | 64 KiB | 167 µs | 374 MiB/s |
| SM4-ECB 加密 | 16 B | 1.14 µs | — |
| SM4-ECB 加密 | 1 KiB | 37.0 µs | — |
| SM4-ECB 加密 | 64 KiB | 2.32 ms | 27 MiB/s |
SM2(256 位椭圆曲线)
| 操作 | 耗时 |
|---|---|
| 密钥生成 | 221 µs |
| 签名 | 258 µs |
| 验签 | 316 µs |
| 加密 | 639 µs |
| 解密 | 417 µs |
SM9(BN256 双线性配对)
| 操作 | 耗时 |
|---|---|
| 主密钥生成 | 753 µs |
| 用户密钥派生 | 324 µs |
| 签名 | 3.44 ms |
| 验签 | 5.50 ms |
| 加密 | 4.68 ms |
| 解密 | 1.54 ms |
本地运行基准测试:
cargo bench
安全性
- 所有涉密操作均为常量时间(固定迭代次数 + 掩码选择,消除数据依赖分支)
- SM4 S 盒采用布尔电路位切片,无任何内存访问模式,免疫缓存时序攻击
- SM2 标量乘法使用 w=4 固定窗口预计算 + 常量时间表查找,消除分支
- SM2 点加法使用完备公式(Renes-Costello-Batina 2016),无退化情况分支
- 私钥类型均实现
ZeroizeOnDrop,离开作用域后自动清零内存 - GCM/CCM 认证标签采用常量时间比较,防止 Padding Oracle 攻击
免责声明:本库尚未经过独立第三方安全审计。如发现安全漏洞,请参阅 SECURITY.md 进行报告。
最低支持 Rust 版本(MSRV)
最低支持版本为 Rust 1.83.0。MSRV 提升视为次版本号变更。
许可证
Apache License, Version 2.0。详见 LICENSE。