Security & Files
This page covers three slices of the spec that share the “attach extra content to the document” theme — encryption (who can read), embedded files (extra payloads), and 3D annotations (interactive viewports).
Public-key encryption
Section titled “Public-key encryption”PdfEncryptor::publicKeyAes256() seals the PDF for one or more X.509 recipients. Only the holder of a matching private key can open it. The example generates a throwaway keypair so it runs anywhere; in production you would import a recipient’s certificate.
use Phpdftk\Pdf\Core\Font\StandardFont;use Phpdftk\Pdf\Core\Font\Type1Font;use Phpdftk\Pdf\Core\Security\PdfEncryptor;use Phpdftk\Pdf\Writer\PdfWriter;
// Public-key encryption locks the PDF to one or more X.509 recipients. Each// recipient unlocks the document with their own private key — no shared password.// Here we generate a throwaway RSA keypair and self-signed cert so the example// runs anywhere. In production, you would import a recipient's certificate.$config = [ 'digest_alg' => 'sha256', 'private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA,];$privateKey = openssl_pkey_new($config);$csr = openssl_csr_new(['commonName' => 'phpdftk-recipient'], $privateKey, $config);$cert = openssl_csr_sign($csr, null, $privateKey, 365, $config);openssl_x509_export($cert, $certPem);openssl_pkey_export($privateKey, $keyPem);
// Save the keypair alongside the PDF so docs can demonstrate decryption.$samplesDir = dirname(example_output_path('core/security/public-key.pdf'));file_put_contents($samplesDir . '/recipient.cert.pem', $certPem);file_put_contents($samplesDir . '/recipient.key.pem', $keyPem);
$writer = new PdfWriter();$page = $writer->addPage();$body = $writer->addFont(new Type1Font(StandardFont::Helvetica))->getResourceName();$bold = $writer->addFont(new Type1Font(StandardFont::HelveticaBold))->getResourceName();
$cs = $writer->addContentStream($page);$cs->beginText()->setFont($bold, 20)->moveTextPosition(72, 720) ->showText('Public-Key Encrypted PDF')->endText();$cs->beginText()->setFont($body, 12)->moveTextPosition(72, 690) ->showText('This document is sealed for a single X.509 recipient.') ->endText();$cs->beginText()->setFont($body, 12)->moveTextPosition(72, 670) ->showText('Only the holder of the matching private key can open it.') ->endText();$cs->beginText()->setFont($body, 12)->moveTextPosition(72, 650) ->showText('Recipient certificate and key are written next to this file.') ->endText();
$fileId = md5('phpdftk-public-key-showcase', true);$encryptor = PdfEncryptor::publicKeyAes256( recipients: [['cert' => $certPem]], fileId: $fileId,);$writer->setEncryption($encryptor);
$writer->save('public-key.pdf');📄 View the sample PDF · View the full script on GitHub ↗
The generated recipient.cert.pem and recipient.key.pem are written next to the PDF so you can decrypt it locally.
Embedded files (Attachments panel)
Section titled “Embedded files (Attachments panel)”FileAttachmentAnnotation exposes embedded files at fixed positions on the page. Names → EmbeddedFiles is the document-wide equivalent — files show up in any viewer’s Attachments panel without consuming page space.
use Phpdftk\Pdf\Core\Document\NameTree;use Phpdftk\Pdf\Core\Document\NamesDictionary;use Phpdftk\Pdf\Core\FileSpec\EmbeddedFile;use Phpdftk\Pdf\Core\FileSpec\FileSpec;use Phpdftk\Pdf\Core\Font\StandardFont;use Phpdftk\Pdf\Core\Font\Type1Font;use Phpdftk\Pdf\Core\PdfArray;use Phpdftk\Pdf\Core\PdfReference;use Phpdftk\Pdf\Core\PdfString;use Phpdftk\Pdf\Writer\PdfWriter;
// FileAttachment annotations expose embedded files at fixed page locations.// /Names → /EmbeddedFiles makes the same files available document-wide —// they show up in any viewer's "Attachments" panel without taking page space.$writer = new PdfWriter();$page = $writer->addPage();$body = $writer->addFont(new Type1Font(StandardFont::Helvetica))->getResourceName();$bold = $writer->addFont(new Type1Font(StandardFont::HelveticaBold))->getResourceName();
$cs = $writer->addContentStream($page);$cs->beginText()->setFont($bold, 22)->moveTextPosition(72, 740) ->showText('Embedded Files (Attachments Panel)')->endText();$cs->beginText()->setFont($body, 12)->moveTextPosition(72, 706) ->showText('Open the Attachments panel in any viewer to download the files below.') ->endText();
$attachments = [ ['hello.txt', 'Plain-text greeting', "Hello from inside the PDF.\n"], ['report.csv', 'CSV report data', "month,visits\nJan,1240\nFeb,1430\nMar,1700\n"], ['config.json', 'Sample configuration', json_encode(['version' => '1.0', 'mode' => 'demo'], JSON_PRETTY_PRINT)],];
// Build the names tree: an alternating array of name strings and FileSpec references.$namesArray = [];$y = 660;foreach ($attachments as [$filename, $description, $payload]) { $embedded = new EmbeddedFile($payload); $writer->register($embedded);
$fs = new FileSpec($filename); $fs->desc = new PdfString($description); $fs->attachEmbeddedFile(new PdfReference($embedded->objectNumber)); $writer->register($fs);
$namesArray[] = new PdfString($filename); $namesArray[] = new PdfReference($fs->objectNumber);
// Render a line on the page so the viewer also sees the file inventory. $cs->beginText()->setFont($bold, 12)->moveTextPosition(72, $y) ->showText($filename)->endText(); $cs->beginText()->setFont($body, 12)->moveTextPosition(220, $y) ->showText($description)->endText(); $y -= 24;}
// Wire the embedded-files name tree into the catalog's /Names dictionary.$nameTree = new NameTree();$nameTree->names = new PdfArray($namesArray);$writer->register($nameTree);
$names = new NamesDictionary();$names->embeddedFiles = new PdfReference($nameTree->objectNumber);$writer->register($names);
$writer->getCatalog()->names = new PdfReference($names->objectNumber);
$writer->save('embedded-file.pdf');📄 View the sample PDF · View the full script on GitHub ↗
3D annotations
Section titled “3D annotations”A ThreeDAnnotation reserves a viewport on the page and binds a U3D or PRC model stream, a default view, and rendering parameters (background, lighting, render mode). The example below wires the full object graph using placeholder model bytes — substitute a real .u3d file in production.
use Phpdftk\Pdf\Core\Annotation\ThreeDAnnotation;use Phpdftk\Pdf\Core\Font\StandardFont;use Phpdftk\Pdf\Core\Font\Type1Font;use Phpdftk\Pdf\Core\Graphics\ColorSpace\DeviceRGB;use Phpdftk\Pdf\Core\PdfArray;use Phpdftk\Pdf\Core\PdfName;use Phpdftk\Pdf\Core\PdfNumber;use Phpdftk\Pdf\Core\ThreeD\ThreeDBackground;use Phpdftk\Pdf\Core\ThreeD\ThreeDLightingScheme;use Phpdftk\Pdf\Core\ThreeD\ThreeDRenderMode;use Phpdftk\Pdf\Core\ThreeD\ThreeDStream;use Phpdftk\Pdf\Core\ThreeD\ThreeDView;use Phpdftk\Pdf\Writer\PdfWriter;
// 3D annotations carry a U3D or PRC payload along with viewport, background, lighting// and render-mode configuration. This example wires the full object graph using// placeholder model bytes — substitute a real .u3d file in production.$writer = new PdfWriter();$page = $writer->addPage();$body = $writer->addFont(new Type1Font(StandardFont::Helvetica))->getResourceName();$bold = $writer->addFont(new Type1Font(StandardFont::HelveticaBold))->getResourceName();
$cs = $writer->addContentStream($page);$cs->beginText()->setFont($bold, 22)->moveTextPosition(72, 740) ->showText('3D Annotation')->endText();$cs->beginText()->setFont($body, 11)->moveTextPosition(72, 706) ->showText('A 3D viewport is reserved below. Viewers with 3D support load the') ->endText();$cs->beginText()->setFont($body, 11)->moveTextPosition(72, 690) ->showText('embedded U3D stream into the box and let users rotate/pan/zoom.') ->endText();
// 1) U3D model stream. Real applications supply real geometry; the structure// is the same.$u3d = new ThreeDStream('U3D', "U3D PLACEHOLDER MODEL DATA — substitute a real file in production.");$u3d->colorSpace = new DeviceRGB();$u3dRef = $writer->register($u3d);
// 2) Default view: camera/coords/background/render/lighting.$bg = new ThreeDBackground();$bg->cs = new DeviceRGB();$bg->c = new PdfArray([new PdfNumber(0.96), new PdfNumber(0.97), new PdfNumber(0.99)]);$bgRef = $writer->register($bg);
$rm = new ThreeDRenderMode('Solid');$rm->op = 1.0;$rmRef = $writer->register($rm);
$ls = new ThreeDLightingScheme('Day');$lsRef = $writer->register($ls);
$view = new ThreeDView('DefaultView');$view->co = 120.0;$view->ms = new PdfName('M');$view->bg = $bgRef;$view->rm = $rmRef;$view->ls = $lsRef;$viewRef = $writer->register($view);
$u3d->va = new PdfArray([$viewRef]);$u3d->dv = $viewRef;
// 3) Annotation: the rectangle on the page where the 3D viewport renders.$annot = new ThreeDAnnotation(new PdfArray([ new PdfNumber(72), new PdfNumber(200), new PdfNumber(540), new PdfNumber(660),]));$annot->dd = $u3dRef;$annot->di = true;$annot->db = new PdfArray([ new PdfNumber(0), new PdfNumber(0), new PdfNumber(1), new PdfNumber(1),]);$page->corePage()->annots[] = $writer->register($annot);
$writer->save('3d-annotation.pdf');