由 HSM 支持的签名
PKCS#11 v3.1 Spec: ISO 32000-2, §12.8 ISO 32000-2 §12.8 Spec: FIPS 140-3 FIPS 140-3 Evidence: Standard-backed
硬件安全模块(HSM)会将签名密钥从你的进程中移出,放到一台设备之后;该设备按请求完成签名,但绝不会把密钥交还给调用方。本页说明 NextPDF 用来执行签名的 PKCS#11 接缝、密钥边界究竟位于何处,以及最终结果中哪些部分由引擎负责,而不是由设备或你来负责。
为什么这很重要
标题为“为什么这很重要”的章节只要签名密钥位于进程内存中,任何能读取该进程的东西都能读到它:一次堆转储、一个调试器、一次日志记录失误、一个存在漏洞的依赖。一旦私钥被复制,它过去生成的每一个签名都会受到质疑,而你无法收回这次泄露。HSM 的意义就在于:根本没有可供拿走的副本。
把边界弄错,代价会高昂且不易察觉。一个看起来由硬件支持、却把密钥载入内存来签名的工作流,既有 HSM 的运营成本,又有软件密钥的风险特征。这种区别在最终的 PDF 中并不可见,因此必须通过设计落实并经过验证,不能想当然。
简要版
标题为“简要版”的章节- PKCS#11 标准定义了一种被标记为敏感且不可导出的密钥对象。该对象的私有值无法以明文形式在令牌外被泄露。 Spec: PKCS#11, v3.1 §10.9 PKCS#11 v3.1 §10.9
- NextPDF 构建 PDF 签名结构和 CMS 容器。它通过 PKCS#11 接缝交付待签名的字节,再接收返回的签名。密钥从不跨越那条接缝。
- 这条接缝是一份稳定的契约。同一份契约可以由智能卡令牌、USB HSM、网络 HSM 和云 KMS 实现。引擎代码在它们之间不发生变化。
- NextPDF 是签名引擎软件。设备的硬件保证、验证状态、PIN 策略以及部署方式,都不是由引擎认证的内容。它使用该设备;它并不为该设备背书。
NextPDF 如何处理它
标题为“NextPDF 如何处理它”的章节精确地说,这条接缝
标题为“精确地说,这条接缝”的章节NextPDF 将组装签名与计算签名值区分开来。组装是引擎的工作:放置签名字段、在文件中预留空间、计算字节范围,并构建带有签名属性的 CMS SignedData。 Spec: ISO 32000-2, §12.8 ISO 32000-2 §12.8
计算签名值则被委派出去。引擎定义了一份精简的签名提供方契约:它接收一段不透明的字节串(实践中即 DER 编码的签名属性),并返回原始的签名字节。那份契约就是接缝。一侧是 PDF 与 CMS 逻辑;另一侧是一把密钥。提供方可以把那把密钥放在进程内(用于本地软件密钥)、放在云 KMS 中,或通过 PKCS#11 放在硬件令牌上。接缝之上的引擎代码在每种情形下都完全相同。只有它背后的提供方有所不同。
边界实际所在的位置
标题为“边界实际所在的位置”的章节PKCS#11——即 OASIS 密码令牌接口,历史上称为「Cryptoki」—— 是面向硬件令牌的标准 C 接口。NextPDF 的硬件路径使用 PKCS#11(直接使用,或在进程内绑定无法加载令牌的 engine 或 provider 部署中,通过 OpenSSL 命令行桥接)。
令牌上的密钥对象由两个定义其边界的属性创建。当密钥被标记为敏感或不可导出时,某些私有属性无法以明文形式在令牌外被泄露。 Spec: PKCS#11, v3.1 §10.9 PKCS#11 v3.1 §10.9 签名操作本身就是一次令牌调用——先 C_SignInit,再 C_Sign——由设备执行。 Spec: PKCS#11, v3.1 §5.10 PKCS#11 v3.1 §5.10 进入 NextPDF 的明文是待签名的字节。返回的是签名和证书。私钥不在这两条路径中的任何一条上。那就是边界,而强制执行它的是令牌,不是库。
- Step 1 of 4: ISO 32000-2 §12.8 — signature dictionary, ByteRange, Contents
- Step 2 of 4: RFC 5652 CMS SignedData — the signature container
- PKCS#11 v3.1 — token interface; sensitive, non-extractable key
- Step 4 of 4: FIPS 140-3 / ISO/IEC 19790 cryptographic module assurance (device-level, deployment-dependent)
一个 PIN,一次重新认证
标题为“一个 PIN,一次重新认证”的章节PKCS#11 允许一把密钥要求每次使用前都重新认证:当设置了 CKA_ALWAYS_AUTHENTICATE 属性时,用户必须再次出示 PIN
以进行每一次密码操作,而非每个会话仅一次。
Spec: PKCS#11, v3.1 §10.9 PKCS#11 v3.1 §10.9 NextPDF 的 PKCS#11 路径就是按这个要求编写的。PIN 是一个敏感参数。它不会被记录到日志,也不会被序列化。当某个会话报告已经登录时,NextPDF 会将其恢复到一个干净状态,从而让下一次签名获得一次全新的 PIN 校验。这对策略要求每次签名都输入一次 PIN 的 PIV 式令牌很重要。这是一种尊重设备策略的引擎行为;它不会放松该策略。
证据怎么说
标题为“证据怎么说”的章节 Evidence: Standard-backed 密钥不可导出这一属性并非 NextPDF 自行作出的主张。它属于 PKCS#11 模型:一个其
CKA_SENSITIVE 为真或 CKA_EXTRACTABLE 为假的密钥对象,不会交出其令牌外明文形式的私有值。 Spec: PKCS#11, v3.1 §10.9 PKCS#11 v3.1 §10.9
NextPDF 的作用在于它从不需要那个值:它通过
令牌的 C_Sign 操作来签名,而不是索要密钥材料。
Evidence: Standard-backed PDF 一侧锚定于
Spec: ISO 32000-2, §12.8 ISO 32000-2 §12.8 。字节范围摘要是在排除签名值后的文件上计算的。放入
Contents 条目中的签名值,是用于公钥签名的 DER 编码 CMS SignedData 对象。
HSM 只生成最内层的签名字节。
NextPDF 围绕它们构建其余结构,并将它们写入标准所定义的结构中。
Evidence: Standard-backed 设备保证由 Spec: FIPS 140-3 FIPS 140-3 及其基础标准 ISO/IEC 19790 来描述,它们在十一个需求领域中定义了四个递增的定性安全级别—— 从算法规格到物理防篡改证据。这些标准描述的是一个模块要主张某一级别必须满足什么。 它们是设备及其验证的属性,而非 NextPDF 的属性;而且——用 ISO/IEC 19790 自身的话来说——符合性本身并不足以 确保某个模块在特定部署中是安全的。
实践示例
标题为“实践示例”的章节下面的形态仅作示意。它展示的是接缝,而非可以照抄照搬的部署。关键在于:引擎收到的是一个签名者,自己从不接触密钥;签名者的 sign() 是一次进入设备的调用。
<?php
declare(strict_types=1);
use NextPDF\Contracts\HsmSignerInterface;
/** * Sign a PDF where the private key lives on a PKCS#11 token. * * `$hsm` is a hardware-backed signer. Its sign() delegates to the token; * the key never enters this process. Everything that makes the bytes a * valid PDF signature — field, byte range, CMS SignedData — is built by * the engine around the value the device returns. * * Token wiring (library path, slot, PIN, key label) is deployment * configuration and is intentionally out of scope here: those values are * operator-owned secrets, not library inputs to hardcode. */function signWithToken( string $pdfPath, HsmSignerInterface $hsm,): string { // The engine asks the signer only for: the certificate (to embed in // the CMS) and a signature over the bytes it computes. It never asks // for, and the contract never exposes, the private key. $certificateDer = $hsm->getCertificateDer(); $chainDer = $hsm->getCertificateChainDer();
// Pseudocode for the engine's own assembly step: build the signature // dictionary + CMS SignedData, then hand the signed-attributes bytes // to $hsm->sign(...) and place the returned octets in /Contents. return nextpdf_sign_pdf( pdfPath: $pdfPath, signer: $hsm, certificateDer: $certificateDer, chainDer: $chainDer, );}关于这种形态,需要坦率说明两点。进程内的 PKCS#11 绑定是一个独立的 PHP 扩展,标准 PHP 构建不包含它。硬件部署会把它作为平台的一部分安装并验证好(或使用 OpenSSL 命令行桥接),而不是事后补救。而且,向设备请求的算法必须是该密钥实际能执行的算法。当所配置的算法对所选提供方没有映射时,引擎会提早拒绝,而不是在某次令牌调用深处才失败。
常见误解
标题为“常见误解”的章节「使用 HSM 就意味着签名是经过 FIPS 验证的。」
并非如此,把这两者混为一谈正是陷阱所在。HSM 是密钥所在、操作执行的场所。FIPS 140-3 / ISO/IEC 19790 验证是设备(或某个特定模块配置)可能持有的属性,由某个验证计划确立——既不是调用库所赋予的,也不是 NextPDF 代设备所断言的。NextPDF 兼容于通过 PKCS#11 设备进行签名,且其签名路径已用具有类别代表性的令牌进行过测试。某一具体部署是否经过 FIPS 模块级验证,完全取决于硬件、它的证书,以及它的配置与运行方式。用准确的词来描述你实际拥有的东西。
限制与边界
标题为“限制与边界”的章节本页描述这条接缝以及它所依托的标准。它并不是一份部署保证,这条分界线值得直白地说明:
- 引擎职责。 构建签名字段、预留空间、计算字节范围、组装 CMS
SignedData、调用签名提供方,并按照 Spec: ISO 32000-2, §12.8 ISO 32000-2 §12.8 写出一个结构上正确的签名。NextPDF 的硬件路径为此符合 PKCS#11 签名接口。 - 设备与操作者职责。 硬件的防篡改能力、它的 FIPS 140-3 / ISO/IEC 19790 验证状态、密钥生成与保管、PIN 策略、插槽配置、固件以及物理安全。这些没有任何一项由引擎认证。
- “已测试”不等于“已认证”。 NextPDF 针对具有代表性的令牌类别拥有一条经过验证的路径——智能卡、USB、网络以及通过同一份 PKCS#11 契约接入的云 KMS 形态——这是一项兼容性声明。它不是一项认证、一份已验证模块计数,也不是对你具体设备的主张。下面的硬件类别,是通过一个标准接口实现集成的形态。把它们视为“接缝被实践过的地方”,而绝不要当作对你尚未亲自测试过的型号的保证。
- 后量子签名是实验性的。 当引擎通过令牌暴露后量子签名时,它是可选启用、受控的,并且验证对象是模拟件,而不是后量子 HSM 固件。PAdES 与 AdES 密码套件目录尚未承认这些套件可用于长期归档。不要把它当作可用于生产的能力。
| Edition | Availability |
|---|---|
| Core | 本版本中不提供。 Core 提供签名引擎以及签名提供方接缝,并附带一个本地软件密钥提供方。 |
| Pro | 云密钥管理——通过托管 KMS 密钥签名——是一项 Pro 能力,仅在行为层面进行描述。 |
| Enterprise | 可用。 通过 PKCS#11 接口进行的硬件令牌签名(以及一个用于 engine/provider 部署的 OpenSSL 命令行桥接)是一项 Enterprise 能力。 可用性是一项能力声明,而不是对任何设备或部署的认证。 |
通过同一个接口的集成形态
标题为“通过同一个接口的集成形态”的章节这些是 PKCS#11 接缝被实践过的形态。这一列说明“集成看起来是什么样的”,而不是“一份已验证、已认证或已计数的设备清单”。
| 集成形态 | 如何接入 | 密钥边界 | 保证是谁的属性 |
|---|---|---|---|
| 智能卡 / PIV 令牌 | PKCS#11 模块;常见为每次使用一个 PIN | 在卡上;不可导出 | 卡及其操作者 |
| USB HSM | PKCS#11 模块 | 在设备上;不可导出 | 设备及其操作者 |
| 网络 / 设备型 HSM | PKCS#11 模块连接到一台网络设备 | 在设备上;不可导出 | 设备、它的配置、操作者 |
| 云 KMS | 托管密钥提供方(Pro) | 在云服务中;从不返回 | 云提供商及其证明 |
| OpenSSL 提供方桥接 | 通过一个 OpenSSL 桥接使用 PKCS#11 | 在令牌上;不可导出 | 令牌及其操作者 |
简短常见问答
密钥会进入 PHP 进程吗? 不会。对于一把不可导出的 PKCS#11 密钥,其私有值无法以明文形式在令牌外被泄露。NextPDF 通过令牌操作来签名,全程只看到待签名的字节和返回的签名。
HSM 支持的签名在 PDF 内部有所不同吗? 没有。签名结构是同一个 CMS SignedData,位于同一个 Contents 条目中,覆盖同一个字节范围。HSM 改变的是签名发生的位置,而非写入磁盘后的形态。
我能因为通过 NextPDF 使用了 HSM 就主张 FIPS 合规吗? 只能审慎地主张。NextPDF 对设备的 FIPS 状态不作任何断言。任何此类主张都必须来自设备自身的验证及其部署方式,而不能来自 NextPDF 调用了它这一事实。
如果进程内的 PKCS#11 绑定不可用怎么办? 引擎会报告硬件签名不可用,而不会悄无声息地回退到软件密钥。对于进程内绑定无法加载令牌的部署,存在一条 OpenSSL 命令行桥接路径。
相关文档
标题为“相关文档”的章节- 合格签名详解 — 硬件密钥在哪些方面必要但不充分,以及 NextPDF 不扮演哪些角色。
- 签名如何置于 PDF 之中 — HSM 结果被写入其中的字节范围与签名字典机制。
- 在生产环境中运行 NextPDF — 硬件签名部署需要承担的运营面。
术语表
标题为“术语表”的章节- HSM(硬件安全模块) — 一种保存密钥并执行密码操作的加固设备,使密钥材料永不离开设备。
- PKCS#11 — OASIS 密码令牌接口标准(历史上称为「Cryptoki」);NextPDF 用来与硬件令牌通信的 C 接口。
- 不可导出密钥 — 一个其私有值无法以明文形式在令牌外被泄露的 PKCS#11 密钥对象(
CKA_SENSITIVE为真或CKA_EXTRACTABLE为假)。 - 接缝 — NextPDF 中的签名提供方边界:不透明字节进,签名字节出。 PDF 与 CMS 知识位于它之上;密钥位于它之后。
- CMS SignedData — 在 PDF 内部承载签名与证书的密码消息语法结构(RFC 5652)。
- FIPS 140-3 / ISO/IEC 19790 — 定义四个定性级别的密码模块安全标准;它们是设备及其验证的属性,而非调用库的属性。