Encryption & Permissions
A Document\Security object on the document is all it takes to encrypt what gets written. Set it and
Pdf::writeToFile() produces a password-protected PDF; leave it unset and nothing changes.
Encryption support is consistent across readers in a way form support is not — every mainstream reader opens an AES-encrypted PDF given the password. Permissions are the part that varies: they are flags a reader agrees to honor, not locks the file enforces, so treat them as intent rather than protection.
Password-Protecting a Document#
Security takes a user password and an owner password, and setSecurity() puts it on the document:
use Pop\Pdf\Document;
use Pop\Pdf\Document\Font;
use Pop\Pdf\Document\Page;
use Pop\Pdf\Document\Page\Text;
use Pop\Pdf\Document\Security;
use Pop\Pdf\Pdf;
$document = new Document(new Page(Page::LETTER));
$document->addFont(Font::HELVETICA);
$document->getPage(1)->addText(new Text('Confidential', size: 24), 'Helvetica', x: 72, y: 700);
$document->setSecurity(new Security('open-me', 'admin123'));
Pdf::writeToFile($document, filename: __DIR__ . '/protected.pdf');
The two passwords do different jobs:
- the user password is what opens the document at all, and is subject to the permissions below
- the owner password grants full access regardless of them
- either one may be
null— an owner password left unset is generated for you, so permissions cannot be bypassed by leaving it blank hasSecurity()andgetSecurity()report what a document is carrying; a document with nosetSecurity()call writes out unencrypted
Encryption is AES-256 by default. Security::AES_128 selects the older algorithm, which older readers
are likelier to open:
use Pop\Pdf\Document\Security;
$security = new Security('open-me', algorithm: Security::AES_128);
$security->getAlgorithm(); // 'AES128' — 'AES256' is the default
Restricting What a Reader Allows#
A Permissions object narrows what the document allows once the user password has opened it. Every
permission starts allowed, so only the ones being taken away need naming:
use Pop\Pdf\Document\Permissions;
use Pop\Pdf\Document\Security;
$permissions = new Permissions();
$permissions->allowPrinting(false)->allowCopying(false);
$security = new Security('open-me', 'admin123');
$security->setPermissions($permissions);
The eight permissions, each with an allow*() setter and an is*Allowed() getter:
| Permission | Governs |
|---|---|
allowPrinting() |
printing at all |
allowHighResPrinting() |
printing at full resolution rather than a degraded copy |
allowModifying() |
changing the document's contents |
allowCopying() |
selecting and copying text and graphics |
allowAnnotating() |
adding comments and annotations |
allowFillingForms() |
filling in form fields |
allowExtractingForAccessibility() |
extraction by screen readers and other assistive software |
allowAssembling() |
inserting, rotating and deleting pages |
They compile down to the single integer the PDF specification calls /P, which toPValue() reports:
use Pop\Pdf\Document\Permissions;
$permissions = new Permissions();
$permissions->isPrintingAllowed(); // true — everything starts allowed
$permissions->allowPrinting(false)->allowCopying(false);
$permissions->isPrintingAllowed(); // false
$permissions->toPValue(); // -24
Whether any of it is obeyed is up to the reader, which is why a permission is not a substitute for simply not handing someone the file.
What Gets Encrypted#
Everything Pop PDF writes: page content streams, embedded images, embedded font files, and the literal
strings it authors — metadata, annotation URLs and form field names and values. Compression and
encryption work together, compression first, so setCompression(true) needs no special handling.
One gap is worth knowing before you rely on it. Calling setSecurity() on a document that came from
importFromFile(), importRawData(), merge() or mergeRawData() encrypts every stream, but leaves
literal strings carried over verbatim from the source — an original annotation's URL, an original form
field's name — unencrypted, while the file claims all strings are encrypted. A reader then tries to
decrypt text that was never encrypted and corrupts it. Until that is closed, encrypt documents you
built rather than documents you imported.
See Also#
- Opening Encrypted PDFs — the password argument on the reading side
- Saving & Output — writing the document once its security is set
- Metadata — the
/Infovalues encryption covers along with everything else - Forms & Fields — the other feature whose behavior depends on the reader