Sample code for 30+ languages & platforms
PHP Requires Chilkat v11.7.0+

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

Chilkat2 PHP
<?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