encryption-rust 1.3.0

可插拔密码学组件库的 Rust 实现:在统一契约下提供对称加密、非对称加密、哈希、密钥派生(HKDF / PBKDF2 / Argon2 / scrypt)、签名(SM2 / ECDSA / Ed25519)、密钥协商(ECDH / X25519)与后量子密钥封装(ML-KEM),包含 AES/Sodium 与国密 SM2/SM3/SM4/ZUC 等实现
Documentation
# Copyright (c) 2026 erik <erik@erik.xyz> — https://erik.xyz

[package]
name = "encryption-rust"
version = "1.3.0"
edition = "2024"
rust-version = "1.88"
description = "可插拔密码学组件库的 Rust 实现:在统一契约下提供对称加密、非对称加密、哈希、密钥派生(HKDF / PBKDF2 / Argon2 / scrypt)、签名(SM2 / ECDSA / Ed25519)、密钥协商(ECDH / X25519)与后量子密钥封装(ML-KEM),包含 AES/Sodium 与国密 SM2/SM3/SM4/ZUC 等实现"
license = "MIT"
repository = "https://github.com/erikwang2013/encryption-rust"
authors = ["erik <erik@erik.xyz>"]
keywords = ["encryption", "cryptography", "sm2", "sm3", "sm4"]
categories = ["cryptography"]
readme = "README.md"

# 随包只发「读代码 / 用库」要用的东西。`docs/pet.svg` 绝不能排 —— src/pet.rs 用
# include_str! 内联它,排掉就编译不过(cargo package 会当场报错,不会静默漏发)。
exclude = [
    "CLAUDE.md",   # 仓库的 agent 配置,与使用者无关
    "AGENTS.md",
    "ruvector.db",
    ".swarm",
    ".claude-flow",
    ".claude",     # agent 工具链配置与 harness worktrees(1.2.0 起排除;此前误随包发布)
    ".agents",
]

[lib]
name = "encryption"

[package.metadata.docs.rs]
# docs.rs 默认只建 default feature —— 那样 8 个框架适配会从文档里消失。
# 全量构建,让 docs.rs 上能看到 Guard 与各框架的集成说明。
all-features = true

[dev-dependencies]
# 只给框架适配层的测试用(各自 feature 打开时才编译那些测试)。这些是
# dev-dependencies,不会进使用者的依赖图。
tokio = { version = "1", features = ["macros", "rt"] }
tower = { version = "0.5", features = ["util"] }
# warp 的 `test` 模块(warp::test::request)挂在它的 `test` feature 后面,
# 而 warp 的默认 feature 是空集。放在 dev-dependencies 里打开它,
# 使用者的构建不会因此多拿任何东西。
warp = { version = "0.4", features = ["test"] }
# 基准测试:对比「本库封装」与「裸 crate」的开销(benches/crypto_bench.rs)
criterion = "0.8"
# ml-kem 的 deterministic 只服务本仓库的 NIST ACVP 定值向量(KAT)测试:
# 它开启「从种子生成密钥对 / 确定性封装」接口。放这里后,cargo 只在构建本仓库
# 的测试目标时启用它(feature 并集只在这时候发生);使用者依赖本 crate 构建
# 生产目标时不会拿到这个确定性接口,生产依赖图里少一个可误用的面。
ml-kem = { version = "0.2.3", features = ["deterministic", "zeroize"] }

[[bench]]
name = "crypto_bench"
harness = false

[profile.release]
# 库的使用者不受影响(依赖不套用本 profile);仅对本仓库的 bench / examples 生效,
# 与兄弟项目的构建配置保持一致。
lto = true
codegen-units = 1

[dependencies]
# 加密 / 哈希 / KDF 统一走 RustCrypto「cipher 0.4 / digest 0.10」代际 —— 与兄弟项目
# encryptable-rust 在本机验证过的组合一致,避免与 cipher 0.5 代际混用时的 trait 不匹配。
# 例外:sm2 / sm3 系自身封装的第二栈(digest 0.11 / elliptic-curve 0.14 / signature 3 /
# hmac 0.13 / rfc6979 0.6 等)属其 crate 内部依赖、不外传 trait,可安全共存(见 sm2 行)。
zeroize = "1"                    # 密钥材质 Drop 清零(src/key.rs)
rand_core = { version = "0.6", features = ["getrandom"] }   # 随机 IV / nonce(OsRng)

