Embed an RFC 3161 timestamp token from a Time Stamping Authority into an existing PDF signature.
use pdfluent::{Document, timestamp::{TsaConfig, TimestampOptions}};
fn main() -> pdfluent::Result<()> {
let mut doc = Document::open("signed.pdf")?;
let tsa = TsaConfig::new("http://timestamp.digicert.com");
let opts = TimestampOptions::new(tsa);
// Add a document-level timestamp signature field
doc.add_timestamp(&opts)?;
doc.save("timestamped.pdf")?;
Ok(())
}The document may already be signed by a signer, or you may add a standalone timestamp signature field.
let mut doc = Document::open("signed.pdf")?;Provide the URL of a trusted RFC 3161 Time Stamping Authority. Many CAs offer free TSA endpoints.
use pdfluent::timestamp::TsaConfig;
let tsa = TsaConfig::new("http://timestamp.digicert.com")
.hash_algorithm(pdfluent::digest::HashAlgorithm::Sha256);TimestampOptions wraps the TsaConfig and specifies the field name and policy OID if required by the TSA.
use pdfluent::timestamp::TimestampOptions;
let opts = TimestampOptions::new(tsa)
.field_name("DocTimestamp")
.policy_oid(None); // None = TSA default policyPDFluent computes the document digest, sends a TSQ to the TSA, receives a TSR, and embeds the RFC 3161 token in a new signature field.
doc.add_timestamp(&opts)?;Save the file and confirm the timestamp token is present.
doc.save("timestamped.pdf")?;
// Verify the timestamp
let doc2 = Document::open("timestamped.pdf")?;
for sig in doc2.signatures() {
if sig.has_timestamp_token() {
let ts = sig.timestamp_token()?;
println!("Timestamp time: {:?}", ts.gen_time());
println!("TSA: {}", ts.tsa_name().unwrap_or("unknown"));
}
}No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.