准备发布 v0.1.0

- 添加 Apache-2.0 许可证
- 添加 CHANGELOG.md 变更日志
- 添加 SECURITY.md 安全策略
- 添加 README.zh-CN.md 中文文档
- 添加 rustfmt.toml 代码格式配置
- 添加 scripts/pre_publish_check.sh 发布检查脚本
- 更新 Cargo.toml 元数据(分类、关键词、文档链接)
- 完善 README.md 示例代码
- 优化 SM2/SM9 性能和测试覆盖率
This commit is contained in:
huangxt
2026-03-07 19:27:41 +08:00
parent bec7f277ce
commit 8ad52ecac0
23 changed files with 1275 additions and 361 deletions
+209
View File
@@ -0,0 +1,209 @@
# libsmx
[![Crates.io](https://img.shields.io/crates/v/libsmx.svg)](https://crates.io/crates/libsmx)
[![docs.rs](https://img.shields.io/docsrs/libsmx)](https://docs.rs/libsmx)
[![License](https://img.shields.io/crates/l/libsmx.svg)](LICENSE)
[![MSRV](https://img.shields.io/badge/MSRV-1.72.0-blue.svg)](https://blog.rust-lang.org/2023/08/24/Rust-1.72.0.html)
纯 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 双线性配对) |
## 特性
- **`#![no_std]`** — 支持嵌入式、WASM 及裸机环境
- **`#![forbid(unsafe_code)]`** — 零 `unsafe`
- **常量时间** — 所有涉密操作均使用 [`subtle`](https://docs.rs/subtle) 原语,防时序侧信道
- **自动清零** — 私钥离开作用域后经由 [`zeroize`](https://docs.rs/zeroize) 自动清零
- **SM4 S 盒抗侧信道** — 布尔电路位切片实现,无任何内存表查询,免疫缓存时序攻击
- **SM2 完备加法公式** — 点加法使用无分支完备公式,杜绝特殊情况侧信道
## 快速开始
`Cargo.toml` 中添加依赖:
```toml
[dependencies]
libsmx = "0.3"
```
### SM3 哈希
```rust
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
```rust
use libsmx::sm3::hmac_sm3;
let mac = hmac_sm3(b"secret-key", b"message");
assert_eq!(mac.len(), 32);
```
### SM2 签名 / 验签
```rust
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 加密 / 解密
```rust
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-GCMAEAD 认证加密)
```rust
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
```rust
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 标识签名 / 验签
```rust
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 标识加密 / 解密
```rust
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` 的 APISM2/SM9 加解密、SM4 各模式) |
| `std` | 否 | 启用 `std::error::Error` trait 实现及 `rand_core/std` 重导出 |
在无 `alloc``no_std` 环境中使用:
```toml
[dependencies]
libsmx = { version = "0.3", default-features = false }
```
`alloc` 时,SM3 哈希、SM3 HMAC、SM2 签名/验签、SM4 ECB 仍可用(固定大小数组 API)。
## 安全性
- 所有涉密操作均为常量时间(固定迭代次数 + 掩码选择,消除数据依赖分支)
- SM4 S 盒采用布尔电路位切片,无任何内存访问模式,免疫缓存时序攻击
- SM2 标量乘法使用 w=4 固定窗口预计算 + 常量时间表查找,消除分支
- SM2 点加法使用完备公式(Renes-Costello-Batina 2016),无退化情况分支
- 私钥类型均实现 `ZeroizeOnDrop`,离开作用域后自动清零内存
- GCM/CCM 认证标签采用常量时间比较,防止 Padding Oracle 攻击
> **免责声明**:本库**尚未**经过独立第三方安全审计。如发现安全漏洞,请参阅 [SECURITY.md](SECURITY.md) 进行报告。
## 最低支持 Rust 版本(MSRV
最低支持版本为 **Rust 1.72.0**。MSRV 提升视为次版本号变更。
## 许可证
Apache License, Version 2.0。详见 [LICENSE](LICENSE)。