# zeroize:让底层块密码的轮密钥 / 内部状态也在释放时清零(与 Key<N> 的 Drop
# 清零闭环;兄弟项目 encryptable-rust 同款做法)。
aes-gcm = { version = "0.10", features = ["zeroize"] }   # aes-256-gcm(认证加密,工厂默认算法)
aes = { version = "0.8", features = ["zeroize"] }        # aes-256-cbc-hmac 的底层块密码
aes-gcm-siv = "0.11.1"           # aes-256-gcm-siv(RFC 8452 误用稳健 AEAD;与 aead 0.5 同代)
cbc = { version = "0.1", features = ["alloc", "block-padding"] }  # CBC 模式 + PKCS#7
hmac = "0.12"                    # encrypt-then-MAC 与子密钥派生(HMAC-SHA256)
sha2 = "0.10"                    # SHA-256(HMAC / HKDF / PBKDF2 的底层)
# 哈希能力扩展(同 digest 0.10 代际;blake3 为独立实现,不走 digest trait)。
# blake2 0.10.6 没有 zeroize feature,故未开启(其内部状态清零依赖 digest 的
# CoreWrapper,不由本库控制)。
sha3 = "0.10.9"                  # SHA3-256 / SHA3-512(FIPS 202)
blake2 = "0.10.6"                # BLAKE2b-512 / BLAKE2s-256(RFC 7693)
blake3 = "1.8"                   # BLAKE3(默认 32 字节输出)
streebog = "0.10.2"              # Streebog-256 / Streebog-512(GOST R 34.11-2012)
belt-hash = "0.1.1"              # Belt-Hash(STB 34.101.31,256-bit)
chacha20poly1305 = "0.10"        # sodium-xchacha20(纯 Rust 实现,恒可用)
# chacha20poly1305 没有暴露 zeroize feature,其内部的 chacha20 / poly1305 通过
# 直接依赖翻转 feature(Cargo feature 取并集),让两器的状态同样清零。
chacha20 = { version = "0.9", features = ["zeroize"] }
poly1305 = { version = "0.8", features = ["zeroize"] }
hkdf = "0.12"                    # hkdf-sha256(RFC 5869)
pbkdf2 = "0.12"                  # pbkdf2-sha256
# 口令派生:argon2 的 zeroize feature 让内部状态(含 secret)在释放时清零,
# 与 Key<N> / 块密码的 Drop 清零闭环一致。两者均属 digest 0.10 代际,不引入新代际。
argon2 = { version = "0.5.3", features = ["zeroize"] }  # argon2id(RFC 9106)
scrypt = "0.11.0"                # scrypt(RFC 7914)
# Guard::from_env 解析 base64 主密钥;文档示例也用它把密文转文本
base64 = "0.22"

sm2 = { version = "0.14", default-features = false, features = [
    "arithmetic",        # 椭圆曲线运算(加解密的前提)
    "pke",               # 公钥加密(C1C3C2 / C1C2C3)
    "dsa",               # SM2DSA 签名 / 验签(1.2.0 起;带入 signature 3 / hmac 0.13 /
                         #              rfc6979 0.6 第二栈,均封在 sm2 内部不外传 trait)
    "alloc",             # encrypt/decrypt 返回 Vec<u8>
    "std",
    "precomputed-tables", # 基点预计算表,加速密钥生成与加解密
] }                  # 国密 SM2 非对称加解密
sm3 = "0.5"                      # 国密 SM3 哈希(与 sm2 内部同版本,避免重复依赖)
sm4 = { version = "0.5", features = ["zeroize"] }  # 国密 SM4-CBC(含 zeroize)
# SM4-GCM(src/guomi/sm4_gcm.rs)不自造 GCM:按 GB/T 38636-2020 附录 A 的
# GCM-AEK 手工组装 —— ghash 出通用哈希 GHASH,ctr 出 inc32 计数器流。
# 版本必须钉在 ghash 0.5 / ctr 0.9 代际:这正是 aes-gcm 0.10 内部使用的同款
# (universal-hash 0.5 / cipher 0.4),跨代际(0.6 / 0.10)会 trait 不匹配。
ghash = "0.5.1"                  # GHASH(GF(2^128) 通用哈希,GCM 的认证部分)
ctr = "0.9"                      # CTR 流(SM4-GCM 的机密性部分,inc32 计数器)
zuc = "0.4"                      # ZUC-128 流密码
# 以下五个同为 cipher 0.4 代际(见上方代际说明);有 zeroize feature 的一律打开,
# 与 aes / sm4 的处理保持一致。
camellia = { version = "0.1.0", features = ["zeroize"] }  # camellia-256-cbc-hmac 的底层块密码
aria = { version = "0.1.0", features = ["zeroize"] }      # aria-256-cbc-hmac 的底层块密码
threefish = { version = "0.5.2", features = ["zeroize"] }  # threefish-512-cbc-hmac(zeroize 为可选 feature,必须显式开启)
kuznyechik = { version = "0.8.2", features = ["zeroize"] }  # kuznyechik-256-cbc-hmac 的底层块密码
salsa20 = { version = "0.10.2", features = ["zeroize"] }  # salsa20 流密码(crate 默认 std)

