Перейти к содержимому

Безопасность и эксплуатация compat-legacy

Адаптер использует модель безопасности движка NextPDF и добавляет несколько намеренных усилений относительно унаследованного TCPDF 6.2.13. На этой странице без преувеличений описано, что доступно, а что нет. Внимательно прочитайте раздел о подписании: его область действия намеренно узкая.

Усиленное поведение унаследованного кода

Заголовок раздела «Усиленное поведение унаследованного кода»

Из соображений безопасности адаптер изменяет три исторических варианта поведения TCPDF 6.2.13. Их нельзя вернуть к небезопасному виду через настройку:

ПроблемаУнаследованный TCPDF 6.2.13Адаптер
Обработка ошибокError() вызывает die() и завершает процессError() выбрасывает RuntimeException; вызывающий код может обнаружить сбой и перехватить его без скрытого завершения процесса.
Выполнение HTMLЛазейка могла выполнять PHP из разметкиКонстанта K_TCPDF_CALLS_IN_HTML жёстко задана как false; разметка не может запустить выполнение PHP.
Прямой выводOutput() выводит данные в активный буфер выводаВывод проходит через безопасный мост назначения и не загрязняет буфер вывода, управляемый вызывающим кодом.

Изменение обработки ошибок гарантирует, что вы сможете увидеть сбой, а не потерять процесс из-за завершения. Стандарт Open Worldwide Application Security Project (OWASP) Application Security Verification Standard (ASVS) 5.0 §16.5.3 требует, чтобы приложение при сбое вело себя корректно и безопасно и не допускало состояний fail-open. Замена die() на выброс исключения применяет этот принцип. Усиление безопасности HTML устраняет точку выполнения кода. Если унаследованный код зависел от старого поведения, считайте это дефектом, который нужно исправить в ходе /integrations/tcpdf-compat/migration/. Зафиксированный дайджест пункта находится во front-matter страницы citations.

Адаптер предоставляет метод SetProtection() из TCPDF и делегирует работу стандартному обработчику безопасности движка NextPDF.

  • Стандартный обработчик использует AES-256. Унаследованный параметр $mode принимается для совместимости с сигнатурой метода и игнорируется; выбрать более слабый шифр через этот метод невозможно. Если включён строгий режим, значение $mode, отличное от значения по умолчанию, приводит к выбросу исключения, чтобы это было учтено при миграции (проверяется в tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php).
  • Если пароль владельца не задан, адаптер генерирует криптографически стойкий случайный пароль владельца вместо повторного использования пароля пользователя. Это не даёт обладателям доступа на уровне пользователя получить контроль над документом на уровне владельца.
  • Шифрование на основе сертификатов (с открытым ключом) не выполняется через SetProtection(); адаптер игнорирует его параметр $pubkeys. Используйте предоставляемую адаптером современную точку входа для шифрования с открытым ключом (setPublicKeyEncryption()), которая делегирует работу движку.

Поведение шифрования отражает стандартный обработчик безопасности, описанный в ISO 32000-2 §7. Этот пункт определяет записи словаря шифрования и стандартный обработчик AES-256, который использует движок. Эта документация не утверждает, что результат является “безопасным по умолчанию” или “защищённым от подделки”. Она указывает только используемый шифр и реализованное в коде поведение пароля владельца. Зафиксированный дайджест пункта находится во front-matter страницы citations.

examples/security-encryption.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, 'Encrypted document');
// User password set; owner password auto-generated (strong, random).
$pdf->SetProtection([], 'user-secret');
$pdf->Output(__DIR__ . '/encrypted.pdf', 'F');

Цифровые подписи — заявление об области действия

Заголовок раздела «Цифровые подписи — заявление об области действия»

Читайте этот раздел буквально. Он намеренно консервативен.

  • Унаследованные методы TCPDF setSignature() и addEmptySignatureAppearance() не реализованы в адаптере на базовом движке. В режиме по умолчанию они ничего не делают. В строгом режиме они выбрасывают TcpdfNotImplementedException.
  • Цифровое подписание не входит в базовую поставку через этот адаптер. Поддержка базовой подписи требует коммерческой редакции NextPDF.
  • Если присутствует коммерческая редакция, адаптер предоставляет современную точку входа для подписи (setSignatureV2()), которая делегирует работу движку. Профиль по умолчанию для неё — базовый (B-B).
  • Эта документация не утверждает, что какая-либо редакция создаёт через этот адаптер профили подписи с метками времени, долгосрочной проверкой или архивные профили. В частности, она не заявляет о поддержке B-T, B-LT или B-LTA. Базовая спецификация PDF Advanced Electronic Signatures (PAdES) §6.1 определяет четыре отдельных базовых уровня: B-B, B-T, B-LT и B-LTA. У каждого уровня свои требования. B-B — это базовый уровень, а более высокие уровни (метка времени, долгосрочный, архивный) являются отдельными, более требовательными профилями. В область действия документации этого слоя совместимости входит только базовый уровень B-B. Более высокие уровни явно находятся вне области действия и здесь не заявлены ни для одной редакции. Зафиксированный дайджест пункта находится во front-matter страницы citations.
  • Эта документация нигде не заявляет, что подпись является “сертифицированной”, “гарантированной”, “юридически действительной” или “квалифицированной по eIDAS”. Корректность подписи, политика доверенных якорей и юридическая действительность относятся к ответственности редакции, выполняющей подписание, и инфраструктуры открытых ключей (PKI) вызывающей стороны, а не этого слоя совместимости.

