This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
uselesskey is a Rust test utility library that generates deterministic and random cryptographic key fixtures for testing. It prevents committing secret-shaped blobs (PEM, DER, tokens) into version control while allowing tests to work with realistic key formats.
This is a test-fixture layer, not a crypto library. The positioning matters for API design and documentation tone.
Secret scanners have different behaviors that both cause friction:
- GitGuardian scans each commit in a PR, so "add then remove" still trips detection
- GitHub push protection requires removing a blocked secret from all commits before pushing again
Path ignores exist but require ongoing maintenance. This crate replaces "security policy + docs + exceptions" with "one dev-dependency."
Snapshot: last reviewed 2026-03-14. This is context, not a compatibility matrix.
| Existing solution | Gap uselesskey fills |
|---|---|
jwk_kit |
No deterministic-from-seed, no negative fixtures |
rcgen |
Deterministic mode not first-class |
test-cert-gen |
Shells out to OpenSSL |
x509-test-certs |
Commits key material (triggers scanners) |
-
Order-independent determinism —
seed + artifact_id → derived_seed → artifact. This is the most defensible feature; most seeded approaches break when test order changes. -
Cache-by-identity — Per-process cache keyed by
(domain, label, spec, variant)makes RSA keygen cheap enough to avoid committed fixtures. -
Shape-first outputs — Users ask for PKCS#8/SPKI/JWK/tempfiles, not crypto primitives.
-
Negative fixtures first-class — Corrupt PEM, truncated DER, mismatched keys, and deterministic corruption variants (
corrupt:*).
- Keep the API ergonomic: one-liner creation (
fx.rsa("issuer", RsaSpec::rs256())) - Avoid production crypto expectations: this is for tests only
- Preserve derivation stability: bump version if algorithm changes
- Extension traits for new key types (not monolithic API growth)
cargo xtask ci # Main CI pipeline: fmt + clippy + tests + matrix + guard + bdd + no-blob + mutants + fuzz
cargo xtask pr # PR-scoped tests based on git diff (emits JSON receipt)
cargo xtask test # Run all tests with all features
cargo xtask fmt --fix # Fix formatting
cargo xtask clippy # Run clippy with -D warnings
cargo xtask bdd # Run Cucumber BDD tests
cargo xtask fuzz # Fuzz testing (requires cargo-fuzz)
cargo xtask mutants # Mutation testing (requires cargo-mutants)
cargo xtask deny # License/advisory checks (requires cargo-deny)
cargo xtask feature-matrix # Run feature matrix checks (default, no-default, each feature, all-features)
cargo xtask publish-check # Run publish dry-runs in dependency order
cargo xtask publish-preflight # Validate metadata + cargo package --no-verify
cargo xtask no-blob # Enforce no secret-shaped blobs in test/fixture paths
cargo xtask dep-guard # Guard against multiple versions of pinned deps
cargo xtask coverage # Run code coverage (requires cargo-llvm-cov)
cargo xtask nextest # Run tests via cargo-nextest (requires cargo-nextest)
cargo xtask lint-fix # Auto-fix fmt + clippy, then verify
cargo xtask lint-fix --check # Check-only (no mutations)
cargo xtask lint-fix --no-clippy # fmt only
cargo xtask gate # Pre-push quality gate: fmt check + cargo check + clippy + test compile
cargo xtask typos # Spell check (requires typos installed)
cargo xtask typos --fix # Auto-fix typos
cargo xtask bdd-matrix # BDD matrix with feature sets
cargo xtask publish # Publish all crates in dependency order
cargo xtask setup # Configure git hooks (sets core.hooksPath to .githooks)Run a single test:
cargo test -p uselesskey-core test_name
cargo test -p uselesskey-rsa test_namecrates/uselesskey- Public facade crate, re-exports stable APIcrates/uselesskey-core- Core factory, derivation, caching, negative fixturescrates/uselesskey-core-jwk- Core typed JWK/JWKS models plus stableJwksBuilderordering semanticscrates/uselesskey-core-x509-spec- X.509 spec models and stable encoding helperscrates/uselesskey-core-x509- X.509 negative-policy types plus X.509 spec/derive re-exportscrates/uselesskey-jwk- Compatibility facade re-exportinguselesskey-core-jwkcrates/uselesskey-rsa- RSA fixtures viaRsaFactoryExttraitcrates/uselesskey-ecdsa- ECDSA (P-256/P-384) fixtures viaEcdsaFactoryExttraitcrates/uselesskey-ed25519- Ed25519 fixtures viaEd25519FactoryExttraitcrates/uselesskey-hmac- HMAC (HS256/HS384/HS512) fixtures viaHmacFactoryExttraitcrates/uselesskey-token- Token fixtures (API key, bearer, OAuth/JWT-shape) viaTokenFactoryExttraitcrates/uselesskey-pgp- OpenPGP key fixtures (RSA/Ed25519, armored/binary) viaPgpFactoryExttraitcrates/uselesskey-x509- X.509 certificate fixtures viaX509FactoryExttraitcrates/uselesskey-jsonwebtoken- Adapter:jsonwebtokenintegrationcrates/uselesskey-rustls- Adapter:rustls/rustls-pki-typesintegrationcrates/uselesskey-ring- Adapter:ringintegrationcrates/uselesskey-rustcrypto- Adapter: RustCrypto integrationcrates/uselesskey-aws-lc-rs- Adapter:aws-lc-rsintegrationcrates/uselesskey-tonic- Adapter:tonicgRPC TLS integrationcrates/uselesskey-bdd- Cucumber BDD testscrates/uselesskey-bdd-steps- BDD step definitionscrates/uselesskey-interop-tests- Cross-adapter interop testscrates/uselesskey-feature-grid- Feature-matrix definitionscrates/uselesskey-test-grid- Test-grid facadecrates/uselesskey-token-spec- Token spec modelstests/- Workspace-level integration testsxtask- Build automation commands
See
docs/explanation/architecture.mdfor the full 48-crate breakdown including core microcrates.
Factory: Central struct managing artifact generation and caching. Operates in Random or Deterministic mode.
Deterministic Derivation: BLAKE3 keyed hash transforms master_seed + artifact_id -> derived_seed -> RNG -> artifact. ArtifactId is a tuple of (domain, label, spec_fingerprint, variant, derivation_version). Adding new fixtures doesn't perturb existing ones.
Cache: DashMap-based concurrent cache stores Arc<dyn Any + Send + Sync>.
Negative Fixtures: Corrupt PEM variants (CorruptPem enum), truncated DER, mismatched keypairs via "mismatch" variant. X.509 negative fixtures include expired certs, hostname mismatch, unknown CA, and revoked leaf with CRL.
Key type support is added via extension traits on Factory:
RsaFactoryExt→fx.rsa(label, spec)EcdsaFactoryExt→fx.ecdsa(label, spec)Ed25519FactoryExt→fx.ed25519(label, spec)HmacFactoryExt→fx.hmac(label, spec)TokenFactoryExt→fx.token(label, spec)PgpFactoryExt→fx.pgp(label, spec)X509FactoryExt→fx.x509_self_signed(label, spec)/fx.x509_chain(label, spec)
Adapter crates (e.g. uselesskey-jsonwebtoken) are separate crates, not features, to avoid coupling versioning.
- Derivation stability: Keep deterministic derivation stable; bump derivation version if changing algorithm
- No key leakage: Debug output must never print key material
- Small composable crates: Prefer modular design over monolith
- No unsafe code: All crates use
#![forbid(unsafe_code)]
- Unit/integration tests use
#[test],proptest(property-based), andrstest(parameterized) cargo xtask testruns--workspace --all-features --exclude uselesskey-bddcargo xtask bddruns BDD tests separately with--release(RSA keygen is too slow in debug)- BDD feature files in
crates/uselesskey-bdd/features/covering all key types, X.509, JWK, negative fixtures, and edge cases - Fuzz targets in
fuzz/fuzz_targets/
rustfmt.toml- Formatting: Unix newlines, crate-level importsclippy.toml- MSRV 1.92deny.toml- Allowed licenses: MIT, Apache-2.0, BSD-3-Clause, ISC, CC0-1.0mutants.toml- Mutation testing exclusions
The repo ships pre-commit and pre-push hooks in .githooks/. Activate them once:
cargo xtask setup # sets core.hooksPath to .githooks- pre-commit: runs
cargo xtask lint-fixwhen staged.rs/Cargo.toml/Cargo.lockfiles are present, then re-stages the touched files. - pre-push: runs
cargo xtask gate --check(fmt check + cargo check + clippy + test compile).