Decrypt

Authenticates a password (or private key for public-key mode) against a PDF encryption dictionary and recovers the document file-encryption key.

Namespace: Com\Tecnick\Pdf\Encrypt

Extends: Compute

File: Decrypt.php line 82

Authenticates a password (or private key for public-key mode) against a PDF encryption dictionary and recovers the document file-encryption key.

Usage: $dec = new Decrypt($encrypt->getEncryptionData()); if ($dec->authenticate(‘userpass’)) { $plaintext = $dec->decryptString($ciphertext, $objnum, $gennum); }

A dictionary read out of an existing document is better passed to fromEncryptionDictionary(), which derives the mode from /V, /R and /CFM for the standard handler, and from /V and /CFM for the public-key one.

After successful authentication the derived key is stored internally and:

  • decryptString() decrypts PDF string/stream objects.
  • getObjectKey() returns the per-object key for RC4 and AES-128 streams.
  • getDocumentKey() returns the raw 32-byte (or shorter) file key.
  • getAuthenticatedRole() reports which credential authenticated.
  • getRecipientPermissions() returns the permission bits of the matching recipient in public-key mode.

Limitations:

  • Passwords are used as supplied. ISO 32000-2 section 7.6.4.3.3 calls for SASLprep (RFC 4013) on R5/R6 passwords and ISO 32000-1 expects PDFDocEncoding for R2 to R4, neither of which is applied here, so non-ASCII passwords may not match other implementations.

Tags

  • since: 2026-04-30
  • category: Library
  • author: Nicola Asuni info@tecnick.com
  • copyright: 2011-2026 Nicola Asuni - Tecnick.com LTD
  • license: https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
  • link: https://github.com/tecnickcom/tc-lib-pdf-encrypt
  • phpstan-import-type: TEncryptData from Output
  • phpstan-type: TDecryptInput TEncryptData|array{ ‘V’: int, ‘mode’: int, ‘O’: string, ‘U’: string, ‘P’: int, ‘fileid’: string, ‘Length’?: int, ‘OE’?: string, ‘UE’?: string, ‘perms’?: string, ‘EncryptMetadata’?: bool, ‘pubkey’?: bool, ‘Recipients’?: array<array-key, string>, }
  • SuppressWarnings: (“PHPMD.ExcessiveClassComplexity”)

Constants

DEFAULTPERMS

File: Data.php line 63

public array<string|int, string> DEFAULTPERMS = ['print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high']

Methods

__construct()

File: Decrypt.php line 122

public __construct(TDecryptInput $input) : mixed

Accepts the array returned by Encrypt::getEncryptionData() or any array that satisfies the TDecryptInput shape. Fields not present in the input are filled with the defaults defined in Output::$encryptdata.

Every required entry is checked for presence and type before it is used.

Parameters

  • $input : TDecryptInput: Encryption dictionary fields.

Tags

  • throws: Exception When the dictionary is malformed.

__debugInfo()

File: Output.php line 131

public __debugInfo() : array<string, mixed>

Return values

array<string, mixed>

authenticate()

File: Decrypt.php line 621

public authenticate(string $password[, string $privkeyPath = '' ][, string $passphrase = '' ]) : bool

Tries the supplied string as the owner password first, then as the user password. For public-key mode, $privkeyPath must be the path to a PEM file containing the recipient’s certificate and private key; $password is ignored in that case.

On success the derived file-encryption key is stored internally and getAuthenticatedRole() reports which password matched. For R5 and R6 the password is truncated to 127 bytes and the Perms entry is verified against the recovered key, so a document with tampered permission bits is rejected.

Parameters

  • $password : string: UTF-8 password to test (ignored for pubkey mode).
  • $privkeyPath : string = ‘’: Path to PEM file for public-key mode.
  • $passphrase : string = ‘’: Passphrase of the PEM private key, when it is encrypted.

Tags

Return values

bool —

True when authentication succeeds.

decryptString()

File: Decrypt.php line 690

public decryptString(string $data[, int $objnum = 0 ][, int $gennum = 0 ]) : string

Must be called after a successful authenticate() call.

For RC4 modes (0, 1) the operation is symmetric: the same method that encrypts also decrypts. For AES modes (2, 3, 4) the first 16 bytes of $data are the random IV and the remainder is the ciphertext; the PKCS#7 padding is stripped.