Если ваша миграция требует подписания, рассматривайте это как отдельное направление работ: примените современный API подписи в коммерческой редакции и проверьте полученную подпись независимым верификатором. Не полагайтесь на вызов setSignature() из TCPDF; здесь он ничего не делает.

Унаследованный метод setTimeStamp() принимается для совместимости с сигнатурой метода и выдаёт уведомление; он не создаёт подпись с меткой времени через этот адаптер.

Флаг конструктора pdfa принимается для совместимости с сигнатурой метода. Соответствие архивному формату PDF/A требует коммерческой редакции NextPDF. Адаптер предоставляет enablePdfA(), который делегирует работу движку, а движок возвращает понятную ошибку конфигурации, когда требуемая редакция отсутствует. Адаптер не создаёт файл, скрытно не соответствующий требованиям, но заявленный как PDF/A.

Результат всегда PDF 2.0 (ISO 32000-2). ISO 32000-2 §7.5.2 устанавливает, что соответствующий записывающий компонент идентифицирует версию документа как 2.0 и не понижает её до более старой версии при сохранении. Поэтому setPDFVersion() не может назначить более старую версию как целевую (см. /integrations/tcpdf-compat/method-coverage/ §4). Зафиксированный дайджест пункта находится во front-matter страницы citations.

  • Без завершения процесса. Поскольку Error() выбрасывает исключение вместо die(), оборачивайте точки входа отрисовки в try/catch и сопоставляйте сбои с контрактом ошибок вашего приложения. Не считайте, что сбой отрисовки завершает запрос.
  • Безопасность буфера вывода. Output() с S возвращает байты; с F записывает файл; с E возвращает тело Multipurpose Internet Mail Extensions (MIME) в base64; с I/D направляет вывод через путь вывода движка. Предпочитайте S или F в обработчиках задач и HTTP, чтобы самостоятельно управлять ответом; см. /integrations/tcpdf-compat/production-usage/.
  • Строгий режим не предназначен для производственной среды. Используйте его только в задачах непрерывной интеграции (CI) или аудита. Исключение на пути отрисовки в производственной среде хуже, чем скрытно ослабленный параметр.
  • Гигиена констант. Определяйте константы PDF_* / K_* до первого создания адаптера. Два усиленных флага (K_TCPDF_CALLS_IN_HTML, K_TCPDF_THROW_EXCEPTION_ERROR) ослабить нельзя; не пытайтесь это сделать.
  • Случайные пароли владельца. Если вы полагаетесь на детерминированный пароль владельца, задайте его явно. Иначе стойкий случайный пароль генерируется для каждого документа и не подлежит восстановлению.
  • Для методов работы с изображениями адаптер отклоняет путь с обёрткой потока до любого чтения из файловой системы. Определение типа изображения (TcpdfImages::getImageFileType) рассматривает любой путь scheme://, включая phar://, php:// и другие обёртки потоков PHP, как обёртку и пропускает проверку file_get_contents / getimagesize, переходя к определению только по расширению. Это закрывает вектор десериализации метаданных phar для целевой среды бэкпорта на PHP 7.4; движок сам отклоняет встраивание по пути с обёрткой.
  • Адаптер не добавляет проверку или очистку путей к файлам, передаваемых в методы работы с изображениями или вывода, помимо той, которую выполняет движок. Рассматривайте пути и URL, предоставленные вызывающим кодом, как недоверенные на границе вашего приложения.
  • HTML, передаваемый в методы HTML, отрисовывается движком, а не парсером HTML TCPDF. Унаследованная точка выполнения PHP закрыта, но вам всё равно следует рассматривать HTML, предоставленный вызывающим кодом, как недоверенный ввод.
  • Шифрование защищает конфиденциальность документа в состоянии покоя под управлением стандартного обработчика. Оно не заменяет безопасность транспортного уровня или контроль доступа в вашем приложении.
  • /integrations/tcpdf-compat/method-coverage/ — точное поведение SetProtection(), setSignature()
  • /integrations/tcpdf-compat/configuration/ — два усиленных ненастраиваемых флага
  • /integrations/tcpdf-compat/production-usage/ — обработчики задач, буферы, обработка сбоев
  • docs/TCPDF_COVERAGE.md — авторитетная матрица охвата
  • Файл NOTICE пакета — заявление о независимой реализации