underskrift
A Rust library for digitally signing and verifying PDF documents. Supports PAdES B-B through B-LTA, PKCS#7 (traditional PDF signatures), visible and invisible signatures, LTV (long-term validation), RFC 3161 timestamps, RFC 9321 SVT tokens, and ETSI TS 119 102-2 validation reports.
Underskrift is Swedish for signature.
Features
- PAdES B-B / B-T / B-LT / B-LTA conformance levels
- PKCS#7 (traditional
adbe.pkcs7.detached) signatures - Visible signatures with configurable layouts, images (JPEG/PNG), and embedded font subsetting
- RFC 3161 timestamping with TSA client and pool (failover)
- Long-term validation (LTV) -- OCSP, CRL fetching, DSS embedding
- Signature verification -- integrity checks, CMS validation, certificate chain verification against configurable trust stores
- Validation policy framework -- basic and PKIX-based policies with revocation checking and grace periods
- SACI AuthnContext parsing (RFC 7773, Swedish e-signing infrastructure)
- SVT (Signature Validation Tokens, RFC 9321) -- issue and validate JWTs, embed as document timestamps
- ETSI TS 119 102-2 XML validation reports
- Three-phase remote signing -- prepare hash, sign externally (HSM / cloud KMS / smart card), finalize PDF
- Pluggable crypto -- bring your own signer via the
CryptoSignertrait; built-inSoftwareSignersupports PKCS#12, PEM, and DER key files - Algorithm coverage -- RSA PKCS#1 v1.5, RSA-PSS, ECDSA (P-256, P-384, P-521), Ed25519, SHA-256/384/512, SHA3-256/384/512
Quick start
Add to your Cargo.toml:
[]
= "0.1"
All features are enabled by default. To use only a subset:
[]
= { = "0.1", = false, = ["verify"] }
Sign a PDF
use ;
let pdf_data = read?;
let signer = from_pkcs12_file?;
let options = SigningOptions ;
let signed = new
.options
.sign
.await?;
write?;
Verify a PDF
use ;
use ;
let pdf_data = read?;
let store = from_pem_directory?;
let trust = new.with_sig_store;
let report = new
.policy
.verify_pdf?;
println!;
for sig in &report.signatures
Three-phase remote signing
For HSMs, cloud KMS, or other external signing services where the private key is not directly accessible:
use ;
// Phase 1: prepare -- returns the hash to be signed externally
let cert_chain = load_certificate_chain; // Vec<Vec<u8>> (DER)
let signer_info = new;
let options = default;
let prepared = prepare_signature?;
// Phase 2: sign the hash externally (your HSM / KMS / smart card)
let signature_bytes = your_external_signer.sign?;
// Phase 3: finalize -- inject signature into the PDF
let signed_pdf = finalize_signature?;
Feature flags
| Flag | Default | Description |
|---|---|---|
verify |
yes | Signature verification and validation |
tsp |
yes | RFC 3161 timestamp client (requires network) |
ltv |
yes | Long-term validation: OCSP, CRL, DSS (implies tsp) |
blocking |
yes | Synchronous wrappers via tokio::runtime::block_on() |
visual |
yes | Visible signature appearances, image embedding, fonts |
saci |
yes | SACI AuthnContext X.509 extension parsing (RFC 7773) |
svt |
yes | RFC 9321 Signature Validation Tokens (JWT-based) |
report |
yes | ETSI TS 119 102-2 XML validation reports (implies verify) |
Modules
| Module | Description |
|---|---|
core |
PDF signature structures, byte ranges, incremental saves, revision parsing |
cms |
CMS/PKCS#7 SignedData construction (PAdES and traditional profiles) |
crypto |
Signing key abstraction, software signer, algorithm registry |
signer |
High-level PdfSigner orchestrator with builder pattern |
remote |
Three-phase remote/deferred signing protocol |
trust |
TrustStore and TrustStoreSet for certificate management |
policy |
Validation policy framework (BasicPdfSignaturePolicy, PkixPdfSignaturePolicy) |
verify |
Signature verification: integrity, CMS, chain, revocation |
tsp |
RFC 3161 TSA client and response parsing |
ltv |
OCSP/CRL clients, certificate chain building, DSS embedding |
visual |
Visible signature layout, image handling, font subsetting |
saci |
SACI AuthnContext parsing for Swedish e-signing |
svt |
SVT issuance, validation, and PDF embedding |
report |
ETSI XML validation report generation |
Supported algorithms
Signing: RSA PKCS#1 v1.5, RSA-PSS, ECDSA P-256, ECDSA P-384, ECDSA P-521, Ed25519
Digest: SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-384, SHA3-512
Key formats: PKCS#12 (.p12/.pfx), PEM, DER
Running tests
Test fixtures (keys, certificates) are generated by a script:
There is also an example:
License
BSD-2-Clause