EffortlessMetrics/uselesskey-swarm

GitHub: EffortlessMetrics/uselesskey-swarm

一个 Rust 测试 fixture 工厂,用于在开发和 CI 中确定性生成加密密钥与证书的测试数据,避免将密钥文件提交到版本库。

Stars: 0 | Forks: 0

uselesskey

CI Codecov ripr+ scanner-safe fixtures

GitHub release crates.io downloads docs.rs

MSRV License: MIT OR Apache-2.0

生成确定性的 auth、TLS、webhook、token 和测试 fixture,并提供仅包含元数据的审计回执。

`uselesskey` 是一个**测试 fixture 工厂**,而不是一个加密库。它生成确定性的 auth、TLS、webhook、token 和测试 fixture;默认将生成的原始材料排除在 git 之外;审计生成的内容;并明确界定证明边界。 ## 从这里开始 首先选择你的任务;仓库的证明机制可以在你需要时通过链接找到。 | 我需要... | 从这里开始 | 复制此项 | | --- | --- | --- | | 编写 Rust 测试 | facade crate | `uselesskey = { version = "0.9.1", features = ["rsa"] }` | | 测试 webhook 签名 | webhook profile | `uselesskey bundle --profile webhook --out target/uselesskey-webhook` | | 测试 TLS 链 | TLS profile | `uselesskey bundle --profile tls --out target/uselesskey-tls` | | 测试 OIDC/JWT 负面用例 | OIDC profile | `uselesskey bundle --profile oidc --out target/uselesskey-oidc` | | 仅测试 token 的 Rust 代码 | facade token feature | `uselesskey = { version = "0.9.1", default-features = false, features = ["token"] }` | | 安装 CI fixture | 已安装的 CLI bundle | `uselesskey bundle --profile scanner-safe --out target/uselesskey-bundle` | | 测试负向验证器路径 | contract pack | `uselesskey bundle --profile oidc --out target/uselesskey-oidc` | | 审查 bundle 证据 | verify + inspect + audit | `uselesskey inspect-bundle target/uselesskey-webhook` | | 保持运行时材料可丢弃 | `target/` 输出 | `uselesskey audit-bundle target/uselesskey-webhook --ci --out target/uselesskey-webhook-audit` | | 上传仅包含元数据的回执 | CI artifact 步骤 | `uses: actions/upload-artifact@v7` | | 从 checkout 证明仓库的公开声明 | repo verification pack | `cargo xtask verification-pack --out target/uselesskey-verification` | 当你需要在此工作区之外使用 fixture bundle 时,请安装 CLI: ``` cargo install uselesskey-cli --version 0.9.1 --locked uselesskey doctor uselesskey profiles uselesskey bundle --profile webhook --explain ``` 生成、验证、检查和审计 webhook bundle: ``` uselesskey bundle --profile webhook --out target/uselesskey-webhook uselesskey verify-bundle target/uselesskey-webhook uselesskey inspect-bundle target/uselesskey-webhook uselesskey audit-bundle target/uselesskey-webhook --ci --out target/uselesskey-webhook-audit ``` 当审计是下游 CI 门禁的一部分时,请使用 `--ci --expect-profile --policy strict --out `: ``` uselesskey audit-bundle target/uselesskey-webhook --ci --expect-profile webhook --policy strict --out target/uselesskey-webhook-audit ``` 对于 GitHub Actions,请仅上传包含元数据的审计回执: ``` - name: Upload uselesskey audit receipts uses: actions/upload-artifact@v7 if: always() with: name: uselesskey-webhook-audit path: | target/uselesskey-webhook-audit/bundle-audit.json target/uselesskey-webhook-audit/bundle-audit.md if-no-files-found: error ``` Rust 测试作者从 facade crate 开始: ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } ``` 然后在运行时生成确定性 fixture: ``` use uselesskey::{Factory, RsaFactoryExt, RsaSpec}; let fx = Factory::deterministic_from_str("test-seed"); let key = fx.rsa("issuer", RsaSpec::rs256()); let pkcs8_pem = key.private_key_pkcs8_pem(); ``` 审查者和维护者的证明是仓库本地的。从 checkout 中,公开声明可以被打包为仅包含元数据的证明 bundle: ``` cargo xtask verification-pack --out target/uselesskey-verification ``` 这不能证明的内容: - 生产密钥生成、密钥保管或机密管理; - 生产 PKI、提供者兼容性或 webhook 传递语义; - 提交生成的 secret 形状 payload 的权限; - 下游验证器的正确性; - 仓库的公开声明,除非你运行了仓库本地的证明命令。 任务路由请参阅 [docs/how-to/start-here.md](docs/how-to/start-here.md),验证/审计循环请参阅 [docs/how-to/verify-a-fixture-bundle.md](docs/how-to/verify-a-fixture-bundle.md),或者完整的证明索引请参阅 [docs/status/PUBLIC_CLAIMS.md](docs/status/PUBLIC_CLAIMS.md)。 对于下游形态的干净项目,请使用[外部示例索引](examples/external/README.md)。 ## 为什么会有这个项目 `uselesskey` 是一个**测试 fixture 层**,而不是运行时加密服务。 当你需要真实的加密 fixture 但又不想提交 PEM/DER/JWK 文件时,请使用它。 它的存在是为了消除这种测试摩擦: - 扫描器会检查 PR 中的每一次提交,而不仅仅是最终的差异 - 看起来像伪造的密钥仍然会触发策略、推送保护和审查摩擦 `uselesskey` 用一个 dev-dependency 和运行时生成取代了安全例外 + 路径忽略 + fixture 目录。 ## 它解决了什么问题 如果没有这一层,团队通常会采用以下方法之一: | 方法 | 问题 | |----------|----------| | 提交 PEM/DER 文件 | 触发扫描器和推送保护 | | 在测试中临时生成密钥 | 重复的样板代码,RSA 速度慢,没有共享的确定性 | | 直接使用原始加密 crate | 你仍然需要自己组装 PEM/DER/JWK/X.509 形状 | | 直接使用 `rcgen` 或其他运行时 crate | 很有用,但并不以 fixture 的人体工程学、确定性或负面用例为中心 | `uselesskey` 是专门为**测试工件**构建的。 ## 你能得到什么 ### Fixture 家族 - RSA (2048, 3072, 4096) - ECDSA (P-256, P-384) - Ed25519 - HMAC (HS256, HS384, HS512) - OpenPGP (RSA 2048/3072, Ed25519) - Token fixture(API key、bearer、OAuth access-token / JWT 形状) - X.509 自签名证书和证书链 ### 输出形状 - PKCS#8 PEM/DER - SPKI PEM/DER - OpenPGP armored 和二进制 keyblock - JWK / JWKS - 用于基于路径的 API 的临时文件 - X.509 叶子和链,以及负向变体 ### 负面工件 - 损坏的 PEM - 截断的 DER - 不匹配的密钥对 - 过期/吊销/主机名不匹配/未知 CA 的证书 ## 首先选择通道 从能保持测试语义且开销最小的通道开始。 | 我需要 | 推荐通道 | 原因 | |----------|----------|----------| | 仅需熵 / scanner 形状 | `uselesskey-entropy` 或 facade `features = ["entropy"]` | 确定性字节,没有密钥生成的负担 | | 仅需 JWT / bearer / API-token 形状 | `uselesskey-token` 或 facade `features = ["token"]` | token 形状的 fixture,无需引入 RSA/X.509 | | 有效的运行时加密语义 | 叶子 crate,如 `uselesskey-rsa`, `uselesskey-x509`, `uselesskey-ssh` | 真实的 PKCS#8/JWK/X.509/SSH fixture 行为 | | 构建时物化的 fixture | `uselesskey-cli materialize` + `verify` | 干净的、仅限形状的 `OUT_DIR` / `include_bytes!` 工作流,RSA 物化作为显式 opt-in | | 可重现的 fixture bundle + 交接 | `uselesskey-cli bundle` + `verify-bundle` + `inspect-bundle` + `export` | 确定性的、对扫描器安全的 fixture、manifest 和回执 bundle;无需提交真实 secret 的 Kubernetes/Vault payload 交接 | 功能选择请参阅 [docs/how-to/choose-features.md](docs/how-to/choose-features.md)。 在决定使用 entropy、token、semantic 还是物化的 fixture 工作流时,请使用 [docs/how-to/choose-lane.md](docs/how-to/choose-lane.md)。 当前的本地成本和咨询回执请参见 [docs/reference/dependency-economics.md](docs/reference/dependency-economics.md) 和 [docs/reference/audit-surface.md](docs/reference/audit-surface.md)。 ## 选择最小的功能集 `uselesskey` facade 具有一个空的默认功能集。只需启用你需要的 fixture 家族。 常见的起点: ``` # 仅有 Entropy 的 fixtures [dev-dependencies] uselesskey = { version = "0.9.1", default-features = false, features = ["entropy"] } ``` ``` # RSA fixtures [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } ``` ``` # 仅有 Token 的 fixtures,不引入 RSA/X.509 [dev-dependencies] uselesskey = { version = "0.9.1", default-features = false, features = ["token"] } ``` ``` # RSA + JWK/JWKS [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa", "jwk"] } ``` ``` # X.509 fixtures [dev-dependencies] uselesskey = { version = "0.9.1", features = ["x509"] } ``` 以下物化命令是仓库 checkout 示例。安装了 CLI 的用户可以运行相同的子命令,如 `uselesskey materialize ...` 和 `uselesskey verify ...`。 ``` # Build-time 物化,仅限形状的通用 lane cargo run -p uselesskey-cli -- materialize --manifest crates/materialize-shape-buildrs-example/uselesskey-fixtures.toml --out-dir target/tmp-fixtures cargo run -p uselesskey-cli -- verify --manifest crates/materialize-shape-buildrs-example/uselesskey-fixtures.toml --out-dir target/tmp-fixtures ``` 对于 `build.rs` 使用者: ``` # 通用的仅限形状的 Build-time 路径 [build-dependencies] uselesskey-cli = { version = "0.9.1", default-features = false } ``` ``` # 专用的 RSA PKCS#8 Build-time 路径 [build-dependencies] uselesskey-cli = { version = "0.9.1", default-features = false, features = ["rsa-materialize"] } ``` 为了方便,请使用 facade。仅当编译时最小化足够重要,足以证明更严格的 API 是合理的时候,才依赖叶子 crate。 如果你不确定从哪些 flag 开始,请从 [docs/how-to/choose-features.md](docs/how-to/choose-features.md) 开始。 对于下游 bot/reviewer 策略,请使用 [docs/how-to/downstream-fixture-policy.md](docs/how-to/downstream-fixture-policy.md)。 有关 crate 级别的支持合约(stable/incubating/experimental、受众和发布状态),请参阅 [docs/reference/support-matrix.md](docs/reference/support-matrix.md)。 ## 快速开始 ``` use uselesskey::{Factory, RsaFactoryExt, RsaSpec}; // Random mode: different keys every run let fx = Factory::random(); // Deterministic mode: stable output for a seed string let fx = Factory::deterministic_from_str("my-test-seed"); // Or use env-var seed with random fallback let fx = Factory::deterministic_from_env("USELESSKEY_SEED") .unwrap_or_else(|_| Factory::random()); let rsa = fx.rsa("issuer", RsaSpec::rs256()); let pkcs8_pem = rsa.private_key_pkcs8_pem(); let spki_der = rsa.public_key_spki_der(); ``` 核心形状始终是: ``` (mode, domain, label, spec, variant) -> artifact ``` 这使得 fixture 在确定性模式下保持稳定,并且在两种模式下都可缓存。 ## 常见代码片段的功能提醒 - `rsa` 用于 PEM/DER、临时文件和负向密钥示例 - `rsa` + `jwk` 用于 `public_jwk()` / `public_jwks()` - `x509` 用于证书、rustls 和 tonic 示例 - `token` 仅用于 token 形状的 fixture - `pgp` 用于 armored/二进制 OpenPGP fixture ## 依赖代码片段提醒 依赖代码片段: - **快速开始 (RSA)** [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } - **仅限 Token** [dev-dependencies] uselesskey = { version = "0.9.1", default-features = false, features = ["token"] } - **JWT/JWK** [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa", "jwk"] } - **X.509 + rustls** [dev-dependencies] uselesskey = { version = "0.9.1", features = ["x509"] } uselesskey-rustls = { version = "0.9.1", features = ["tls-config", "rustls-ring"] } - **jsonwebtoken 适配器** [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa", "ecdsa", "ed25519", "hmac"] } uselesskey-jsonwebtoken = { version = "0.9.1", features = ["all"] } ### JWK / JWKS 需要 `features = ["rsa", "jwk"]`。 ``` use uselesskey::{Factory, RsaSpec, RsaFactoryExt}; let fx = Factory::random(); let rsa = fx.rsa("issuer", RsaSpec::rs256()); let jwk = rsa.public_jwk(); let jwks = rsa.public_jwks(); ``` ### 临时文件 ``` use uselesskey::{Factory, RsaSpec, RsaFactoryExt}; let fx = Factory::random(); let rsa = fx.rsa("server", RsaSpec::rs256()); let keyfile = rsa.write_private_key_pkcs8_pem().unwrap(); assert!(keyfile.path().exists()); ``` ### X.509 证书 需要 `features = ["x509"]`。 用于简单 TLS 测试的自签名证书: ``` use uselesskey::{Factory, X509FactoryExt, X509Spec}; let fx = Factory::random(); let cert = fx.x509_self_signed("my-service", X509Spec::self_signed("test.example.com")); let cert_pem = cert.cert_pem(); let key_pem = cert.private_key_pkcs8_pem(); ``` 三级链(root intermediate leaf): ``` use uselesskey::{Factory, X509FactoryExt, ChainSpec}; let fx = Factory::random(); let chain = fx.x509_chain("my-service", ChainSpec::new("test.example.com")); // Standard TLS server chain: leaf + intermediate, no root let chain_pem = chain.chain_pem(); // Individual artifacts for custom setups let root_pem = chain.root_cert_pem(); let leaf_key = chain.leaf_private_key_pkcs8_pem(); ``` ### X.509 负面 fixture 这些用于错误路径测试,而不是验证逻辑。 ``` use uselesskey::{Factory, X509FactoryExt, ChainSpec}; let fx = Factory::random(); let chain = fx.x509_chain("my-service", ChainSpec::new("test.example.com")); // Expired leaf certificate let expired = chain.expired_leaf(); // Hostname mismatch (SAN doesn't match expected hostname) let wrong_host = chain.hostname_mismatch("wrong.example.com"); // Signed by an unknown CA (not in your trust store) let unknown = chain.unknown_ca(); // Revoked leaf with CRL signed by the intermediate CA let revoked = chain.revoked_leaf(); let crl_pem = revoked.crl_pem().expect("CRL present for revoked variant"); ``` ### 负面 fixture(密钥) ``` use uselesskey::{Factory, RsaSpec, RsaFactoryExt}; use uselesskey::negative::CorruptPem; let fx = Factory::random(); let rsa = fx.rsa("issuer", RsaSpec::rs256()); let bad_pem = rsa.private_key_pkcs8_pem_corrupt(CorruptPem::BadBase64); let truncated = rsa.private_key_pkcs8_der_truncated(32); let mismatched_pub = rsa.mismatched_public_key_spki_der(); ``` ### Token fixture Token fixture 是**工件形状**,而不是 auth 框架。它们的存在是为了让测试可以使用看起来真实的 token 值,而无需提交 blob。 ``` use uselesskey::{Factory, TokenFactoryExt, TokenSpec}; let fx = Factory::random(); let api_key = fx.token("billing", TokenSpec::api_key()); let bearer = fx.token("gateway", TokenSpec::bearer()); let oauth = fx.token("issuer", TokenSpec::oauth_access_token()); assert!(api_key.value().starts_with("uk_test_")); assert!(bearer.authorization_header().starts_with("Bearer ")); assert_eq!(oauth.value().split('.').count(), 3); ``` ## 对扫描器安全的 bundle 和导出 `uselesskey-cli` bundle 工作流会生成一个确定性的 fixture 目录、一个 manifest 和每个工件的回执,下游测试可以验证、检查这些内容,并将其交接给 Kubernetes 或 Vault,而无需提交真实的 secret 材料。 ``` # 生成 scanner 安全的 fixture bundle(默认 profile) uselesskey bundle --profile scanner-safe --out target/uselesskey-bundle # 根据记录的 manifest 和 receipts 验证 bundle uselesskey verify-bundle target/uselesskey-bundle # 打印人类可读的摘要,而不暴露 fixture payloads uselesskey inspect-bundle target/uselesskey-bundle # 从已验证的 bundle 渲染 Kubernetes / Vault payloads uselesskey export k8s \ --bundle-dir target/uselesskey-bundle \ --name uselesskey-fixtures \ --namespace tests \ --out target/uselesskey-bundle/secret.yaml uselesskey export vault-kv-json \ --bundle-dir target/uselesskey-bundle \ --out target/uselesskey-bundle/kv-v2.json ``` `oidc` profile 会生成一个 OIDC/JWKS contract pack,其中包含有效的 JWKS 和 JWT 形状的 fixture,以及重复的 `kid`、缺失的 `kid`、`alg: none` 和错误受众的负向变体: ``` uselesskey bundle --profile oidc --out target/uselesskey-oidc ``` 有关参考 manifest、回执和 payload 形状,请参阅 [`examples/scanner-safe-bundle/README.md`](examples/scanner-safe-bundle/README.md)。有关 OIDC/JWT 验证器测试方案,请参阅 [`docs/how-to/test-oidc-jwks-validation.md`](docs/how-to/test-oidc-jwks-validation.md) 和 [`docs/how-to/test-jwt-negative-validation.md`](docs/how-to/test-jwt-negative-validation.md)。 有关对扫描器安全的、TLS、OIDC/JWKS 和 webhook profile 的任务优先列表, 请参阅 [`docs/contract-packs/README.md`](docs/contract-packs/README.md)。 ## 适配器 crate 适配器 crate 是独立的包,而不是 facade feature。这使得集成版本控制变得明确,并避免了将 facade 与每个下游生态系统类型耦合在一起。 当你希望直接从 fixture 工件返回**原生第三方库类型**时,请使用它们。 ### TLS 配置构建器 (`uselesskey-rustls`) 通过 `tls-config` feature,一步构建 rustls 配置: ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["x509"] } uselesskey-rustls = { version = "0.9.1", features = ["tls-config", "rustls-ring"] } ``` ### ring 签名密钥 (`uselesskey-ring`) ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } uselesskey-ring = { version = "0.9.1", features = ["all"] } ``` ``` use uselesskey::{Factory, RsaFactoryExt, RsaSpec}; use uselesskey_ring::RingRsaKeyPairExt; let fx = Factory::random(); let rsa = fx.rsa("signer", RsaSpec::rs256()); let ring_kp = rsa.rsa_key_pair_ring(); ``` ### RustCrypto 类型 (`uselesskey-rustcrypto`) ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } uselesskey-rustcrypto = { version = "0.9.1", features = ["all"] } ``` ``` use uselesskey::{Factory, RsaFactoryExt, RsaSpec}; use uselesskey_rustcrypto::RustCryptoRsaExt; let fx = Factory::random(); let rsa = fx.rsa("signer", RsaSpec::rs256()); let rsa_pk = rsa.rsa_private_key(); ``` ### aws-lc-rs 类型 (`uselesskey-aws-lc-rs`) ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["rsa"] } uselesskey-aws-lc-rs = { version = "0.9.1", features = ["native", "all"] } ``` ``` use uselesskey::{Factory, RsaFactoryExt, RsaSpec}; use uselesskey_aws_lc_rs::AwsLcRsRsaKeyPairExt; let fx = Factory::random(); let rsa = fx.rsa("signer", RsaSpec::rs256()); let lc_kp = rsa.rsa_key_pair_aws_lc_rs(); ``` ### gRPC TLS (`uselesskey-tonic`) ``` [dev-dependencies] uselesskey = { version = "0.9.1", features = ["x509"] } uselesskey-tonic = "0.9.1" ``` ``` use uselesskey::{ChainSpec, Factory, X509FactoryExt}; use uselesskey_tonic::{TonicClientTlsExt, TonicServerTlsExt}; let fx = Factory::random(); let chain = fx.x509_chain("grpc", ChainSpec::new("test.example.com")); let server_tls = chain.server_tls_config_tonic(); let client_tls = chain.client_tls_config_tonic("test.example.com"); ``` ## 可运行示例 [`crates/uselesskey/examples/`](crates/uselesskey/examples/) 目录包含独立程序。由于 facade 的默认 feature 集是空的,请使用下面一个有效的 feature 集,通过 `cargo run -p uselesskey --example --features ""` 运行它们: | 示例 | Feature(s) | 描述 | |---------|------------|-------------| | [adapter_jsonwebtoken](crates/uselesskey/examples/adapter_jsonwebtoken.rs) | `rsa,ecdsa,ed25519,hmac` | 使用 `jsonwebtoken` crate 集成对 JWT 进行签名和验证 | | [adapter_rustls](crates/uselesskey/examples/adapter_rustls.rs) | `x509` | 将 X.509 fixture 转换为 rustls `ServerConfig` / `ClientConfig` | | [basic_ecdsa](crates/uselesskey/examples/basic_ecdsa.rs) | `ecdsa,jwk` | 为 P-256 和 P-384 生成 PEM, DER, JWK 格式的 ECDSA 密钥对 | | [basic_ed25519](crates/uselesskey/examples/basic_ed25519.rs) | `ed25519,jwk` | 生成 PEM, DER 和 JWK 格式的 Ed25519 密钥对 | | [basic_hmac](crates/uselesskey/examples/basic_hmac.rs) | `hmac,jwk` | 为 HS256, HS384 和 HS512 生成 HMAC 密钥 | | [basic_rsa](crates/uselesskey/examples/basic_rsa.rs) | `rsa,jwk` | 生成 PEM, DER 和 JWK 格式的 RSA 密钥对 | | [basic_token](crates/uselesskey/examples/basic_token.rs) | `token` | 生成 API key、bearer token 和 OAuth access-token fixture | | [basic_usage](crates/uselesskey/examples/basic_usage.rs) | `ecdsa,ed25519,rsa,jwk` | 多合一:RSA、ECDSA 和 Ed25519 fixture 生成 | | [deterministic](crates/uselesskey/examples/deterministic.rs) | `rsa` | 从种子生成可重现的 fixture - 相同的种子总是产生相同的密钥 | | [deterministic_mode](crates/uselesskey/examples/deterministic_mode.rs) | `rsa,ecdsa,ed25519` | 顺序无关的确定性派生保证 | | [jwk_generation](crates/uselesskey/examples/jwk_generation.rs) | `ecdsa,ed25519,hmac,rsa,jwk` | 使用 `JwksBuilder` 跨密钥类型构建 JWK 和 JWKS | | [jwk_jwks](crates/uselesskey/examples/jwk_jwks.rs) | `ecdsa,ed25519,hmac,rsa,jwk` | 来自多种密钥类型的 JWK 集合,支持元数据检查 | | [jwks](crates/uselesskey/examples/jwks.rs) | `rsa,ecdsa,jwk` | 从 RSA 和 ECDSA 公钥构建 JWKS | | [jwks_server_mock](crates/uselesskey/examples/jwks_server_mock.rs) | `rsa,ecdsa,ed25519,jwk` | 为模拟的 `/.well-known/jwks.json` endpoint 生成 JWKS 响应体 | | [jwt_rs256_jwks](crates/uselesskey/examples/jwt_rs256_jwks.rs) | `rsa,jwk` | 提取 RSA 密钥对的 JWK/JWKS,用于 JWT 验证流程 | | [jwt_signing](crates/uselesskey/examples/jwt_signing.rs) | `rsa,jwk` | 使用确定性的 RSA、ECDSA 和 HMAC 密钥进行 JWT 签名(ECDSA/HMAC 可选) | | [negative_fixtures](crates/uselesskey/examples/negative_fixtures.rs) | `x509` | 用于错误路径测试的故意无效的证书和密钥 | | [negative_payload_shapes](crates/uselesskey/examples/negative_payload_shapes.rs) | `rsa,jwk,token` | 用于验证器测试的、对扫描器安全的负向 JWK/JWKS 和 token 形状 | | [tempfile_paths](crates/uselesskey/examples/tempfile_paths.rs) | `rsa,ed25519` | 将密钥 fixture 写入临时文件,用于基于路径的 API | | [tempfiles](crates/uselesskey/examples/tempfiles.rs) | `x509` | 将 X.509 证书、密钥和身份 PEM 写入临时文件 | | [tls_server](crates/uselesskey/examples/tls_server.rs) | `x509` | 用于 TLS 服务器测试的证书链生成 | | [token_generation](crates/uselesskey/examples/token_generation.rs) | `token` | 用于测试的逼真 API key、bearer token 和 OAuth token | | [x509_certificates](crates/uselesskey/examples/x509_certificates.rs) | `x509` | 自签名证书、证书链和负面 X.509 fixture | ## 工作区 Crate `uselesskey` 是一个 **facade crate**,它从专注的实现 crate 中重新导出。 为了方便,可以依赖 facade,或者依赖单个 crate 以最大程度地减少编译时间。 ### 实现 Crate | Crate | 描述 | |-------|-------------| | [`uselesskey`](https://crates.io/crates/uselesskey) | 公共 facade — 在 feature flag 之后重新导出所有密钥类型和 trait | | [`uselesskey-core`](https://crates.io/crates/uselesskey-core) | 工厂、确定性派生、缓存和负面 fixture 助手 | | [`uselesskey-entropy`](https://crates.io/crates/uselesskey-entropy) | 用于扫描器安全和占位符测试的确定性高熵字节 fixture | | [`uselesskey-rsa`](https://crates.io/crates/uselesskey-rsa) | RSA 2048/3072/4096 密钥对 (PKCS#8, SPKI, PEM, DER) | | [`uselesskey-ecdsa`](https://crates.io/crates/uselesskey-ecdsa) | ECDSA P-256 / P-384 密钥对 | | [`uselesskey-ed25519`](https://crates.io/crates/uselesskey-ed25519) | Ed25519 密钥对 | | [`uselesskey-hmac`](https://crates.io/crates/uselesskey-hmac) | HMAC HS256/HS384/HS512 密钥 | | [`uselesskey-ssh`](https://crates.io/crates/uselesskey-ssh) | 确定性的 OpenSSH 密钥和证书 fixture | | [`uselesskey-pgp`](https://crates.io/crates/uselesskey-pgp) | OpenPGP 密钥 fixture(armored + 二进制 keyblock) | | [`uselesskey-token`](https://crates.io/crates/uselesskey-token) | API key、bearer token 和 OAuth access-token fixture | | [`uselesskey-webhook`](https://crates.io/crates/uselesskey-webhook) | 用于 GitHub、Stripe 和 Slack 签名测试的确定性 webhook fixture | | [`uselesskey-jwk`](https://crates.io/crates/uselesskey-jwk) | 类型化的 JWK/JWKS 模型和构建器 | | [`uselesskey-x509`](https://crates.io/crates/uselesskey-x509) | X.509 自签名证书和证书链 | | [`uselesskey-cli`](https://crates.io/crates/uselesskey-cli) | 命令行 fixture 生成、打包和导出助手 | | [`uselesskey-test-server`](https://crates.io/crates/uselesskey-test-server) | 确定性的 OIDC 发现和 JWKS HTTP 测试服务器 fixture | | [`uselesskey-pkcs11-mock`](https://crates.io/crates/uselesskey-pkcs11-mock) | 用于 HSM/提供者集成测试的 PKCS#11 模拟提供者 fixture | | [`uselesskey-webauthn`](https://crates.io/crates/uselesskey-webauthn) | 用于 passkey 测试的 WebAuthn 凭据和断言 fixture | ### 适配器 Crate | Crate | 描述 | |-------|-------------| | [`uselesskey-axum`](https://crates.io/crates/uselesskey-axum) | `axum` auth 测试助手,带有确定性的 JWKS/OIDC 路由 | | [`uselesskey-jsonwebtoken`](https://crates.io/crates/uselesskey-jsonwebtoken) | `jsonwebtoken` `EncodingKey` / `DecodingKey` | | [`uselesskey-rustls`](https://crates.io/crates/uselesskey-rustls) | `rustls` `ServerConfig` / `ClientConfig` 构建器 | | [`uselesskey-tonic`](https://crates.io/crates/uselesskey-tonic) | 用于 gRPC 的 `tonic::transport` TLS 身份 / 配置 | | [`uselesskey-ring`](https://crates.io/crates/uselesskey-ring) | `ring` 0.17 原生签名密钥类型 | | [`uselesskey-rustcrypto`](https://crates.io/crates/uselesskey-rustcrypto) | RustCrypto 原生类型(`rsa::RsaPrivateKey` 等) | | [`uselesskey-aws-lc-rs`](https://crates.io/crates/uselesskey-aws-lc-rs) | `aws-lc-rs` 原生类型 | ## Feature Flag `uselesskey` facade 默认不启用任何 feature。 按 feature 划分的扩展 trait: - `rsa`: `RsaFactoryExt` - `ecdsa`: `EcdsaFactoryExt` - `ed25519`: `Ed25519FactoryExt` - `hmac`: `HmacFactoryExt` - `pgp`: `PgpFactoryExt` - `token`: `TokenFactoryExt` - `x509`: `X509FactoryExt` 对于输出系列的覆盖范围和依赖影响,请使用下面的矩阵。 ## Feature 矩阵 ### Facade feature(`uselesskey` crate) | Feature | 扩展 Trait | 算法 / 输出 | 隐含 | |---------|----------------|---------------------|---------| | `rsa` | `RsaFactoryExt` | RSA 2048/3072/4096 — PKCS#8, SPKI, PEM, DER | — | | `ecdsa` | `EcdsaFactoryExt` | P-256 (ES256), P-384 (ES384) — PKCS#8, SPKI | — | | `ed25519` | `Ed25519FactoryExt` | Ed25519 — PKCS#8, SPKI | — | | `hmac` | `HmacFactoryExt` | HS256, HS384, HS512 | — | | `pgp` | `PgpFactoryExt` | OpenPGP RSA 2048/3072, Ed25519 — armored, binary | — | | `token` | `TokenFactoryExt` | API key、bearer access token 和 OAuth access token | — | | `x509` | `X509FactoryExt` | 自签名证书、证书链、负面证书 | `rsa` | | `jwk` | — | 为所有启用的密钥类型提供 JWK/JWKS 输出 | — | | `all-keys` | — | (bundle) | `rsa` `ecdsa` `ed25519` `hmac` `pgp` | | `full` | — | (everything) | `all-keys` `token` `x509` `jwk` | ### 适配器 crate 的密钥类型支持 每个适配器 crate 都有针对特定算法的 feature flag(`rsa`, `ecdsa`, `ed25519`, `hmac`)以及一个方便的 `all` flag。 | 适配器 | RSA | ECDSA | Ed25519 | HMAC | X.509 / TLS | 额外 feature | |---------|:---:|:-----:|:-------:|:----:|:-----------:|----------------| | `uselesskey-jsonwebtoken` | ✓ | ✓ | ✓ | ✓ | — | — | | `uselesskey-ring` | ✓ | ✓ | ✓ | — | — | — | | `uselesskey-rustcrypto` | ✓ | ✓ | ✓ | ✓ | — | — | | `uselesskey-aws-lc-rs` | ✓ | ✓ | ✓ | — | — | `native (enables aws-lc-rs dep)` | | `uselesskey-rustls` | ✓ | ✓ | ✓ | — | ✓ | `tls-config, rustls-ring, rustls-aws-lc-rs` | | `uselesskey-tonic` | — | — | — | — | ✓ | — | ## 为什么选择这个 crate ### 顺序无关的确定性 Fixture 派生自稳定的身份组件: ``` seed + (domain, label, spec, variant) -> derived seed -> artifact ``` 添加新的 fixture 不会干扰现有的。测试顺序并不重要。 ### 按身份缓存 RSA 密钥生成开销很大。基于 `(domain, label, spec, variant)` 的每个工厂缓存使得运行时生成成本足够低,足以取代提交的 fixture。 ### 形状优先的输出 首先要求形状:PKCS#8, SPKI, PEM, DER, JWK, JWKS 或临时文件。 使用者要求的是工件形状;低级加密原语故意不作为默认输出。 ### 第一类负面工件 损坏的 PEM、截断的 DER、不匹配的密钥、过期的证书、带有RL 的吊销叶子:这些正是团队否则需要手工制作并提交的工件。 `uselesskey` 使它们变得具有确定性、低成本且可随意丢弃。 ## 何时不使用此 crate - 生产密钥生成 - 运行时证书颁发机构行为 - 证书验证逻辑 - HSM / TPM / 硬件支持的密钥 - 以签名或验证 API 作为主要抽象 对于运行时证书生成,请直接使用 `rcgen`。对于验证,请使用 `rustls`、`x509-parser` 或实际负责验证的库。 ## 生态系统 当你需要**不应存在于 git 历史记录中的真实测试 fixture** 时,请使用 `uselesskey`。 在以下情况寻求其他工具: - 当你需要在以 fixture 为中心的工作流之外进行运行时证书生成时,请选择 `rcgen` - 当你需要 TLS 运行时集成和验证时,请选择 `rustls` - 当你需要解析/检查/验证工作时,请选择 `x509-parser` ## 社区 - [CHANGELOG](CHANGELOG.md) — 发布历史 - [CONTRIBUTING](CONTRIBUTING.md) — 如何构建、测试和添加新的密钥类型 - [SECURITY](SECURITY.md) — 安全策略(这是一个仅供测试的 crate) - [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) — Contributor Covenant - [SUPPORT](SUPPORT.md) — 如何获取帮助 ## 稳定性和版本控制 **派生稳定性** 在同一个 `DerivationVersion` 中,给定 `(seed, domain, label, spec, variant)` 元组的工件是稳定的。 如果派生逻辑发生变化,将引入新的派生版本,而不是改变旧版本。 **Semver** 破坏性 API 更改在 `1.0` 之前会提升 minor 版本,之后则提升 major 版本。 **MSRV** 最低支持的 Rust 版本为 **1.95**(2024 edition)。 ## 许可证 根据以下任一许可证授权: - Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE)) - MIT license ([LICENSE-MIT](LICENSE-MIT)) 由你选择。
标签:Rust, 加密测试数据, 可视化界面, 开发辅助, 文档结构分析, 测试夹具, 测试工具, 网络流量审计, 证书生成, 通知系统