generated from jric11/baseProject
Initial commit
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* E056_encryption_cert_recipients.php
|
||||
*
|
||||
* @since 2026-05-01
|
||||
* @category Library
|
||||
* @package Pdf
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2002-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
|
||||
*
|
||||
* This file is part of tc-lib-pdf software library.
|
||||
*/
|
||||
|
||||
// NOTE: local file reads (images, fonts, attachments) are restricted to an allowlist of
|
||||
// trusted paths that covers this package tree, so run the examples in place. To read assets
|
||||
// from other locations, list them in the 'allowedPaths' entry of the fileOptions constructor
|
||||
// parameter (see E047_remote_resources_security.php).
|
||||
|
||||
// NOTE: run make fonts in the project root to generate the dependencies and example fonts.
|
||||
|
||||
// autoloader when using Composer
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// define fonts directory
|
||||
\define('K_PATH_FONTS', \realpath(__DIR__ . '/../vendor/tecnickcom/tc-lib-pdf-font/target/fonts'));
|
||||
|
||||
/**
|
||||
* Demonstrate certificate-based (public-key) PDF encryption with a permission matrix.
|
||||
*
|
||||
* Certificate-based encryption lets you define a list of recipients; each recipient's
|
||||
* public-key certificate is used to wrap the document key. Only holders of the
|
||||
* corresponding private key can decrypt the document. No shared password is required.
|
||||
*
|
||||
* The example creates two logical recipients from the same demo certificate to show
|
||||
* how different permission sets can be defined per-recipient:
|
||||
* Recipient A – read-only (print only)
|
||||
* Recipient B – reviewer (print + annotate)
|
||||
*
|
||||
* The demo certificate shipped with the examples is a self-signed X.509 cert.
|
||||
* To create your own certificate:
|
||||
* openssl req -x509 -nodes -days 365000 -newkey rsa:2048 \
|
||||
* -keyout cert.pem -out cert.pem
|
||||
*/
|
||||
|
||||
$certPath = \realpath(__DIR__ . '/data/cert/tcpdf.crt');
|
||||
if ($certPath === false) {
|
||||
throw new \RuntimeException('Missing demo certificate: examples/data/cert/tcpdf.crt');
|
||||
}
|
||||
|
||||
$certUri = 'file://' . $certPath;
|
||||
|
||||
$mode = PHP_SAPI === 'cli' ? 'encrypted' : 'preview';
|
||||
if (PHP_SAPI === 'cli') {
|
||||
$mode = (string) ($argv[1] ?? 'encrypted');
|
||||
} elseif (isset($_GET['mode']) && \is_string($_GET['mode'])) {
|
||||
$mode = $_GET['mode'];
|
||||
}
|
||||
|
||||
$mode = \strtolower(\trim($mode));
|
||||
if (!\in_array($mode, ['encrypted', 'preview'], true)) {
|
||||
$mode = PHP_SAPI === 'cli' ? 'encrypted' : 'preview';
|
||||
}
|
||||
|
||||
$useEncryption = $mode === 'encrypted';
|
||||
|
||||
// Build recipient list:
|
||||
// Each entry has 'c' (certificate path/URI) and 'p' (allowed permissions array).
|
||||
$pubkeys = [
|
||||
[
|
||||
'c' => $certUri,
|
||||
'p' => ['print'], // Recipient A: print-only
|
||||
],
|
||||
[
|
||||
'c' => $certUri,
|
||||
'p' => ['print', 'annot-forms'], // Recipient B: print + annotate
|
||||
],
|
||||
];
|
||||
|
||||
$fileId = \md5('E056_encryption_cert_recipients');
|
||||
|
||||
$encrypt = null;
|
||||
if ($useEncryption) {
|
||||
// AES-128 (mode 2) with certificate recipients – no shared password needed.
|
||||
$encrypt = new \Com\Tecnick\Pdf\Encrypt\Encrypt(
|
||||
true, // enabled
|
||||
$fileId,
|
||||
2, // mode: AES-128
|
||||
[], // global permissions (empty – controlled per-recipient)
|
||||
'', // no user password
|
||||
'', // no owner password
|
||||
$pubkeys, // certificate recipients
|
||||
true, // encryptMetadata
|
||||
true, // encryptEmbeddedFiles
|
||||
);
|
||||
}
|
||||
|
||||
// main TCPDF object
|
||||
$pdf = new \Com\Tecnick\Pdf\Tcpdf(
|
||||
unit: \Com\Tecnick\Pdf\Page\Unit::Millimeter,
|
||||
isunicode: true,
|
||||
subsetfont: false,
|
||||
compress: true,
|
||||
mode: \Com\Tecnick\Pdf\PdfConformance::None,
|
||||
objEncrypt: $encrypt,
|
||||
);
|
||||
|
||||
$pdf->setCreator('tc-lib-pdf');
|
||||
$pdf->setAuthor('Nicola Asuni');
|
||||
$pdf->setSubject('tc-lib-pdf example: 056');
|
||||
$pdf->setTitle('Certificate-Based Recipient Encryption');
|
||||
$pdf->setKeywords('TCPDF tc-lib-pdf example encryption certificate recipients public-key');
|
||||
$pdf->setPDFFilename('E056_encryption_cert_recipients.pdf');
|
||||
|
||||
$pdf->setViewerPreferences(['DisplayDocTitle' => true]);
|
||||
|
||||
$pdf->enableDefaultPageContent();
|
||||
|
||||
$bfont = $pdf->font->insert($pdf->pon, 'helvetica', '', 10);
|
||||
$bfontB = $pdf->font->insert($pdf->pon, 'helvetica', 'B', 12);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Page 1 – Overview
|
||||
// -----------------------------------------------------------------------
|
||||
$page1 = $pdf->addPage();
|
||||
$pdf->page->addContent($bfontB['out']);
|
||||
$pdf->page->addContent($pdf->getTextCell(
|
||||
txt: 'Certificate-Based Recipient Encryption',
|
||||
posx: 15,
|
||||
posy: 15,
|
||||
width: 180,
|
||||
height: 0,
|
||||
offset: 0,
|
||||
linespace: 1,
|
||||
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
||||
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
||||
));
|
||||
$pdf->page->addContent($bfont['out']);
|
||||
$pdf->font->insert($pdf->pon, 'helvetica', '', 10);
|
||||
|
||||
$html = <<<HTML
|
||||
<p><b>How it works</b></p>
|
||||
<p>Certificate-based encryption (also called <em>public-key encryption</em>) wraps the
|
||||
document encryption key using each recipient's X.509 public-key certificate.
|
||||
No shared password is distributed; only the holder of the matching private key can
|
||||
open the document.</p>
|
||||
|
||||
<p><b>Recipient permission matrix</b></p>
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<th>Recipient</th>
|
||||
<th>Certificate</th>
|
||||
<th>Allowed permissions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recipient A (read-only)</td>
|
||||
<td>tcpdf.crt (demo)</td>
|
||||
<td>print</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recipient B (reviewer)</td>
|
||||
<td>tcpdf.crt (demo)</td>
|
||||
<td>print, annot-forms</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><b>Encryption parameters</b></p>
|
||||
<ul>
|
||||
<li>Output mode: MODE_PLACEHOLDER</li>
|
||||
<li>Algorithm: AES-128 (mode 2) when mode is <em>encrypted</em></li>
|
||||
<li>Metadata encrypted: yes (encrypted mode)</li>
|
||||
<li>Embedded files encrypted: yes (encrypted mode)</li>
|
||||
<li>User/owner password: none (certificate recipients only, encrypted mode)</li>
|
||||
</ul>
|
||||
|
||||
<p><b>Creating your own certificate</b></p>
|
||||
<p>Use the following OpenSSL command to generate a self-signed certificate suitable for
|
||||
recipient encryption:</p>
|
||||
<p><em>openssl req -x509 -nodes -days 365000 -newkey rsa:2048 -keyout cert.pem -out cert.pem</em></p>
|
||||
HTML;
|
||||
|
||||
$modeLabel = $useEncryption ? 'encrypted (certificate recipients)' : 'preview (unencrypted for browser compatibility)';
|
||||
|
||||
$html = \str_replace('MODE_PLACEHOLDER', $modeLabel, $html);
|
||||
|
||||
$pdf->addHTMLCell(html: $html, posx: 15, posy: 30, width: 180);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Page 2 – Permissions reference
|
||||
// -----------------------------------------------------------------------
|
||||
$page2 = $pdf->addPage();
|
||||
$pdf->page->addContent($bfontB['out']);
|
||||
$pdf->page->addContent($pdf->getTextCell(
|
||||
txt: 'PDF Permission Flags Reference',
|
||||
posx: 15,
|
||||
posy: 15,
|
||||
width: 180,
|
||||
height: 0,
|
||||
offset: 0,
|
||||
linespace: 1,
|
||||
valign: \Com\Tecnick\Pdf\TextVAlign::Top,
|
||||
halign: \Com\Tecnick\Pdf\TextHAlign::Left,
|
||||
));
|
||||
$pdf->page->addContent($bfont['out']);
|
||||
$pdf->font->insert($pdf->pon, 'helvetica', '', 10);
|
||||
|
||||
$html2 = <<<HTML
|
||||
<p><b>Available permission identifiers</b></p>
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr><th>Identifier</th><th>Description</th></tr>
|
||||
<tr><td>print</td><td>Print the document (low-quality).</td></tr>
|
||||
<tr><td>modify</td><td>Modify document content (not covered by more specific flags).</td></tr>
|
||||
<tr><td>copy</td><td>Copy or extract text and graphics.</td></tr>
|
||||
<tr><td>annot-forms</td><td>Add/modify annotations and fill interactive forms.</td></tr>
|
||||
<tr><td>fill-forms</td><td>Fill in existing interactive form fields.</td></tr>
|
||||
<tr><td>extract</td><td>Extract content for accessibility.</td></tr>
|
||||
<tr><td>assemble</td><td>Insert/rotate/delete pages, create bookmarks and thumbnails.</td></tr>
|
||||
<tr><td>print-high</td><td>Print at high quality (faithful digital reproduction).</td></tr>
|
||||
</table>
|
||||
|
||||
<p><b>Notes</b></p>
|
||||
<ul>
|
||||
<li>With certificate recipients, permission flags are embedded inside the CMS enveloped-data
|
||||
structure for each recipient separately.</li>
|
||||
<li>Viewer enforcement of permissions depends on the PDF reader implementation.</li>
|
||||
<li>Combining certificate encryption with a digital signature (E057) provides both
|
||||
access control and document integrity assurance.</li>
|
||||
</ul>
|
||||
HTML;
|
||||
|
||||
$pdf->addHTMLCell(html: $html2, posx: 15, posy: 30, width: 180);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Output
|
||||
// -----------------------------------------------------------------------
|
||||
$rawpdf = $pdf->getOutPDFString();
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
if ($useEncryption) {
|
||||
// Most browser-native PDF viewers do not support certificate-based decryption.
|
||||
// Force a download so the file can be opened with a compatible PDF reader.
|
||||
$pdf->downloadPDF(rawpdf: $rawpdf);
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdf->renderPDF(rawpdf: $rawpdf);
|
||||
exit();
|
||||
}
|
||||
|
||||
echo $rawpdf;
|
||||
Reference in New Issue
Block a user