Enterprise 版本
FIPS 140 — 深入參考
本頁是 NextPDF Enterprise FIPS 140 模組的深入參考。此模組是一種政策與自我測試能力。它將加密選擇限制在一份 FIPS 對齊的允許清單、執行一組開機已知答案測試序列,並在該序列失敗時抑制加密輸出。NextPDF 並非經 FIPS 140 驗證的加密模組,不持有任何認證,也不授予任何認證。 支援不等於符合,符合也不等於認證。一個 FIPS 相容的部署還需要一個由操作者提供、經 FIPS 驗證的加密提供者。
可用性與授權
標題為「可用性與授權」的區段此能力隨 NextPDF Enterprise(nextpdf/enterprise)出貨,並以 Enterprise 級授權封套啟用。缺少該權利的部署不會載入此能力的類別。比較版本並取得授權。
公開 API 表面
標題為「公開 API 表面」的區段所有符號皆位於 NextPDF\Enterprise\Security\Fips,唯 FipsBootstrap 位於 NextPDF\Enterprise\Bootstrap。
| 符號 | 參數 | 預設行為 | 回傳 | 拋出或失敗於 | 備註 |
|---|---|---|---|---|---|
FipsBootstrap::boot() | ?CryptoPolicyInterface $policy、?FipsSelfTest $selfTest、?LoggerInterface $auditLogger(皆預設 null) | 於啟動時執行一次開機序列;預設採用嚴格政策 | FipsModeGuard | 任一開機測試失敗時拋出 FipsModuleErrorStateException | 組合根;當 $auditLogger 為 null 時稽核軌跡關閉 |
FipsBootstrap::lazy() | 同 boot() | 將序列延後至首次邊界斷言 | FipsModeGuard | 呼叫時不拋出;首次斷言可拋出 FipsModuleErrorStateException | 模組在首次斷言前維持 PRE_OPERATIONAL |
FipsBootstrap::signatureEnforcer() | ?CryptoPolicyInterface $policy = null、?FipsSelfTest $selfTest = null | 啟動模組後,為簽章瓶頸點包裝守衛 | FipsSignatureEnforcer | 任一開機測試失敗時拋出 FipsModuleErrorStateException | 委派給 boot() |
FipsBootstrap::selfTestReport() | ?FipsSelfTest $selfTest = null | 按需執行序列並彙整結果 | array{status: FipsSelfTestStatus, operational: bool, failed: list<string>} | 不拋出;失敗會出現在 failed 中 | 供管理健康端點與 CLI 使用 |
FipsCryptoPolicy::strict() | ?FipsSelfTest $selfTest = null | FIPS 140-3 預設集:SHA-256/384/512;核准的 RSA、RSASSA-PSS、ECDSA OID;aes-256-cbc、aes-256-gcm;RSA >= 2048、EC >= 256 | self | 無 | 建構子為 private;預設集是唯一入口 |
FipsCryptoPolicy::standard() | ?FipsSelfTest $selfTest = null | FIPS 140-2 預設集:嚴格集合再加上 aes-128-cbc | self | 無 | 僅供舊制互通 |
FipsCryptoPolicy::assertPreOperational() | 無 | 執行開機序列,或重播其閂鎖的結果 | void | 任一開機測試失敗時拋出 FipsModuleErrorStateException | 由 Core 強制縫合層在首次操作前驅動 |
FipsCryptoPolicy 查詢表面 | string / int 輸入 | 允許清單成員檢查;未知金鑰型別遭拒 | bool / string | 無 | isHashAlgorithmAllowed、isSignatureAlgorithmAllowed、isEncryptionAlgorithmAllowed、isKeyStrengthAllowed、getPreferredHashAlgorithm、getName |
FipsModeGuard::__construct() | CryptoPolicyInterface $policy、?FipsBootGuard $bootGuard = null、?FipsAuditLogger $auditLogger = null | 以 assert 式邊界包裝一項政策 | — | 無 | 缺少 $bootGuard 時沒有自我測試閘門;正式組合會提供它 |
FipsModeGuard::assertHashAllowed() | string $algorithm | 先過拒絕目錄,再過允許清單 | void | FipsViolationException;已接線開機守衛時拋出 FipsModuleErrorStateException | 稽核紀錄先於任何 FipsViolationException |
FipsModeGuard::assertSignatureAlgorithmAllowed() | string $oid | 先過拒絕目錄,再過允許清單 | void | 同上 | OID 採精確比對 |
FipsModeGuard::assertEncryptionAllowed() | string $algorithm | 先過拒絕目錄,再過允許清單 | void | 同上 | 名稱以小寫比較 |
FipsModeGuard::assertKeyStrengthAllowed() | string $keyType、int $bitLength | 先過拒絕目錄,再過政策下限 | void | 同上 | 未知金鑰型別遭拒 |
FipsModeGuard::getPolicy() | 無 | 回傳被包裝的政策 | CryptoPolicyInterface | 無 | — |
FipsBootGuard::__construct() | FipsSelfTest $selfTest | 持有序列;不執行它 | — | 無 | 每個實例一個開機週期 |
FipsBootGuard::report() | 無 | 執行序列一次、快取報告、於錯誤時閂鎖 | FipsSelfTestReport | 無 | 首次呼叫執行測試 |
FipsBootGuard::rerun() | 無 | 強制重新執行;錯誤的執行會閂鎖整個程序 | FipsSelfTestReport | 無 | 按需自我測試;不是錯誤復原途徑 |
FipsBootGuard::assertOperational() | 無 | 斷言模組可運作;在整個程序中黏著 | void | FipsModuleErrorStateException | 當程序已閂鎖錯誤時,乾淨的實例仍會拋出 |
FipsBootGuard::status() | 無 | 回報快取的狀態 | FipsSelfTestStatus | 無 | 閂鎖時為 ERROR;從未執行時為 PRE_OPERATIONAL |
FipsSelfTest::__construct() | ?callable $randomBytesProvider = null、?callable $hashProvider = null | 使用平台 hash() 與 random_bytes() | — | 無 | 存在覆寫以進行確定性失敗測試 |
FipsSelfTest::run() | 無 | 執行完整序列;絕不短路 | FipsSelfTestReport | 無 | 失敗落於報告中,而非例外中 |
FipsSelfTestReport | FipsSelfTestStatus $status、array $results、array $failedResults | 單次執行的不可變聚合 | — | 於錯誤狀態時 assertOperational() 拋出 FipsModuleErrorStateException | 亦有 isOperational()、isError() |
FipsSelfTestResult | string $algorithm、string $kind、bool $passed、string $message = '' | 不可變的單項測試結果 | — | 無 | kind 為 KAT、PWCT 或 HEALTH;亦有 isPassed()、isFailed() |
FipsSelfTestStatus | — | 以字串為底的列舉 | — | 無 | 列舉項 PRE_OPERATIONAL、OPERATIONAL、ERROR |
FipsSignatureEnforcer::__construct() | FipsModeGuard $guard | 為簽署瓶頸點包裝一個開機閘控的守衛 | — | 無 | — |
FipsSignatureEnforcer::assertSignatureGenerationAllowed() | string $algorithm、string $certificatePem | 解析 OID 與金鑰強度後委派給守衛 | void | FipsViolationException(未知演算法、未核准的 PSS 摘要、無法證實的金鑰,或政策拒絕);經由守衛拋出 FipsModuleErrorStateException | 僅生成途徑;驗證絕不經此路由 |
FipsAuditLogger::__construct() | CryptoPolicyInterface $policy、LoggerInterface $logger | 包裝一個 PSR-3 記錄器與守衛所強制的同一份政策 | — | 無 | 所紀錄的決策不能偏離所強制的決策 |
FipsAuditLogger::logHashOperation() / logSignatureOperation() / logEncryptionOperation() / logKeyStrengthCheck() | 每項決策的 string / int 輸入 | 以 INFO 記錄 ALLOW,以 WARNING 記錄 DENY | bool(允許時為 true) | 無 | 結構化情境:政策名稱、項目、決策 |
FipsTransitioningAlgorithms | string / int 輸入 | 靜態的 SP 800-131A Rev.2 拒絕目錄 | bool / list<string> | 無 | isHashDisallowed、isSignatureOidDisallowed、isEncryptionDisallowed、isKeyStrengthDisallowed,以及 disallowedHashes、disallowedSignatureOids、disallowedEncryption |
FipsViolationException | string $policyName、string $violatingItem、string $reason | 帶有 public readonly 欄位的具型別政策違規 | — | — | NextPDF\Exception\NextPdfException 的子型別 |
FipsModuleErrorStateException | array $failedResults、?string $message = null | 承載失敗測試結果的錯誤狀態拒絕 | — | — | NextPDF\Exception\NextPdfException 的子型別 |
public 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): arraypublic static function strict(?FipsSelfTest $selfTest = null): selfpublic static function standard(?FipsSelfTest $selfTest = null): selfpublic function assertPreOperational(): voidpublic function isHashAlgorithmAllowed(string $algorithm): boolpublic function isSignatureAlgorithmAllowed(string $oid): boolpublic function isEncryptionAlgorithmAllowed(string $algorithm): boolpublic function isKeyStrengthAllowed(string $keyType, int $bitLength): boolpublic function getPreferredHashAlgorithm(): stringpublic function getName(): stringpublic 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 function __construct(private readonly FipsSelfTest $selfTest)public function report(): FipsSelfTestReportpublic function rerun(): FipsSelfTestReportpublic function assertOperational(): voidpublic function status(): FipsSelfTestStatuspublic function __construct(?callable $randomBytesProvider = null, ?callable $hashProvider = null)public function run(): FipsSelfTestReportpublic function __construct(private readonly FipsModeGuard $guard)public function assertSignatureGenerationAllowed(string $algorithm, string $certificatePem): voidpublic function __construct(private CryptoPolicyInterface $policy, private LoggerInterface $logger)public function logHashOperation(string $algorithm): boolpublic function logSignatureOperation(string $oid): boolpublic function logEncryptionOperation(string $algorithm): boolpublic function logKeyStrengthCheck(string $keyType, int $bitLength): boolpublic static function isHashDisallowed(string $algorithm): boolpublic static function isSignatureOidDisallowed(string $oid): boolpublic static function isEncryptionDisallowed(string $algorithm): boolpublic static function isKeyStrengthDisallowed(string $keyType, int $bitLength): boolpublic static function disallowedHashes(): arraypublic static function disallowedSignatureOids(): arraypublic static function disallowedEncryption(): arraypublic function __construct(public FipsSelfTestStatus $status, public array $results, public array $failedResults)public function isOperational(): boolpublic function isError(): boolpublic function assertOperational(): void
// FipsSelfTestResultpublic function __construct(public string $algorithm, public string $kind, public bool $passed, public string $message = '')public function isPassed(): boolpublic function isFailed(): bool
// FipsSelfTestStatusenum FipsSelfTestStatus: string{ case PRE_OPERATIONAL = 'pre_operational'; case OPERATIONAL = 'operational'; case ERROR = 'error';}行為契約
標題為「行為契約」的區段- 政策允許清單是權威性的決策依據。
FipsTransitioningAlgorithms在其之上疊加一層明確的 SP 800-131A Rev.2 拒絕層,以提供稽核清晰的拒絕訊息。此拒絕層絕不擴張或覆寫允許清單。 FipsCryptoPolicy::strict()允許 SHA-256、SHA-384 與 SHA-512;RSA PKCS#1 v1.5、RSASSA-PSS及綁定於這些雜湊的 ECDSA 簽章 OID;aes-256-cbc與aes-256-gcm;以及 RSA 2048、EC 256、Ed25519 256 的金鑰下限。standard()另外允許aes-128-cbc。- 開機序列涵蓋:SHA-256/384/512 摘要 KAT、一項 HMAC-SHA-256 KAT、一項 AES-256-CBC 加解密 KAT、一項 AES-256-GCM 標籤 KAT、一項 ECDSA P-256 成對一致性測試,以及一項 DRBG 健康檢查。
FipsSelfTest::run()一律執行每一項測試且絕不短路,因此報告對稽核佐證是完整的。 - DRBG 那一列是一項持續性健康測試(抽取長度加上相異的連續抽取),並非已知答案測試。DRBG 的已知答案義務委派給操作者所提供的底層 FIPS 驗證提供者。
- 錯誤狀態具程序黏著性。任一
FipsBootGuard所觀察到的第一份ERROR報告會閂鎖整個程序。新的守衛或政策實例無法洗清此錯誤,之後一次通過的重跑也不會將其清除。唯有程序重啟(一次真正的電源循環)才會重設此狀態。 FipsCryptoPolicy實作NextPDF\Contracts\CryptoPolicyInterface與NextPDF\Contracts\PreOperationalSelfTestInterface。當被配置為 Core 加密政策時,Core 強制縫合層會在產生首個簽章或密文之前驅動assertPreOperational()。FipsSignatureEnforcer僅閘控生成途徑。對已生成簽章的驗證在 SP 800-131A Rev.2 下屬於舊制用途,絕不經由強制器路由。- 當接線了稽核記錄器時,每一個 assert 邊界都會在任何政策違規拋出之前送出一筆 ALLOW(INFO)或 DENY(WARNING)紀錄。因此每一次
FipsViolationException拒絕都在軌跡中留有佐證。開機守衛閘門先執行,因此錯誤狀態拒絕會在稽核紀錄之前被引發。FipsAuditLogger諮詢守衛所強制的同一份政策,故所紀錄的決策不能偏離所強制的決策。
邊界情況與失效模式
標題為「邊界情況與失效模式」的區段- 未知金鑰型別會被兩層同時拒絕:政策回傳
false,目錄則將其視為不允許。 - 強制器無法對映到簽章 OID 的簽署演算法識別碼,會以失效即關閉方式被
FipsViolationException拒絕。 - 每一種
RSASSA-PSS變體共用 OID1.2.840.113549.1.1.10,故單憑 OID 無法證實摘要。強制器明確綁定有效摘要,並拒絕任何摘要非 SHA-256/384/512 的 PSS 標記。 - 無法解析、或其公鑰位元長度不可得的憑證,會被以
key:unprovable拒絕。 - 在缺乏 OpenSSL 非對稱基元的執行環境上,ECDSA 成對一致性測試會記錄為失敗而非略過,且模組進入
ERROR。 - 兩次相同的連續 32 位元組隨機抽取會使 DRBG 健康檢查失敗(卡住輸出偵測)並強制進入
ERROR。 - 未帶開機守衛所建構的
FipsModeGuard僅執行政策檢查,沒有自我測試閘門。正式組合會經由FipsBootstrap,其一律接線該閘門。 - 雜湊與密碼名稱以小寫比較;簽章 OID 採精確比對,不做任何正規化。
- 於
FipsBootstrap::lazy()之後,模組維持PRE_OPERATIONAL,直到首個 assert 邊界執行序列為止。PRE_OPERATIONAL在斷言時被視為非可運作。
FIPS 模式行為
標題為「FIPS 模式行為」的區段此模組本身即是 FIPS 模式表面。當模組處於錯誤狀態時,以及在開機前自我測試執行時,加密輸出被抑制:每一個 assert 邊界都會在產生任何簽章或密文之前拋出 FipsModuleErrorStateException(ISO/IEC 19790:2025 §7.3.3 b),AS03.07)。FipsBootGuard::status() 與 FipsBootstrap::selfTestReport() 暴露該狀態,讓操作者能判定模組已進入錯誤狀態(ISO/IEC 19790:2025 §7.10.3)。這些是關於 NextPDF 程式碼的能力宣稱,並非驗證宣稱:FIPS 140 所驗證的模組邊界是操作者提供的加密提供者,而非 NextPDF。
符合性
標題為「符合性」的區段| 宣稱 | 標準 | 條款 |
|---|---|---|
| FIPS 140-3 基於 ISO/IEC 19790 與 ISO/IEC 24759;因此本頁引用 ISO/IEC 19790 條款。 | FIPS 140-3 | Introduction (fips_140_3#x26.x2) |
| 在錯誤狀態下以及開機前自我測試期間,輸出被抑制。 | ISO/IEC 19790:2025 | §7.3.3 b) [AS03.07] |
| 已知答案測試將計算結果與已知的預期輸出比對;本序列即實作此形態。 | ISO/IEC 19790:2025 | §7.10.4 |
| 操作者可透過狀態輸出判定錯誤狀態。 | ISO/IEC 19790:2025 | §7.10.3 [AS10.10] |
操作者可按需啟動自我測試以進行週期性測試;rerun() 與 selfTestReport() 提供此功能。 | ISO/IEC 19790:2025 | §7.10.5 [AS10.54] |
| SHA-1 不允許用於新的數位簽章生成;拒絕目錄會將其拒絕。 | NIST SP 800-131A Rev.2 | §9 |
| 低於 112 位元強度的簽章生成(RSA < 2048、ECDSA order < 224)不被允許;金鑰下限強制此規定。 | NIST SP 800-131A Rev.2 | §3 Table 2 |
| 對已生成 SHA-1 簽章的驗證屬於舊制用途;其不經由生成閘門路由。 | NIST SP 800-131A Rev.2 | Change summary (9.x4.p12) |
所有條款皆為轉述;未重現任何規範性文字。NextPDF 不作任何 FIPS 140 認證宣稱。 模組將其行為與所引條款對齊,作為一項合規協助能力。一個部署是否符合 FIPS,取決於操作者的驗證提供者、模組邊界定義與合規計畫——而非僅取決於 NextPDF。
開發備註
標題為「開發備註」的區段- 確定性失敗測試透過
FipsSelfTest建構子,或透過FipsCryptoPolicy::strict()、standard()及FipsBootstrap方法上的$selfTest參數注入受損的提供者。 - 程序黏著的錯誤閂鎖有一個內部的、僅供測試的重設鉤子。它不屬於受支援的 API,正式程式碼絕不可呼叫它。
- 每一個 PHP 工作程序執行自己的開機序列。報告以實例為單位快取,故熱路徑斷言是常數時間的狀態檢查。
- 不要捕捉
FipsModuleErrorStateException後繼續執行。此例外意味模組拒絕加密服務;正確的回應是停止,並在補救後重啟程序。 FipsBootstrap::selfTestReport()服務於按需與週期性自我測試需求,例如健康端點。一次通過的按需執行絕不會清除已閂鎖的錯誤。
- FIPS 140-2/3 加密政策與自我測試 — 附設定與範例的能力頁。
- 安全性 — 深入參考 — 整合的 Enterprise 安全控制。
- 簽章 — 深入參考 — PAdES 長期簽章生成器及其 FIPS 模式備註。
- 安全性 — NextPDF Core — 政策所綁定的 Core 加密與簽署表面。
發布邊界
標題為「發布邊界」的區段本頁僅記載外部可觀察的行為與受支援的公開 API 表面。內部命名空間路徑、輔助類別、機制表、runbook 檔名與工單前綴皆不在範圍內。