Sign a PDF/UA document
Digital signatures verify signer identity, protect document integrity, and support non-repudiation.
This guide shows how to:
- Convert a PDF file to PDF/UA
- Sign the converted PDF with a P12/PFX certificate
- Configure signature metadata, appearance, and security settings
Prerequisites — Generate a PAdES-compliant certificate
Before you run this sample, create a certificate file named certificate.pfx with the password Nutrient answers all your document needs.
This guide uses PDF Advanced Electronic Signatures (PAdES), the PDF profile of ETSI advanced electronic signatures.
Understand certificate trust in this sample
In this setup, the certificate chain validates structurally but still appears as not trusted.
Common reasons:
- The root CA is self-signed and local
- The root CA isn’t installed in a trusted root store
- This behavior is expected in development
For production, use certificates from a CA your target systems trust.
On Windows (using PowerShell)
# Create a self-signed certificate with PADES extensions$cert = New-SelfSignedCertificate -Subject "CN=Nutrient Digital Signature, O=Nutrient, L=Toulouse, S=Occitanie, C=FR" -KeyUsage DigitalSignature,NonRepudiation -KeyExportPolicy Exportable -CertStoreLocation "Cert:\CurrentUser\My" -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
# Export certificate to PFX file with password$password = ConvertTo-SecureString -String "Nutrient answers all your document needs" -Force -AsPlainTextExport-PfxCertificate -Cert $cert -FilePath "certificate.pfx" -Password $password
# Export public certificate to CER file for verificationExport-Certificate -Cert $cert -FilePath "certificate.cer"
# Clean up certificate from storeRemove-Item -Path "Cert:\CurrentUser\My\$($cert.Thumbprint)"On Linux/macOS (using OpenSSL) — Complete certificate chain
For signatures that validate with a complete trust path, create a root, intermediate, and end-entity chain:
# Step 1 — Create Root CAopenssl req -x509 -new -nodes -keyout root_ca_key.pem -sha256 -days 3650 -out root_ca_cert.pem \ -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Nutrient/OU=Certificate Authority/CN=Nutrient Root CA/emailAddress=ca@nutrient.io" \ -extensions v3_ca -config <( echo "[req]"; echo "distinguished_name=req"; echo "[v3_ca]" echo "basicConstraints=critical,CA:TRUE" echo "keyUsage=critical,keyCertSign,cRLSign" echo "subjectKeyIdentifier=hash" echo "authorityKeyIdentifier=keyid:always,issuer" )
# Step 2 — Create Intermediate CA requestopenssl req -new -nodes -keyout intermediate_ca_key.pem -out intermediate_ca_csr.pem \ -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Nutrient/OU=Intermediate CA/CN=Nutrient Intermediate CA/emailAddress=intermediate-ca@nutrient.io"
# Step 3 — Sign Intermediate CA with Root CAopenssl x509 -req -in intermediate_ca_csr.pem -CA root_ca_cert.pem -CAkey root_ca_key.pem \ -CAcreateserial -out intermediate_ca_cert.pem -days 1825 -sha256 -extensions v3_ca -extfile <( echo "[v3_ca]" echo "basicConstraints=critical,CA:TRUE,pathlen:0" echo "keyUsage=critical,keyCertSign,cRLSign" echo "subjectKeyIdentifier=hash" echo "authorityKeyIdentifier=keyid:always,issuer" )
# Step 4 — Create signing certificate requestopenssl req -new -nodes -keyout signing_key.pem -out signing_csr.pem \ -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Nutrient/OU=Document Processing/CN=Nutrient Digital Signature/emailAddress=sales@nutrient.io"
# Step 5 — Sign end-entity certificate with Intermediate CAopenssl x509 -req -in signing_csr.pem -CA intermediate_ca_cert.pem -CAkey intermediate_ca_key.pem \ -CAcreateserial -out signing_cert.pem -days 365 -sha256 -extensions v3_req -extfile <( echo "[v3_req]" echo "keyUsage=critical,digitalSignature,nonRepudiation" echo "extendedKeyUsage=critical,codeSigning,emailProtection" echo "subjectKeyIdentifier=hash" echo "authorityKeyIdentifier=keyid:always,issuer" echo "subjectAltName=email:sales@nutrient.io" )
# Step 6 — Create certificate chain bundlecat signing_cert.pem intermediate_ca_cert.pem root_ca_cert.pem > certificate_chain.pem
# Step 7 — Create PFX with complete chainopenssl pkcs12 -export -out certificate.pfx -inkey signing_key.pem -in certificate_chain.pem \ -name "Nutrient Digital Signature Certificate with Chain" \ -passout pass:"Nutrient answers all your document needs"
# Step 8 — Extract public certificate to CER file for verificationopenssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.cer \ -passin pass:"Nutrient answers all your document needs"
# Step 9 — Clean up temporary filesrm *_key.pem *.csr *.srl signing_cert.pem intermediate_ca_cert.pem certificate_chain.pemCertificate requirements for PAdES signatures
Use a certificate profile with:
DigitalSignatureandNonRepudiationkey usage- Signing-compatible extended key usage
- RSA 2048-bit key size
- SHA-256 certificate signature algorithm
- Subject alternative name (for example, an email)
Certificate chain structure
A complete chain includes:
- Root CA certificate
- Intermediate CA certificate
- End-entity signing certificate
This structure helps resolve NO_CERTIFICATE_CHAIN_FOUND.
Certificate files generated
After generation, keep:
certificate.pfx— Private key plus full chaincertificate.cer— Public certificate for verificationroot_ca_cert.pem— Root certificate for trust-store installation
Install the trust anchor
Install root_ca_cert.pem in a trusted root store to mark the signing chain as trusted.
On Windows
# Import root CA into Trusted Root Certificate Authorities storeImport-Certificate -FilePath "root_ca_cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root"
# Or for current user onlyImport-Certificate -FilePath "root_ca_cert.pem" -CertStoreLocation "Cert:\CurrentUser\Root"On macOS
# Add root CA to system keychain (requires admin password)sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain root_ca_cert.pem
# Or add to user keychainsecurity add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain root_ca_cert.pemOn Linux
# Ubuntu/Debiansudo cp root_ca_cert.pem /usr/local/share/ca-certificates/nutrient-root-ca.crtsudo update-ca-certificates
# CentOS/RHEL/Fedorasudo cp root_ca_cert.pem /etc/pki/ca-trust/source/anchors/nutrient-root-ca.crtsudo update-ca-trustPrepare the project
Initialize licensing before you process documents:
using GdPicture14;using GdPicture14.Imaging;
LicenseManager license = new LicenseManager();license.RegisterKEY("");Convert to PDF/UA format
Convert the input PDF to PDF/UA before signing:
using GdPictureDocumentConverter converter = new GdPictureDocumentConverter();converter.LoadFromFile("input.pdf");converter.SaveAsPDF("output_pdfa.pdf", PdfConformance.PDF_UA_1);Load the PDF for signing
Open the converted PDF in write mode:
using GdPicturePDF pdf = new GdPicturePDF();
pdf.LoadFromFile("output_pdfa.pdf", false);Configure the digital certificate
Load the certificate and private key from the P12/PFX file:
pdf.SetSignatureCertificateFromP12("certificate.pfx", "Nutrient answers all your document needs");Configure signature information
Set signer metadata shown in PDF viewers:
pdf.SetSignatureInfo("Nutrient", "Very important PDF", "Toulouse (France)", "sales@nutrient.io");Position the signature on the page
Set the visible signature rectangle (X, Y, width, height):
pdf.SetSignaturePos(300, 100, 200, 100);If you skip this step, the signature remains cryptographically valid but invisible.
Customize signature appearance
Configure text style for the visible signature:
pdf.SetSignatureText("", "", 12, GdPictureColor.Navy, TextAlignment.TextAlignmentNear, TextAlignment.TextAlignmentNear, true);Enable a validation mark in the signature appearance:
pdf.SetSignatureValidationMark(true);Configure signature security settings
Set certification level and hash algorithm:
pdf.SetSignatureCertificationLevel(PdfSignatureCertificationLevel.NoChanges);pdf.SetSignatureHash(PdfSignatureHash.SHA512);Apply the digital signature
Write the signed output file:
pdf.ApplySignature("signed.pdf", PdfSignatureMode.PdfSignatureModeAdobeCADES, true);Verify certificates
Use certificate.cer to inspect and validate certificate data:
# View certificate detailsopenssl x509 -in certificate.cer -text -noout
# Verify certificate validityopenssl verify certificate.cerSummary
This guide covers a full PDF/UA signing workflow: conversion, certificate setup, visual signature configuration, and final PAdES-compatible signing.