Безопасность: шифрование, криптополитика и поверхность подписания
Модуль безопасности Core применяет 256-битное шифрование документов Advanced Encryption Standard (AES-256), проводит каждый выбор алгоритма через контракт криптополитики и предоставляет точки интеграции для службы управления ключами, управляемой на уровне развёртывания. Реальная защита документа зависит от работы с ключами, надёжности пароля, читающего приложения и среды развёртывания. Эта страница явно описывает эти границы.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Концептуальный обзор
Заголовок раздела «Концептуальный обзор»У модуля безопасности три поверхности. Поверхность шифрования использует точку входа документа setEncryption() для настройки обработчика безопасности Standard на основе AES-256. Криптополитика использует CryptoPolicyInterface, чтобы определить, какие алгоритмы хеширования, подписи, шифрования и какую стойкость ключа разрешает развёртывание. Поверхность подписания упомянута здесь, но описана отдельно; см. Подписание.
Шифрование использует AES-256, как определено в ISO 32000-2:2020 §7.6. По умолчанию используется обработчик безопасности Standard V=5 / R=6 с фильтром шифрования AESV3. Ключ файла занимает 32 байта (256 бит), что соответствует Federal Information Processing Standards (FIPS) 197. Дополнительный путь добавляет аутентифицированное шифрование ISO/TS 32003:2023 V=6 / R=7 AES-256 in Galois/Counter Mode (AES-256-GCM). Подробная страница описывает оба пути: Шифрование.
Криптополитика — это предикат “запретить или разрешить”. Core обращается к CryptoPolicyInterface перед любым шагом подписания, шифрования или хеширования. Если политика не задана, Core разрешает любой алгоритм. Такое открытое значение по умолчанию подходит для разработки, но не для продакшена. В регулируемом развёртывании нужно задать явную политику. Contracts / Security Policy описывает поверхность контракта.
Флаги разрешений чаще всего становятся источником завышенных заявлений, поэтому эта страница говорит об этом прямо. Битовая маска разрешений хранится в зашифрованной записи /Perms и в значении /P. Ожидается, что читающее приложение, соответствующее стандарту, соблюдает эти ограничения. Криптография не обеспечивает соблюдение этих флагов. Обработчик, который игнорирует биты, всё равно может читать, копировать или изменять содержимое после получения ключа расшифровки. Указывайте это ограничение любой стороне, которая полагается на флаги разрешений.
Управление ключами и интеграция Public-Key Cryptography Standards #11 (PKCS#11) — это точки контракта. Core поставляет путь с локальным ключом. Объект-значение KeyMaterial оборачивает 256-битный ключ, проверяет длину и предотвращает раскрытие в строковом и отладочном выводе. Путь хранения ключей через hardware security module (HSM)/PKCS#11 — это возможность Enterprise, защищённая теми же контрактами; эта страница называет точку интеграции, но не описывает реализацию Enterprise.
Поверхность API
Заголовок раздела «Поверхность API»| Тип | Вид | Ключевые элементы | Стабильность | С версии |
|---|---|---|---|---|
Document::setEncryption() | метод (трейт HasSecurity) | userPassword, ownerPassword, permissions | стабильно | 1.0.0 |
Document::useAesGcm() | метод (трейт HasSecurity) | ?bool $enabled — дополнительный ISO/TS 32003 V=6/R=7 | стабильно | 2.18.0 |
Aes256Encryptor | класс | encrypt(), decrypt(), buildEncryptionDictionary(), verifyUserPassword(), verifyOwnerPassword(), validatePerms() | стабильно | 1.0.0 |
Aes256GcmEncryptor | класс | encrypt(), decrypt(), encryptStream(), assertWithinSafetyBound(), invocationCount() | стабильно | 2.18.0 |
KeyMaterial | final readonly class | generate(), exposeKey(), fingerprint() | стабильно | 2.18.0 |
CryptoPolicyInterface | интерфейс | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | стабильно | 1.9.0 |
Config::withCryptoPolicy() | метод | CryptoPolicyInterface $policy | стабильно | 1.9.0 |
CryptoCapabilities | final class | hasAesGcm(), detectFipsMode(), assertFipsAvailableForProfile() | стабильно | 2.0.0 |
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Encrypted Document — Restricted Permissions');
// Call setEncryption() BEFORE addPage().// Permission bit 3 (value 4) = printing allowed; all other operations denied.$doc->setEncryption( userPassword: 'demo', ownerPassword: 'admin', permissions: 4,);
$doc->addPage();$doc->setFont('helvetica', 'B', 20);$doc->cell(0, 14, 'Encrypted PDF Document', newLine: true);
$doc->save(__DIR__ . '/output/22-protection.pdf');Пользовательский пароль открывает документ. Пароль владельца даёт полный доступ. Флаги разрешений ограничивают только читающее приложение, которое соблюдает стандарт.
Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;use NextPDF\Core\Document;use Psr\Log\LoggerInterface;
final readonly class PolicyGatedEncryption{ public function __construct( private CryptoPolicyInterface $cryptoPolicy, private LoggerInterface $logger, ) {}
/** * Encrypt only when the active policy permits AES-256-CBC. * * @param non-empty-string $userPassword Opens the document. * @param non-empty-string $ownerPassword Grants full access. */ public function protect( Document $doc, string $userPassword, string $ownerPassword, int $permissions, ): void { if (!$this->cryptoPolicy->isEncryptionAlgorithmAllowed('aes-256-cbc')) { $this->logger->error('Encryption refused by crypto policy', [ 'policy' => $this->cryptoPolicy->getName(), ]);
throw new \RuntimeException('AES-256-CBC denied by the active crypto policy.'); }
$doc->setEncryption($userPassword, $ownerPassword, $permissions);
$this->logger->info('Document encrypted', [ 'policy' => $this->cryptoPolicy->getName(), 'algorithm' => 'aes-256-cbc', ]); }}Код обращается к политике перед шифрованием, записывает имя политики в журнал аудита и выбрасывает конкретное исключение, когда политика запрещает шифр.
Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Вызывайте
setEncryption()доaddPage(). Более поздний вызов не шифрует задним числом содержимое, которое модуль записи уже вывел. - Режим PDF/A и шифрование несовместимы. ISO 19005 запрещает ключ трейлера
Encryptво всех разновидностях PDF/A, поэтомуsetEncryption()иuseAesGcm()выбрасывают исключение, когда активен менеджер PDF/A. - Внутри
setEncryption()пустой пароль владельца заменяется на пользовательский пароль. Если документ использует один общий пароль, обладатель пользовательского пароля получает доступ уровня владельца. - Когда политика не внедрена,
CryptoPolicyInterfaceразрешает любой алгоритм. Воспринимайте открытое значение по умолчанию как удобство для разработки и задавайте явную политику в любом регулируемом развёртывании. - Флаги разрешений носят рекомендательный характер для читающего приложения. Не описывайте их как контроль доступа, который враждебный обработчик не сможет обойти.
Производительность
Заголовок раздела «Производительность»setEncryption() выполняет итеративную процедуру выведения ключа (Algorithm 2.B, revision 6) во время сборки документа. Затраты ограничены и постоянны для каждого документа; они не растут с числом страниц. Шифрование на уровне объектов выполняет одну операцию AES для каждого потока или строки. Дополнительный путь AES-256-GCM добавляет 28 байт накладных расходов на объект (12-байтовый вектор инициализации (IV) плюс 16-байтовый тег) и обрабатывает крупное содержимое блоками по 16 МиБ. Благодаря этому потоковый проход остаётся ниже задокументированного пика 64 МБ. Значение performance_budget в 1500 мс по времени и 64 МБ по пику определяется в основном отрисовкой документа, а не шифрованием.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»Модель угроз описана явно. Криптополитика снижает риск понижения алгоритма, отклоняя слабые шифры, слабые хеши и короткие ключи до выполнения любой операции. Движок не подменяет запрошенный примитив более слабым, если тот недоступен; он выбрасывает исключение, чтобы оператор мог принять меры. KeyMaterial снижает риск раскрытия ключа через журналирование: его строковая и отладочная формы скрывают байты и раскрывают только необратимый отпечаток. Подделка шифротекста обнаруживается только на дополнительном пути AES-256-GCM: там проверяется тег аутентификации, и при несовпадении выбрасывается исключение вместо возврата открытого текста. Путь по умолчанию AES-256 Cipher Block Chaining (AES-256-CBC) обеспечивает только конфиденциальность и сам по себе не обнаруживает изменения. На пути GCM повторное использование IV предотвращается монотонным счётчиком плюс набором обнаружения коллизий по принципу эшелонированной защиты, что согласуется с требованием уникального IV в NIST SP 800-38D §8.
Границы описаны так же явно. Шифрование AES-256 применяется так, как определено в ISO 32000-2:2020 §7.6. Реальная защита зависит от надёжности пароля, управления ключами, среды развёртывания и читающего приложения. Читающие приложения, соответствующие стандарту, соблюдают флаги разрешений, но криптография их не обеспечивает. Зонд режима FIPS сообщает, загрузила ли сборка OpenSSL на хосте провайдер FIPS. Библиотека работает в FIPS-совместимом режиме, когда хост предоставляет проверенный модуль; сама она не сертифицирует ни один модуль. NIST SP 800-57 Part 1 §4 относит срок жизни ключа и криптопериод к обязанностям развёртывания. Core предоставляет средства управления, а развёртывание задаёт политику ротации.
Резидентность данных и меры по защите PII
Заголовок раздела «Резидентность данных и меры по защите PII»Поверхность шифрования не передаёт байты документа, включая любую содержащуюся в них персональную информацию (PII), за пределы хоста. Выведение ключа, шифрование и расшифровка выполняются внутри процесса. Дополнительный путь GCM индексирует набор обнаружения коллизий IV в памяти по необратимому отпечатку ключа, а не по байтам ключа. Модуль безопасности не записывает на диск ни пароль, ни значение ключа. Развёртывание, которое направляет ключи через внешнюю службу управления ключами, отвечает за резидентность этой службы.
Безопасная телеметрия и очистка журналов
Заголовок раздела «Безопасная телеметрия и очистка журналов»KeyMaterial::__toString() и __debugInfo() возвращают скрытую заглушку, поэтому при случайной записи объекта ключа в журнал попадает отпечаток, а не байты ключа. Пароли, передаваемые в setEncryption(), несут атрибут #[\SensitiveParameter], который скрывает их в трассировке стека. Для аудита используйте имя политики из CryptoPolicyInterface::getName() и 8-символьный отпечаток ключа как идентификаторы криптографической операции. Записывайте в журнал эти значения, но никогда — ключ или пароль.
Модель угроз
Заголовок раздела «Модель угроз»| Угроза | Меры в Core | Остаточная граница |
|---|---|---|
| Понижение алгоритма / подмена слабым шифром | Криптополитика; без молчаливого ослабления (выбрасывает UnsupportedAlgorithmException) | Действует только при внедрённой политике |
| Раскрытие ключа через журналы | KeyMaterial: сокрытие; #[\SensitiveParameter] на паролях | Вызывающий код, передающий exposeKey() в логгер, сводит это на нет |
| Подделка шифротекста | Проверка тега GCM на дополнительном пути | Путь CBC по умолчанию обеспечивает только конфиденциальность |
| Повторное использование IV (GCM) | Монотонный счётчик плюс набор обнаружения коллизий; переполнение отклоняется | — |
| Обход флага разрешений | Нет; флаги носят рекомендательный характер | Читающее приложение, не соответствующее стандарту, игнорирует флаги |
| Перебор слабого пароля | SASLprep плюс итеративное выведение ключа повышают стоимость | Слабый пароль остаётся доминирующим риском |
Поведение в режиме FIPS
Заголовок раздела «Поведение в режиме FIPS»Core не является криптографическим модулем, прошедшим валидацию FIPS, и не сертифицирован по FIPS. CryptoCapabilities::detectFipsMode() — это best-effort зонд времени выполнения: он читает переопределение оператора, затем список провайдеров OpenSSL, затем устаревший вызов режима FIPS и сообщает: активен, отсутствует или неопределён. assertFipsAvailableForProfile() отказывает по принципу fail-closed, когда профиль FIPS выбран на хосте, который не может подтвердить провайдер FIPS. Библиотека работает в FIPS-совместимом режиме, когда она настроена на сборку OpenSSL хоста, загрузившую провайдер, прошедший валидацию FIPS. Проверенная и сертифицированная позиция FIPS относится к Enterprise; см. документацию Enterprise.
Соответствие стандартам
Заголовок раздела «Соответствие стандартам»| Заявление | Стандарт | Пункт | Подтверждение |
|---|---|---|---|
| Путь GCM сохраняет уникальность каждого IV для вызова, что согласуется с требованием уникальности стандарта. | NIST SP 800-38D | §8.2.1 | |
| Core предоставляет средства управления сроком жизни ключа и криптопериодом; политику задаёт развёртывание. | NIST SP 800-57 Часть 1, ред. 5 | §4 | |
| Файловый ключ AES составляет 256 бит, что соответствует длине ключа стандарта. | FIPS 197 | §4.2.1 | |
| Генерация ключа на токене — это точка интеграции для внешнего хранилища ключей. | OASIS PKCS#11 v3.1 | C_GenerateKey |
ISO 32000-2:2020 §7.6 — нормативная основа для обработчика безопасности Standard. Его текст ограничен лицензией и здесь пересказан, но не цитируется; эта страница ссылается на пункт по номеру. Каждый пункт выше представляет пересказ цитируемого стандарта.
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»Core определяет и фиксирует контракт криптополитики, поставляет путь шифрования AES-256 и предоставляет поверхность с локальным ключом. Редакция Enterprise предоставляет путь хранения ключей через HSM/PKCS#11 и профиль криптополитики в режиме FIPS за тем же CryptoPolicyInterface. Поверхность контракта одинакова во всех редакциях; развёртывание подключает другую реализацию политики и бэкенд хранения ключей.
См. также
Заголовок раздела «См. также»- Security / Encryption — подробный справочник по AES-256 и AES-256-GCM.
- Contracts / Security Policy — контракты криптополитики и политики ресурсов.
- Security / Signing — PDF Advanced Electronic Signatures (PAdES), Cryptographic Message Syntax (CMS) и метки времени.
- Audit — журналирование аудита по имени политики и операциям.
- Conformance — взаимодействие PDF/A с шифрованием.