1 unstable release
| 0.1.0 | Jun 1, 2026 |
|---|
#1734 in Cryptography
98KB
2K
SLoC
jades
JSON Advanced Electronic Signatures (JAdES) — JWS signing and verification implementing ETSI TS 119 182-1, with conformance levels B-B through B-LTA.
Features
- JAdES-B-B — Basic signature: JWS + signing time (
sigT) + signer certificate (x5c) - JAdES-B-T — Signature timestamp: RFC 3161 token over signature value (
sigTstinetsiU) - JAdES-B-LT — Long-term: certificate chain (
xVals) + revocation data (rVals) - JAdES-B-LTA — Long-term archival: archive timestamp (
arcTst) for indefinite validity - Minimal JWS — Built-in JWS Compact and JSON (Flattened/General) serialization
- Detached signatures — sign/verify with an external (non-embedded) payload
(RFC 7515 empty-payload form; the ETSI
sigDheader is not populated) - Three-phase remote signing — prepare/finalize pattern for HSM and cloud KMS backends (B-B and B-T)
- Verification — in-crate signature verification,
critenforcement, level detection, and (with a trust store) certificate-chain, timestamp, and revocation validation - Post-quantum — ML-DSA (FIPS 204) signing and verification behind the
pqfeature
Design
Built on a minimal JWS (RFC 7515) implementation because existing Rust JWS
crates don't support JWS JSON Serialization with custom unprotected headers
(required for etsiU). Uses tsp-ltv for RFC
3161 timestamping, OCSP/CRL revocation, trust stores, and certificate chain
validation.
jades (this crate)
├── jws/ — JWS Compact + JSON serialization, base64url
├── header/ — ETSI protected headers (sigT, x5c, sigD, ...)
│ + unprotected etsiU (sigTst, xVals, rVals, arcTst)
├── sign — sign_jades_{bb,bt,blt,blta}
├── verify — verify_jades: in-crate JWS signature verification + level detection
├── remote — three-phase prepare/finalize for remote signing (B-B, B-T)
└── signer — JadesSigner trait + SoftwareSigner
JWS signature verification (RSA/ECDSA/EdDSA) is performed in-crate with
RustCrypto, using the raw JWS signature encodings of RFC 7518. tsp-ltv is used
for the trust- and time-related parts of higher conformance levels:
├── tsp — RFC 3161 TSA client (sigTst, arcTst) + timestamp-token verification
├── ltv — OCSP/CRL clients (rVals) + offline revocation checking
└── trust — TrustStore + certificate-chain verification
Quick start
Add to your Cargo.toml:
[dependencies]
jades = "0.1"
Network-dependent features are enabled by default (tsp, ltv). For B-B only
(no network, no async runtime):
[dependencies]
jades = { version = "0.1", default-features = false }
Sign a JAdES-B-B
use jades::{sign_jades_bb, SignOptions};
use jades::signer::SoftwareSigner;
let signer = SoftwareSigner::from_p256(signing_key, cert_chain_der)?;
let payload = b"document content";
let opts = SignOptions::default();
let jws = sign_jades_bb(payload, &signer, &opts)?;
Three-phase remote signing
use jades::remote::{prepare_jades, finalize_jades_bb};
use jades::signer::JwsAlgorithm;
use jades::SignOptions;
// Phase 1: prepare (local)
let prepared = prepare_jades(payload, &cert_chain, JwsAlgorithm::ES256, &opts)?;
// Phase 2: sign (remote — send prepared.signing_input to HSM/KMS)
let signature = remote_sign(&prepared.signing_input)?;
// Phase 3: finalize (local)
let jws = finalize_jades_bb(prepared, &signature)?;
Verify
use jades::{verify_jades, VerifyOptions};
let opts = VerifyOptions::default();
let result = verify_jades(&jws, &opts)?;
assert!(result.signature_valid);
println!("Level: {}", result.level); // "JAdES-B-B", "JAdES-B-T", etc.
signature_valid is a cryptographic check only — it proves the signature
matches the public key in the embedded signer certificate. To establish trust,
supply a jades::TrustStore (re-exported from tsp-ltv) via
VerifyOptions::trust_store; the signer chain (and any TSA chains) are then
validated and reported in result.chain_valid. Without a trust store,
chain_valid is None (not evaluated). For detached signatures, supply the
external bytes via VerifyOptions::detached_payload.
Feature flags
| Flag | Default | Description |
|---|---|---|
tsp |
yes | RFC 3161 timestamping + timestamp verification (B-T and above) |
ltv |
yes | OCSP/CRL + chain validation for B-LT/B-LTA (implies tsp) |
pq |
no | Post-quantum ML-DSA (FIPS 204) signing and verification — ML-DSA-44/65/87 |
The tsp/ltv signing and timestamp/revocation functions are async and
require a Tokio runtime (pulled in by these features). The B-B signing and the
verify_jades API are synchronous.
Serialization forms
| Form | Unprotected Headers | Levels produced by signing |
|---|---|---|
| JWS Compact | No | B-B only |
| JWS JSON Flattened | Yes (via etsiU) |
B-B, B-T, B-LT, B-LTA |
| JWS JSON General | Yes (via etsiU) |
B-B only |
For B-T and above, signing always emits the Flattened form (the JAdES common case). Verification accepts Compact, Flattened, and General forms; for a General JWS, every signature is verified.
Supported algorithms
Verification (verify_jades) supports all of the following:
- RSA: RS256, RS384, RS512, PS256, PS384, PS512
- ECDSA: ES256 (P-256), ES384 (P-384), ES512 (P-521)
- EdDSA: Ed25519
- ML-DSA (FIPS 204,
pqfeature): ML-DSA-44, ML-DSA-65, ML-DSA-87
The bundled SoftwareSigner can sign with ES256, ES384, Ed25519, the RSA
algorithms, and — with the pq feature — ML-DSA-44/65/87 (via
SoftwareSigner::from_ml_dsa_44 / _65 / _87). ES512 (P-521) and any other
algorithm can be signed via a custom JadesSigner implementation (e.g. an
HSM/KMS backend) or the three-phase remote-signing API.
ML-DSA uses the pure (non-prehashed) algorithm with an empty context string, the
convention adopted by the JOSE/COSE post-quantum drafts. Construct ML-DSA keys
through the re-exported jades::ml_dsa module so no separate dependency is
needed.
License
BSD-2-Clause
Dependencies
~10–19MB
~354K SLoC