PHP Requires Chilkat v11.7.0+
Chilkat2 PHP
Encrypt and Sign a PDF, and Sign an Encrypted PDF
See more PDF Protection Examples
Demonstrates signing together with encryption. A pending encrypt is applied by SignPdf before it signs, so one call produces a PDF that is both encrypted and signed. A PDF that is already encrypted can be signed too, and stays encrypted. When it was opened with only the user password its permissions decide: adding a signature field needs both the modify and the annotate permission. Loading the PDF with its owner password lifts that.Chilkat PHP Downloads
<?php
use Chilkat2\Cert;
use Chilkat2\JsonObject;
use Chilkat2\Pdf;
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// The PDF used in this example is available at two_page_memo.pdf
// The signing certificate, with its private key.
$cert = new Cert();
try {
$cert->LoadPfxFile('qa_data/pfx/myPdfSigningCert.pfx', 'secret');
$pdf = new Pdf();
$pdf->LoadFile('qa_data/pdf/two_page_memo.pdf');
// Encrypt with AES-256 and do not permit modifying.
$pdf->UserPassword = 'user-secret';
$pdf->OwnerPassword = 'owner-secret';
$json = new JsonObject();
$json->UpdateBool('permissions.modify', false);
$jsonOut = new JsonObject();
$pdf->Protection('encrypt', $json, $jsonOut);
// The encryption is still pending. SignPdf applies it first and signs the encrypted result.
$pdf->SetSigningCert($cert);
$sigOpts = new JsonObject();
$sigOpts->UpdateBool('invisibleSignature', true);
$sigOpts->UpdateInt('signingCertificateV2', 1);
$sigOpts->UpdateInt('signingTime', 1);
$pdf->SignPdf($sigOpts, 'qa_output/memo_encrypted_signed.pdf');
// The result is encrypted and signed.
$check = new Pdf();
$check->UserPassword = 'user-secret';
$check->LoadFile('qa_output/memo_encrypted_signed.pdf');
$empty = new JsonObject();
$info = new JsonObject();
$check->Protection('getInfo', $empty, $info);
} catch (\Chilkat2\Exception $e) {
echo $e->getMessage(), "\n";
exit;
}
echo 'algorithm: ', $info->StringOf('loaded.algorithm'), "\n";
echo 'signatures: ', $check->NumSignatures, "\n";
$sigInfo = new JsonObject();
try {
$check->VerifySignature(0, $sigInfo);
$verified = true;
} catch (\Chilkat2\Exception $e) {
$verified = false;
}
echo 'signature verifies: ', ($verified ? 'true' : 'false'), "\n";
// Signing an encrypted PDF. This one was opened with only the user password, and its
// permissions do not allow modifying, so another signature is refused.
try {
$check->SetSigningCert($cert);
} catch (\Chilkat2\Exception $e) {
echo $e->getMessage(), "\n";
exit;
}
try {
$check->SignPdf($sigOpts, 'qa_output/memo_signed_twice.pdf');
} catch (\Chilkat2\Exception $e) {
echo "A second signature was refused: the permissions do not allow it.\n";
}
// Loaded with the owner password, the same PDF can be signed. It stays encrypted, and the
// first signature stays valid because the new one is added as an incremental update.
$owner = new Pdf();
$owner->UserPassword = 'user-secret';
$owner->OwnerPassword = 'owner-secret';
try {
$owner->LoadFile('qa_output/memo_encrypted_signed.pdf');
$owner->SetSigningCert($cert);
$owner->SignPdf($sigOpts, 'qa_output/memo_signed_twice.pdf');
$twice = new Pdf();
$twice->UserPassword = 'user-secret';
$twice->LoadFile('qa_output/memo_signed_twice.pdf');
} catch (\Chilkat2\Exception $e) {
echo $e->getMessage(), "\n";
exit;
}
echo 'signatures after signing with owner rights: ', $twice->NumSignatures, "\n";
try {
$twice->VerifySignature(0, $sigInfo);
$verified = true;
} catch (\Chilkat2\Exception $e) {
$verified = false;
}
echo 'first signature still verifies: ', ($verified ? 'true' : 'false'), "\n";
try {
$twice->VerifySignature(1, $sigInfo);
$verified = true;
} catch (\Chilkat2\Exception $e) {
$verified = false;
}
echo 'second signature verifies: ', ($verified ? 'true' : 'false'), "\n";
// Sample output:
// algorithm: aes-256
// signatures: 1
// signature verifies: True
// A second signature was refused: the permissions do not allow it.
// signatures after signing with owner rights: 2
// first signature still verifies: True
// second signature verifies: True