Digital Signatures
Commercial License Required - This feature requires a commercial license. See printwell.dev/pricing.
Sign PDF documents with PAdES-compliant digital signatures.
Signature Levels
| Level | Description |
|---|---|
PadesB | Basic signature |
PadesT | With trusted timestamp |
PadesLT | Long-term validation data |
PadesLTA | Long-term archival |
Invisible Signatures
#![allow(unused)]
fn main() {
use printwell::signing::{sign_pdf, SigningOptions};
let cert_data = std::fs::read("certificate.p12")?;
let options = SigningOptions {
reason: Some("Document approved".into()),
location: Some("New York, NY".into()),
contact_info: Some("signer@example.com".into()),
signature_level: SignatureLevel::PadesB,
..Default::default()
};
let signed = sign_pdf(&pdf_data, &cert_data, "cert_password", options)?;
}
Visible Signatures
#![allow(unused)]
fn main() {
use printwell::signing::{sign_pdf_visible, SignatureAppearance};
let appearance = SignatureAppearance {
page: 1,
x: 400.0,
y: 50.0,
width: 200.0,
height: 75.0,
show_name: true,
show_date: true,
show_reason: true,
background_image: None, // Optional logo
};
let signed = sign_pdf_visible(
&pdf_data,
&cert_data,
"password",
SigningOptions::default(),
appearance
)?;
}
Verifying Signatures
#![allow(unused)]
fn main() {
use printwell::signing::verify_signatures;
let results = verify_signatures(&signed_pdf)?;
for result in &results {
println!("Signer: {}", result.signer_name);
println!("Valid: {}", result.is_valid);
println!("Covers whole doc: {}", result.covers_whole_document);
println!("Time: {:?}", result.signing_time);
if !result.cert_warnings.is_empty() {
println!("Warnings: {:?}", result.cert_warnings);
}
}
}
Extracting Signature Info
#![allow(unused)]
fn main() {
use printwell::signing::extract_signatures;
let signatures = extract_signatures(&pdf_data)?;
for sig in &signatures {
println!("Signer: {:?}", sig.signer_name);
println!("Reason: {:?}", sig.reason);
println!("Location: {:?}", sig.location);
println!("Time: {:?}", sig.signing_time);
}
}
Certificate Requirements
Certificates must be in PKCS#12 format (.p12 or .pfx):
- Must contain private key
- Should include certificate chain
- Supported algorithms: RSA, ECDSA (P-256, P-384)
Creating Test Certificates
# Generate self-signed certificate (for testing only)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
openssl pkcs12 -export -out certificate.p12 -inkey key.pem -in cert.pem
Node.js Example
import { signPdf, signPdfVisible, verifySignatures } from 'printwell';
const signed = signPdf(pdfData, certData, 'password', {
reason: 'Approved',
location: 'New York',
signatureLevel: 'PadesB'
});
const signedVisible = signPdfVisible(pdfData, certData, 'password',
{ reason: 'Approved' },
{ page: 1, x: 400, y: 50, width: 200, height: 75 }
);
const results = verifySignatures(signedData);
Python Example
from printwell import sign_pdf, sign_pdf_visible, verify_signatures
signed = sign_pdf(pdf_data, cert_data, "password",
SigningOptions(reason="Approved", location="New York"))
results = verify_signatures(signed)
for r in results:
print(f"{r.signer_name}: {'Valid' if r.is_valid else 'Invalid'}")