Enterprise 版本
Security — 深入參考(HSM、PKCS#11、FIPS 模式)
本頁是 NextPDF Enterprise 安全範圍的整合深入參考。它涵蓋透過 PKCS#11 的硬體 token 簽署、透過 OpenSSL 命令列介面(CLI)的子程序簽署、FIPS 密碼學原則預設、執行階段 FIPS 守衛,以及開機自我測試守衛。另有兩份聚焦的搭配文件:HSM — 深入參考 提供簽署器細節,以及 FIPS 140 — 深入參考 提供 FIPS 模組細節。後量子簽署路徑為預覽,不做任何符合性聲明。NextPDF 未持有任何認證,亦不授予任何認證;支援不等於符合,符合不等於認證。
可用性與授權
標題為「可用性與授權」的區段此功能隨 NextPDF Enterprise(nextpdf/enterprise)出貨,並以 Enterprise 層級授權封套啟用。未具該權利的部署不會載入此功能的類別。比較版本並取得授權。
公開 API 介面
標題為「公開 API 介面」的區段composer require nextpdf/enterprise:^3簽署型別位於 NextPDF\Enterprise\Security\Signature\Hsm;FIPS 型別位於 NextPDF\Enterprise\Security\Fips;組合根位於 NextPDF\Enterprise\Bootstrap。兩個簽署器都實作 Core 的 NextPDF\Contracts\HsmSignerInterface 合約。該原則實作 Core 的 NextPDF\Contracts\CryptoPolicyInterface 與 NextPDF\Contracts\PreOperationalSelfTestInterface 合約。
| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
Pkcs11Signer::__construct() | string $libraryPath, int $slotId, string $pin, string $certLabel, ?string $keyLabel = null, array $chainDer = [], bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null | 開啟廠商函式庫、登入 slot、載入憑證與金鑰演算法中繼資料 | — | 當 ext-pkcs11 不存在或 token 存取失敗時拋出 HsmOperationException | PIN 與標籤為 #[SensitiveParameter];每個程序中每個函式庫路徑快取一個模組控制代碼 |
Pkcs11Signer::isAvailable() | 無 | 回報是否已載入 ext-pkcs11 | bool | 無 | 靜態;於建構前檢查 |
Pkcs11Signer::sign() | string $data, string $algorithm = 'sha256WithRSAEncryption' | 在 token 上簽署;原始 ECDSA 輸出會轉換為 DER ECDSA-Sig-Value | string 原始簽章位元組 | HsmOperationException(找不到金鑰、token 失敗);InvalidArgumentException(未對應的演算法);當接上 enforcer 時於簽署前拋出 FipsViolationException / FipsModuleErrorStateException | 封閉演算法集合;見〈行為契約〉 |
Pkcs11Signer::signPqs() | string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true | 除非已設定 $enablePostQuantum,否則拒絕;派送暫定的 PKCS#11 後量子機制 | string 原始簽章位元組 | HsmOperationException(已停用、token 失敗、簽章長度不符);InvalidArgumentException(context 超過 255 位元組) | 預覽;不做符合性聲明 |
Pkcs11Signer accessor surface | 無 | 唯讀的建構結果 | bool / string / array<string> | 無 | isPostQuantumEnabled, getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm |
OpenSslCliSigner::__construct() | string $keyUri, string $certPath, string $pin, array $extraCertPaths = [], OpenSslCliBackend $backend = OpenSslCliBackend::Auto, string $opensslBinary = 'openssl', int $timeoutSeconds = 30, ?string $modulePath = null, ?string $configPath = null, bool $legacyPinDelivery = false, ?FipsSignatureEnforcer $fipsEnforcer = null | 驗證 proc_open、探測二進位檔、解析後端、載入憑證 | — | HsmOperationException(proc_open 已停用、缺少 module/config/憑證檔、無後端);InvalidArgumentException($keyUri 內含 pin-value) | Auto 優先使用 OpenSSL 3.x provider,其次為 engine |
OpenSslCliSigner::sign() | string $data, string $algorithm = 'sha256WithRSAEncryption' | 在一個 openssl 子程序中簽署;PIN 預設透過一個短暫的 0600 pin-source 檔傳遞 | string 原始簽章位元組 | HsmOperationException(逾時、PIN 被拒、找不到金鑰、空白輸出);InvalidArgumentException(未對應的演算法);於簽署前的 FIPS 閘門例外 | 子程序於 $timeoutSeconds 後被終止;stderr 會被遮蔽 |
OpenSslCliSigner accessor surface | 無 | 唯讀的建構結果 | string / array<string> / OpenSslCliBackend | 無 | getCertificateDer, getCertificateChainDer, getPublicKeyAlgorithm, getCertificatePem, getResolvedBackend, getOpensslVersion |
OpenSslCliBackend | — | 列舉:Provider、Engine、Auto | — | 無 | CLI 簽署器的後端選擇 |
Pkcs11PqsAlgorithm | — | ML-DSA 與 SLH-DSA 參數集的列舉 | — | 無 | 輔助方法:isMlDsa, isSlhDsa, mechanismId, parameterSetId, signatureLength, nistCategory |
PqsCapabilityStatus::current() | 無 | 為程序建立誠實的後量子態勢 | PqsCapabilityStatus | 無 | 每個符合性聲明布林值都硬編碼為 false;沒有任何旗標能將其開啟 |
HsmSignerProviderAdapter | HsmSignerInterface $hsm, string $providerId, SignatureAlgorithm $algorithm = SignatureAlgorithm::Pkcs1v15 | 將一個 HSM 具體實作公開為統一的 SignerProviderInterface | 依 SPI | KeyManagementException(非 null 的金鑰版本);SignatureFailedException(驅動程式失敗、空白簽章) | Provider id:pkcs11-{module-id}, openssl-cli |
HsmOperationException | — | 每條 HSM 簽署路徑的具型別失敗 | — | — | 繼承 Core 的 NextPdfException |
FipsCryptoPolicy::strict() / ::standard() | ?FipsSelfTest $selfTest = null | 工廠預設;strict 是 FIPS 140-3 設定檔,standard 另加 AES-128-CBC | FipsCryptoPolicy | 無 | 不可變的允許清單;見 FIPS 模式行為 |
FipsCryptoPolicy predicate surface | string / int 輸入 | 允許清單成員檢查 | bool / string | 無 | isHashAlgorithmAllowed, isSignatureAlgorithmAllowed, isEncryptionAlgorithmAllowed, isKeyStrengthAllowed, getPreferredHashAlgorithm, getName |
FipsCryptoPolicy::assertPreOperational() | 無 | 執行(或重播)開機自我測試 | void | FipsModuleErrorStateException | 由 Core 的強制執行接縫在第一次密碼學操作時驅動 |
FipsModeGuard::__construct() | CryptoPolicyInterface $policy, ?FipsBootGuard $bootGuard = null, ?FipsAuditLogger $auditLogger = null | 以斷言式邊界包覆一個原則 | — | 無 | 沒有 boot guard 時,自我測試閘門不存在(僅原則) |
FipsModeGuard assert surface | string / int 輸入 | 先查拒絕目錄,再查允許清單;在任何拋出之前先記錄稽核 | void | FipsViolationException;FipsModuleErrorStateException(已接上 boot guard) | assertHashAllowed, assertSignatureAlgorithmAllowed, assertEncryptionAllowed, assertKeyStrengthAllowed,外加 getPolicy |
FipsBootGuard::report() / ::rerun() | 無 | 執行自我測試電池(快取 / 強制) | FipsSelfTestReport | 無 | 一份 ERROR 報告會鎖存整個程序;一次通過的重跑絕不清除此鎖存 |
FipsBootGuard::assertOperational() | 無 | 斷言模組處於 OPERATIONAL | void | FipsModuleErrorStateException | 黏性:程序層級鎖存的 ERROR 即使對一個乾淨的實例也會拒絕 |
FipsBootGuard::status() | 無 | 回報快取的狀態 | FipsSelfTestStatus | 無 | PRE_OPERATIONAL, OPERATIONAL, or ERROR |
FipsSelfTest::run() | 無 | 執行完整的已知答案測試(known-answer-test)電池;絕不短路 | FipsSelfTestReport | 無 | 建構子接受可注入的雜湊與隨機位元組供應者,以進行確定性測試 |
FipsSelfTestReport / FipsSelfTestResult / FipsSelfTestStatus | — | 報告值物件與狀態列舉 | — | FipsSelfTestReport::assertOperational() 拋出 FipsModuleErrorStateException | results 始終列出每個結果作為稽核證據 |
FipsSignatureEnforcer::assertSignatureGenerationAllowed() | string $algorithm, string $certificatePem | 解析簽章 OID 與金鑰強度,然後委派給守衛 | void | FipsViolationException(不被允許或無法分類,fail-closed) | 在 FIPS 模式下,兩個簽署器都在 sign() 開頭呼叫的節流點 |
FipsAuditLogger | CryptoPolicyInterface $policy, LoggerInterface $logger | 每個決策發出 ALLOW(INFO)/ DENY(WARNING)記錄 | 每次記錄呼叫回傳 bool | 無 | logHashOperation, logSignatureOperation, logEncryptionOperation, logKeyStrengthCheck |
FipsTransitioningAlgorithms | string / int 輸入 | 靜態的 NIST SP 800-131A 拒絕目錄 | bool / array | 無 | 每個守衛邊界之下的明確拒絕層 |
FipsBootstrap::boot() / ::lazy() | ?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null | 組合 boot guard、原則與 mode guard;boot() 立即執行自我測試,lazy() 將其延後至第一個邊界 | FipsModeGuard | boot():測試失敗時拋出 FipsModuleErrorStateException | 預設為 strict 原則 |
FipsBootstrap::signatureEnforcer() | ?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null | 啟動模組並回傳給簽署器使用的產生時閘門 | FipsSignatureEnforcer | FipsModuleErrorStateException | 將結果傳入簽署器的 $fipsEnforcer 參數 |
FipsBootstrap::selfTestReport() | ?FipsSelfTest $selfTest = null | 隨選執行電池並加以摘要 | array{status, operational, failed} | 無 | 供健康檢查端點與 CLI 子指令使用 |
FipsViolationException / FipsModuleErrorStateException | — | 具型別的 FIPS 失敗 | — | — | 分別公開 policyName / violatingItem / reason 與 failedResults |
public function __construct(private readonly string $libraryPath, private readonly int $slotId, #[SensitiveParameter] private readonly string $pin, #[SensitiveParameter] private readonly string $certLabel, #[SensitiveParameter] private readonly ?string $keyLabel = null, array $chainDer = [], private readonly bool $enablePostQuantum = false, ?FipsSignatureEnforcer $fipsEnforcer = null)public static function isAvailable(): boolpublic function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): stringpublic function signPqs(string $data, Pkcs11PqsAlgorithm $algorithm, string $context = '', bool $randomized = true): stringpublic function __construct(private string $keyUri, string $certPath, #[SensitiveParameter] private string $pin, array $extraCertPaths = [], private OpenSslCliBackend $backend = OpenSslCliBackend::Auto, private string $opensslBinary = 'openssl', private int $timeoutSeconds = 30, private ?string $modulePath = null, private ?string $configPath = null, private bool $legacyPinDelivery = false, private ?FipsSignatureEnforcer $fipsEnforcer = null)public function sign(string $data, string $algorithm = 'sha256WithRSAEncryption'): stringpublic static function strict(?FipsSelfTest $selfTest = null): selfpublic static function standard(?FipsSelfTest $selfTest = null): selfpublic function assertPreOperational(): voidpublic function __construct(private CryptoPolicyInterface $policy, private ?FipsBootGuard $bootGuard = null, private ?FipsAuditLogger $auditLogger = null)public function assertHashAllowed(string $algorithm): voidpublic function assertSignatureAlgorithmAllowed(string $oid): voidpublic function assertEncryptionAllowed(string $algorithm): voidpublic function assertKeyStrengthAllowed(string $keyType, int $bitLength): voidpublic function getPolicy(): CryptoPolicyInterfacepublic static function boot(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function lazy(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null, ?LoggerInterface $auditLogger = null): FipsModeGuardpublic static function signatureEnforcer(?CryptoPolicyInterface $policy = null, ?FipsSelfTest $selfTest = null): FipsSignatureEnforcerpublic static function selfTestReport(?FipsSelfTest $selfTest = null): array行為契約
標題為「行為契約」的區段- 合約解析。 兩個簽署器都實作 Core 的
HsmSignerInterface;該原則實作 Core 的CryptoPolicyInterface。呼叫端程式碼依賴合約,因此版本升級改變的是組合,而非呼叫點。 - 金鑰保管。 私鑰絕不離開 token 邊界。
Pkcs11Signer將操作委派給 token;OpenSslCliSigner將一個 PKCS#11 URI 金鑰參照傳給子程序。NextPDF 不儲存、不產生,也不保證簽署金鑰的安全。金鑰保護是操作者的保管責任(NIST SP 800-57 Part 1 Rev.5 §5.5.2)。 - 工作階段與登入。 token 簽署操作、工作階段與使用者登入遵循 PKCS#11 v3.1 §5。憑證標籤與私鑰標籤可以不同;建構子為此類 token 接受一個獨立的金鑰標籤。
- 封閉演算法集合。 簽署器恰好接受:搭配 SHA-256/384/512 的 RSA PKCS#1 v1.5、搭配 SHA-256/384/512 的 RSASSA-PSS,以及搭配 SHA-256/384/512 的 ECDSA(
Pkcs11Signer亦接受ecdsa-raw)。任何其他識別碼都會引發InvalidArgumentException;絕不簽署任何替代演算法。 - PSS salt 綁定。 對於每個 PSS 變體,salt 長度等於摘要長度——32、48 或 64 位元組——且雜湊與遮罩產生參數與所選摘要一致(PKCS#11 v3.1 §5)。
- ECDSA 轉換。 token ECDSA 機制回傳原始簽章;
sign()會將其轉換為 DER 編碼的ECDSA-Sig-Value形式,以利 PDF 與 OpenSSL 互通。簽章產生遵循 FIPS 186-5 §6.3.2。 - 預設內容。 strict 預設允許 SHA-256/384/512;搭配那些雜湊的 RSA 與 ECDSA 簽章 OID;RSASSA-PSS;AES-256-CBC 與 AES-256-GCM;最小 RSA 2048 與 EC 256。standard 預設另外允許 AES-128-CBC 以利舊式互通。任何 AES-GCM 使用都要求每把金鑰有一個唯一的初始化向量(NIST SP 800-38D §5)。
- 雙層強制。 每個守衛邊界先查詢明確的 NIST SP 800-131A 拒絕目錄,再查詢原則允許清單。拒絕層產生稽核清晰的「不被允許」訊號;允許清單仍為權威。
- 開機自我測試。 該電池涵蓋 SHA-256/384/512、HMAC-SHA-256、AES-256-CBC、AES-256-GCM、一個 ECDSA P-256 成對一致性測試,以及一個隨機位元健康檢查。在 Core 路徑上,原則之下的第一次密碼學操作會於每個程序執行它一次,fail-closed。失敗會讓模組進入 ERROR 狀態;在重設之前拒絕提供密碼學服務。此遵循 ISO/IEC 19790:2025 §7.10、§7.10.2、§7.10.3 與 §7.10.3.p3。
- 黏性 ERROR 狀態。 一個被觀察到的 ERROR 會鎖存整個程序。建構一個全新的原則或 boot guard 無法將其洗清;一次通過的重跑不會清除它。只有程序重啟——一次真正的電源循環——才會重設此狀態。
- 僅限產生閘門。
FipsSignatureEnforcer管轄產生新簽章。對既有簽章的驗證屬於舊式使用,絕不經由 enforcer。 - 稽核軌跡。 當守衛與稽核記錄器組合時,每個邊界在允許或拒絕操作之前都會發出一筆 ALLOW 或 DENY 記錄。記錄器查詢守衛所強制的同一個原則,因此記錄的決策不會分歧。
邊界案例與失敗模式
標題為「邊界案例與失敗模式」的區段- 在沒有
ext-pkcs11的情況下建構Pkcs11Signer會立即引發HsmOperationException;標準 PHP 發行版並未隨附此擴充。 - 未對應任何 token 物件的憑證或私鑰標籤會引發
HsmOperationException,並指名缺少的物件類別。 OpenSslCliSigner在建構時拒絕含有pin-value的$keyUri,fail-closed;PIN 改為透過安全的 pin-source 路徑傳遞。- 在 FIPS 模式下,無法對應到已知簽章 OID 的演算法識別碼會被 fail-closed 拒絕;公鑰強度無法確定的憑證亦然。
- 未知的金鑰型別預設被拒絕;原則絕不退回到較弱的演算法。
- 失敗的已知答案測試會引發
FipsModuleErrorStateException,其中攜帶失敗結果;程序中之後的每個邊界都會重複此失敗,直到重啟為止。 - 沒有 boot guard 而建構的守衛會強制允許清單,但不提供自我測試閘門;正式的 FIPS 組合會透過 bootstrap 提供一個。
- 除非設定了建構子的選用啟用,否則
signPqs()拒絕執行。超過 255 位元組的 context 字串會引發InvalidArgumentException(FIPS 204 §5.4)。回傳簽章的位元組長度若與所選參數集不符,會在其到達編碼之前被拒絕。
FIPS 模式行為
標題為「FIPS 模式行為」的區段strict 模式中 FIPS 允許:SHA-256/384/512;搭配那些雜湊的 RSA PKCS#1 v1.5 與 RSA-PSS;搭配那些雜湊的 ECDSA;AES-256-CBC 與 AES-256-GCM;RSA 至少 2048 位元、EC 至少 256 位元。strict 模式中 FIPS 拒絕:較弱或舊式的雜湊、非核准的簽章 OID、AES-128(僅在 standard 預設中允許),以及任何低於最小強度的金鑰。最小 RSA 金鑰長度與轉換狀態遵循 NIST SP 800-131A Rev.2 §3。ECDSA 曲線與雜湊配對遵循 FIPS 186-5 §6.1.1。此路徑為 fail-closed,且絕不以較弱的演算法替代。
NextPDF Enterprise 不是經 FIPS 驗證的密碼學模組,亦不做任何 FIPS 認證聲明。 NextPDF Enterprise 只有在被設定為搭配一個經 FIPS 驗證的密碼學供應者——例如一個經 FIPS 驗證的 OpenSSL 供應者——或一個經 FIPS 驗證的 HSM 時,才以 FIPS 相容模式運作。FIPS 模式原則協助合規;它不是認證。本儲存庫中不存在任何 FIPS 認證成品。
符合性
標題為「符合性」的區段| 聲明 | 標準 | 條款 |
|---|---|---|
| token 簽署操作、工作階段與使用者登入語意 | PKCS#11 v3.1 | §5 (sign) |
| PSS salt 長度等於摘要長度 | PKCS#11 v3.1 | §5 (PSS sLen) |
| ECDSA 簽章產生;曲線與雜湊配對 | FIPS 186-5 | §6.3.2; §6.1.1 |
| 最小 RSA 金鑰長度與簽章產生轉換狀態 | NIST SP 800-131A Rev.2 | §3 |
| 自我測試類別、文件、條件式觸發、不相交集合 | ISO/IEC 19790:2025 | §7.10, §7.10.2, §7.10.3, §7.10.3.p3 |
| AES-GCM 初始化向量唯一性 | NIST SP 800-38D | §5 |
| 金鑰保護與保管責任 | NIST SP 800-57 Part 1 Rev.5 | §5.5.2 |
| 後量子簽署 context 字串限制為 255 位元組 | FIPS 204 | §5.4 |
所有條款皆為改寫;未重現任何規範性文字。這些是關於 NextPDF 程式碼的能力聲明,而非認證。所產生的簽章是否通過驗證,是驗證者依其自身信任設定所做的決定。FIPS 模式原則是一項合規協助功能,不是法律意見;請諮詢你自己的合規與法律顧問。本模組涉及密碼學功能;請在你自己的審查中將其視為安全敏感。
開發注意事項
標題為「開發注意事項」的區段- 透過 bootstrap 組合 FIPS 模式:
boot()提供啟動時閘門,lazy()將電池延後至第一個邊界,以及 enforcer 工廠供簽署器的$fipsEnforcer參數使用。非 FIPS 部署傳入null,行為不變。 bin/nextpdf-enterprise的fips:self-test子指令隨選執行電池,並在 ERROR 狀態下以非零值退出;請將其接到維護工作或僅限管理員的健康檢查端點(ISO/IEC 19790:2025 隨選自我測試)。FipsBootGuard::resetProcessErrorLatchForTesting()為@internal且僅供測試;正式程式碼絕不呼叫它,因為那會破壞黏性 ERROR 狀態。- 簽署器建構一次即重複使用;建構過程會登入並讀取憑證,而每函式庫的模組快取使得對同一函式庫的重複建構是安全的。
- 從機密管理器提供 PIN。它是
#[SensitiveParameter],絕不記錄或序列化;請勿將其提交至設定中。 - 操作者負責 token 配置、PIN 處理、slot 設定、網路型 HSM 的網路保護,以及信任設定。本頁不揭露 token PIN 原則內部實作或廠商憑證材料。
- 請勿為正式的 AdES 簽章啟用後量子預覽。AdES 密碼學套件目錄尚未承認後量子套件,多數 PDF 檢視器會拒絕此類簽章,且硬體往返驗證尚未完成。內部機制細節保留在來源儲存庫的內部文件中,不在本手冊範圍內。
發布邊界
標題為「發布邊界」的區段本頁僅記載外部可觀察的行為與受支援的公開 API 介面。內部命名空間路徑、輔助類別、機制對照表、runbook 檔名與工單前綴不在範圍內。
另請參閱
標題為「另請參閱」的區段- Security — NextPDF Enterprise — 此範圍的功能頁面。
- 硬體安全模組簽署(PKCS#11) — 設定、配置與驗證步驟。
- FIPS 140 密碼學原則 — FIPS 功能頁面。
- HSM — 深入參考 — 聚焦的簽署器參考。
- FIPS 140 — 深入參考 — 聚焦的 FIPS 模組參考。
- Security — NextPDF Pro — Pro 層級安全範圍。
- Security — NextPDF Core — Core 安全基準。