# RSA-OAEP(SHA-256)非对称加解密。钉 0.9.x 线:digest 0.10 / rand_core 0.6 /
# signature <2.3,与本库其余依赖同代(0.10-rc 属新代际,勿升)。
# getrandom:显式打开 rand_core/getrandom,使 `rand_core::OsRng` 不依赖别处 feature 并集。
rsa = { version = "0.9.10", features = ["getrandom"] }
# SM2 的密钥生成与加密需要外部随机源;SysRng 即 rand_core 0.10 体系的操作系统随机
getrandom = { version = "0.4", features = ["sys_rng"] }

# 后量子 KEM(FIPS 203 ML-KEM)。代际钉死 0.2.3:0.3.x 会拉 sha3 0.11 新代际,
# 与上面「digest 0.10」的统一策略冲突(本 crate 自带 sha3 0.10.9 / rand_core 0.6)。
# zeroize:解析出的私钥与内部状态在 Drop 时清零(与上面各 zeroize feature 同款做法)。
# deterministic(从种子生成密钥对 / 确定性封装)只在 KAT 测试里用,见 dev-dependencies。
ml-kem = { version = "0.2.3", features = ["zeroize"] }

# ── 非对称能力扩充:ECDSA(P-256 / P-384 / secp256k1)/ Ed25519 / X25519 ────
# 统一钉在 RustCrypto「elliptic-curve 0.13 / signature 2 / sha2 0.10 / rand_core 0.6」
# 代际(与 cipher 0.4 代际同样的钉版理由:跨代际 trait 不匹配)。
p256 = { version = "0.13.2", features = ["ecdsa", "ecdh"] }   # ECDSA P-256(SHA-256)+ ECDH
p384 = { version = "0.13.1", features = ["ecdsa", "ecdh"] }   # ECDSA P-384(SHA-384)+ ECDH
k256 = { version = "0.13.4", features = ["ecdsa", "ecdh"] }   # ECDSA secp256k1(SHA-256)+ ECDH
ed25519-dalek = { version = "2.2", features = ["rand_core"] } # Ed25519 签名(RFC 8032)
x25519-dalek = { version = "2.0.1", features = [
    "static_secrets",   # 以持久私钥参与协商(本库 API 每次调用传入私钥)
    "zeroize",          # 临时私钥 / 共享秘密用完清零
    "getrandom",        # 系统 CSPRNG 生成私钥
] }                  # X25519 密钥协商(RFC 7748)

# ── 框架集成(全部 opt-in)────────────────────────────────────────────────
# 一律保留各框架的默认 feature:适配层要用的是它们的提取器 / 守卫 / 路由核心,
# 而那几块常常挂在默认 feature 上。反正这些依赖只在用户主动开启对应 feature
# 时才进图,且用户自己的框架依赖本来就会把默认 feature 拉进来(Cargo 取并集),
# 在这里关掉除了让 `cargo check --features <那一个>` 编译不过之外没有收益。
axum = { version = "0.8", optional = true }
actix-web = { version = "4", optional = true }
rocket = { version = "0.5", optional = true }
poem = { version = "3", optional = true }
salvo = { version = "1", optional = true }
warp = { version = "0.4", optional = true }
# bee-rust 的路由/上下文层
bee_router = { version = "1", optional = true, default-features = false }
# e-cat 的中间件层(其 feature 只有 cors / redis,默认不额外拉东西)
ecat-middleware = { version = "4", optional = true, default-features = false }
# e-cat 的 guard 要写成 tower Layer/Service,这两个 crate 提供那两个 trait
tower = { version = "0.5", optional = true }
http = { version = "1", optional = true }

[features]
default = []

# ── 框架集成 ────────────────────────────────────────────────────────────────
# 每个都是 opt-in:默认构建一个框架都不拉。它们做的事都一样 —— 把 Guard
# (src/guard.rs,框架无关)按各自框架的惯例注入请求上下文,仅此而已。
#
# 注意 Cargo 的 feature 是**并集**:同一个二进制里同时开两个框架特性时,
# 两个都会进依赖图。生产构建只开你真正在用的那个。
axum = ["dep:axum"]
actix-web = ["dep:actix-web"]
rocket = ["dep:rocket"]
poem = ["dep:poem"]
salvo = ["dep:salvo"]
warp = ["dep:warp"]
# bee-rust 的路由层(bee_router)直接吃 axum handler,状态也走 axum 的 State,
# 所以 axum 适配层在这里原样可用,顺带把它带上。
bee-rust = ["axum", "dep:bee_router"]
# e-cat 同样是 axum + tower 的组合:HTTP 传输层是 axum,中间件是 tower Layer。
# 它的 guard 形态是「往请求扩展里塞东西」,多需要 tower 与 http 两个 trait 来源。
ecat = ["axum", "dep:ecat-middleware", "dep:tower", "dep:http"]