Docs 1.24.0: PDF/A, passwords and watermarks
Download PDF Changelog

This is the manual for PdfPecker 1.24.0. Read it for the latest version, 1.25.0.

PDF/A, passwords and watermarks

Changed in 1.24.0: Watermarks and passwords.

Watermarks and passwords Changed in 1.24.0

var options = new PdfOptions
{
    // A diagonal stamp on every page. Also: Image (PNG, JPEG, GIF, WebP, BMP, TIFF or SVG bytes; SVG stays vector), FontSize, LetterSpacing, Angle, Opacity, Bold, Behind.
    Watermark = new PdfWatermark { Text = "WATERMARK", Color = "#c00000", Opacity = 0.25f },

    // AES-256 encryption (PDF 2.0 / Acrobat X and later). Without an OwnerPassword a random one is used,
    // so the permissions cannot be lifted.
    Security = new PdfSecurity
    {
        UserPassword = "1234",                                   // needed to open the file; null = opens freely
        OwnerPassword = "owner-secret",                          // full access
        Permissions = PdfPermissions.Print | PdfPermissions.Copy,
    },
};

PDF/A

For archiving, set Conformance = PdfConformance.PdfA2b (or another level below): the PDF gets XMP metadata, an sRGB output intent and a file ID, and CMYK JPEGs are converted to RGB. All fonts are embedded: text without a registered font uses the bundled Liberation fonts (see Fonts). PDF/A does not allow encryption, so combining Conformance with Security throws an ArgumentException.

var options = new PdfOptions { Conformance = PdfConformance.PdfA4 };
Level Standard File Use it for
PdfA2b, PdfA3b ISO 19005-2/-3, level B PDF 1.7 the usual archive format; part 3 also allows attachments (e-invoices)
PdfA2u, PdfA3u ISO 19005-2/-3, level U PDF 1.7 as level B, plus a Unicode mapping for every character, so text can be searched and copied
PdfA4 ISO 19005-4:2020 PDF 2.0 the current part; identified in the XMP only (pdfaid:rev 2020, no conformance letter), no document information dictionary
PdfA4f ISO 19005-4:2020, with files PDF 2.0 PDF/A-4 with attachments: only with EInvoice (it throws without one)

Every font is embedded with a ToUnicode map, and a character no font has is left out as blank space rather than drawn as .notdef (in SVG text too), so levels U cost nothing over B. A PDF 2.0 file keeps the title, author, keywords and custom properties in its XMP metadata, since PDF 2.0 deprecates the information dictionary. Every level, on its own and with PDF/UA, passes veraPDF 1.28 (flavours 2b, 2u, 3b, 3u, 4 and 4f) on documents with text, tables, lists, images, links, form fields, SVG and Markdown. AES-256 keys come from a password hash that is slow on purpose, which adds about 3 ms to a conversion.

Passwords are prepared with SASLprep before they are hashed, as PDF 2.0 requires and as pypdf and PDFBox do, so a password typed in another normalization form (é as one character or as e and an accent) opens the file as it does in other PDF 2.0 readers. A password with control, private-use or bidi control characters, or with characters Unicode 3.2 had not assigned (most emoji), cannot be prepared and is refused with an ArgumentException. Files encrypted elsewhere with such passwords still open.

To make a PDF you already have into PDF/A, whichever tool made it, see PDF to PDF/A.

Passwords on existing PDFs

To add, change or remove the password of a PDF you already have (from any producer, not only PdfPecker), use PdfProtector:

// Encrypt any PDF with AES-256
byte[] locked = PdfProtector.Encrypt(pdf, new PdfSecurity { UserPassword = "1234", Permissions = PdfPermissions.Print });

// Change the passwords or permissions of an encrypted PDF (give its current user or owner password)
byte[] relocked = PdfProtector.Encrypt(locked, new PdfSecurity { UserPassword = "5678" }, password: "1234");

// Remove the encryption, and with it the permission restrictions
byte[] open = PdfProtector.Decrypt(locked, "1234");

// Stream overloads, and a check
PdfProtector.Encrypt(inputStream, outputStream, security);
bool encrypted = PdfProtector.IsEncrypted(pdf);

Encrypted inputs can use RC4 (40 to 128 bit), AES-128 or AES-256; the output of Encrypt is always AES-256. Like other PDF tools, PdfProtector accepts the user password as well as the owner password (or none, for a file that only restricts permissions), so anyone who can open a document can also lift its permissions. A wrong password throws PdfPasswordException. The document is rewritten as a whole and keeps its pages, bookmarks, links, form fields and values, tags, metadata, page labels and attachments; earlier revisions from incremental updates are dropped. Signed PDFs are refused with an ArgumentException (rewriting them would break the signatures; sign after encrypting instead), as is encrypting a PDF/A file, or a PDF/UA file without PdfPermissions.ExtractForAccessibility. Decrypt returns a PDF that is not encrypted unchanged.

Watermark applies while converting HTML; to stamp a PDF you already have, see Stamping PDFs.