Parameters

  • $data : string: Encrypted string/stream data.
  • $objnum : int = 0: PDF object number (used for per-object key derivation in RC4 and AES-128 modes).
  • $gennum : int = 0: PDF object generation number.

Tags

  • throws: Exception When no key has been recovered, when the AES stream is malformed, or when decryption fails.

Return values

string —

Decrypted data.

encrypt()

File: Compute.php line 51

public encrypt(int|string $type[, string $data = '' ][, string $key = '' ][, int $objnum = 0 ][, int $gennum = 0 ]) : string

Parameters

  • $type : int|string: Encrypt type.
  • $data : string = ‘’: Data string to encrypt.
  • $key : string = ‘’: Encryption key.
  • $objnum : int = 0: Object number.
  • $gennum : int = 0: Object generation number.

Tags

Return values

string

escapeString()

File: Output.php line 146

public escapeString(string $str) : string

Parameters

  • $str : string: String to escape.

Return values

string

fromEncryptionDictionary()

File: Decrypt.php line 184

public static fromEncryptionDictionary(array<string, mixed> $dict) : self

Derives this library’s mode index from /V, /R and the crypt filter method, and accepts /Perms under its PDF name.

The public-key handler is recognised from /Filter /Adobe.PubSec or from the presence of /Recipients, and needs no /R: that entry belongs to the standard handler.

‘fileid’ is not a dictionary entry: it is the first element of the trailer /ID array, from which revisions 2 to 4 derive the key, so the caller has to add it to $dict.

Parameters

  • $dict : array<string, mixed>: Encryption dictionary entries under their PDF names, plus ‘fileid’. /R is required for the standard handler; /CFM is required for R 4.

Tags

  • throws: Exception When the revision is not supported.

Return values

self

getAuthenticatedRole()

File: Decrypt.php line 651

public getAuthenticatedRole() : string|null

In public-key mode the role is ‘recipient’: the applicable permissions are the ones getRecipientPermissions() returns.

Return values

string|null —

‘user’, ‘owner’, ‘recipient’, or null when not authenticated.

getDocumentKey()

File: Decrypt.php line 711

public getDocumentKey() : string

Return values

string —

Raw binary key (empty string before authenticate() succeeds).

getEncPermissionsString()

File: Compute.php line 239

public getEncPermissionsString(int $protection) : string

Parameters

  • $protection : int: 32bit encryption permission value (P value).

Return values

string

getObjectKey()

File: Decrypt.php line 751

public getObjectKey(int $objnum[, int $gennum = 0 ]) : string

Must be called after a successful authenticate() call.

Parameters

  • $objnum : int: Object number.
  • $gennum : int = 0: Object generation number.

Tags

  • throws: Exception When no key has been recovered, or when either number is out of range.

Return values

string

getPdfEncryptionObj()

File: Decrypt.php line 735

public getPdfEncryptionObj(int &$pon) : string

Parameters

  • $pon : int: Current PDF object number.

Tags

Return values

string

getPubKeyPermissionsString()

File: Compute.php line 253

public getPubKeyPermissionsString(int $protection) : string

The byte order is the opposite of the /P key material of getEncPermissionsString().

Parameters

  • $protection : int: 32bit encryption permission value (P value).

Return values

string

getRecipientPermissions()

File: Decrypt.php line 665

public getRecipientPermissions() : int|null

Public-key documents carry no /P entry: each recipient’s permissions travel inside its own PKCS#7 envelope. Returns null outside public-key mode and before authentication.

Return values

int|null —

Signed 32-bit permission value, or null when unavailable.

getRevision()

File: Decrypt.php line 722

public getRevision() : int

Taken from /R when the dictionary carried it, derived from the mode and /V otherwise.

Return values

int

getUserPermissionCode()

File: Compute.php line 285

public getUserPermissionCode(array<string|int, string> $permissions, int $mode) : int

The returned value is a signed 32-bit integer as required by Table 22: reserved bits 7, 8 and 13 to 32 are set, bits 1 and 2 are clear, and every granted permission bit is set.

Parameters

  • $permissions : array<string|int, string>: The set of permissions (specify the ones you want to block).
  • $mode : int: Encryption strength: 0 = RC4-40 (deprecated); 1 = RC4-128 (deprecated); 2 = AES-128; 3 = AES-256 R5; 4 = AES-256 R6 (PDF 2.0 / ISO 32000-2). Revision 2 defines fewer permission bits than the others.

Tags

  • throws: Exception When a permission name is not recognised.

Return values

int