This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/dotnet/signatures/digital-signatures/sign-a-pdf-ua-document.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. 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)

Terminal window
# 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 -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "certificate.pfx" -Password $password
# Export public certificate to CER file for verification
Export-Certificate -Cert $cert -FilePath "certificate.cer"
# Clean up certificate from store
Remove-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:

Terminal window
# Step 1 — Create Root CA
openssl 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 request
openssl 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 CA
openssl 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 request
openssl 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 CA
openssl 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 bundle
cat signing_cert.pem intermediate_ca_cert.pem root_ca_cert.pem > certificate_chain.pem
# Step 7 — Create PFX with complete chain
openssl 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 verification
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.cer \
-passin pass:"Nutrient answers all your document needs"
# Step 9 — Clean up temporary files
rm *_key.pem *.csr *.srl signing_cert.pem intermediate_ca_cert.pem certificate_chain.pem

Certificate requirements for PAdES signatures

Use a certificate profile with:

  • DigitalSignature and NonRepudiation key 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:

  1. Root CA certificate
  2. Intermediate CA certificate
  3. End-entity signing certificate

This structure helps resolve NO_CERTIFICATE_CHAIN_FOUND.

Certificate files generated

After generation, keep:

  • certificate.pfx — Private key plus full chain
  • certificate.cer — Public certificate for verification
  • root_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

Terminal window
# Import root CA into Trusted Root Certificate Authorities store
Import-Certificate -FilePath "root_ca_cert.pem" -CertStoreLocation "Cert:\LocalMachine\Root"
# Or for current user only
Import-Certificate -FilePath "root_ca_cert.pem" -CertStoreLocation "Cert:\CurrentUser\Root"

On macOS

Terminal window
# 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 keychain
security add-trusted-cert -d -r trustRoot -k ~/Library/Keychains/login.keychain root_ca_cert.pem

On Linux

Terminal window
# Ubuntu/Debian
sudo cp root_ca_cert.pem /usr/local/share/ca-certificates/nutrient-root-ca.crt
sudo update-ca-certificates
# CentOS/RHEL/Fedora
sudo cp root_ca_cert.pem /etc/pki/ca-trust/source/anchors/nutrient-root-ca.crt
sudo update-ca-trust

Prepare 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:

Terminal window
# View certificate details
openssl x509 -in certificate.cer -text -noout
# Verify certificate validity
openssl verify certificate.cer

Summary

This guide covers a full PDF/UA signing workflow: conversion, certificate setup, visual signature configuration, and final PAdES-compatible signing.