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 | 无 | 构造函数是私有的;预设是唯一入口 |
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 | 以断言式边界包装一个策略 | — | 无 | 没有 $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 | 带公开只读字段的类型化策略违规 | — | — | 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 下属于旧版用途,从不经强制器路由。- 当接入了审计日志器时,每个断言边界都会在任何策略违规抛出之前发出一条 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,直到第一个断言边界运行套件。在断言时,PRE_OPERATIONAL被视为不可运行。
FIPS 模式行为
标题为“FIPS 模式行为”的章节本模块本身就是 FIPS 模式表面。当模块处于错误状态时,以及在运行上电前自检期间,加密输出被抑制:每个断言边界都会在产生任何签名或密文之前抛出 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 阶 < 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 表面。内部命名空间路径、辅助类、机制表、运行手册文件名以及工单前缀均不在范围内。