跳转到内容

由 HSM 支持的签名

Spec: ISO 32000-2, §12.8 Spec: FIPS 140-3 Evidence: Standard-backed

硬件安全模块(HSM)会将签名密钥从你的进程中移出,放到一台设备之后;该设备按请求完成签名,但绝不会把密钥交还给调用方。本页说明 NextPDF 用来执行签名的 PKCS#11 接缝、密钥边界究竟位于何处,以及最终结果中哪些部分由引擎负责,而不是由设备或你来负责。

只要签名密钥位于进程内存中,任何能读取该进程的东西都能读到它:一次堆转储、一个调试器、一次日志记录失误、一个存在漏洞的依赖。一旦私钥被复制,它过去生成的每一个签名都会受到质疑,而你无法收回这次泄露。HSM 的意义就在于:根本没有可供拿走的副本。

把边界弄错,代价会高昂且不易察觉。一个看起来由硬件支持、却把密钥载入内存来签名的工作流,既有 HSM 的运营成本,又有软件密钥的风险特征。这种区别在最终的 PDF 中并不可见,因此必须通过设计落实并经过验证,不能想当然。

  • PKCS#11 标准定义了一种被标记为敏感且不可导出的密钥对象。该对象的私有值无法以明文形式在令牌外被泄露 Spec: PKCS#11, v3.1 §10.9
  • NextPDF 构建 PDF 签名结构和 CMS 容器。它通过 PKCS#11 接缝交付待签名的字节,再接收返回的签名。密钥从不跨越那条接缝。
  • 这条接缝是一份稳定的契约。同一份契约可以由智能卡令牌、USB HSM、网络 HSM 和云 KMS 实现。引擎代码在它们之间不发生变化。
  • NextPDF 是签名引擎软件。设备的硬件保证、验证状态、PIN 策略以及部署方式,都不是由引擎认证的内容。它使用该设备;它并不为该设备背书。

NextPDF 将组装签名计算签名值区分开来。组装是引擎的工作:放置签名字段、在文件中预留空间、计算字节范围,并构建带有签名属性的 CMS SignedData Spec: 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 签名操作本身就是一次令牌调用——先 C_SignInit,再 C_Sign——由设备执行。 Spec: PKCS#11, v3.1 §5.10 进入 NextPDF 的明文是待签名的字节。返回的是签名和证书。私钥不在这两条路径中的任何一条上。那就是边界,而强制执行它的是令牌,不是库。

  1. Step 1 of 4: ISO 32000-2 §12.8 — signature dictionary, ByteRange, Contents
  2. Step 2 of 4: RFC 5652 CMS SignedData — the signature container
  3. Step 4 of 4: FIPS 140-3 / ISO/IEC 19790 cryptographic module assurance (device-level, deployment-dependent)
一个由硬件支持的 PDF 签名所依托的根基,按顺序为:PDF 载体(ISO 32000-2 §12.8)、它所容纳的 CMS 容器、NextPDF 通过其进行签名的令牌接口(PKCS#11),以及描述其背后设备——但本身并不保证该设备——的模块保证标准。

PKCS#11 允许一把密钥要求每次使用前都重新认证:当设置了 CKA_ALWAYS_AUTHENTICATE 属性时,用户必须再次出示 PIN 以进行每一次密码操作,而非每个会话仅一次。 Spec: 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 NextPDF 的作用在于它从不需要那个值:它通过 令牌的 C_Sign 操作来签名,而不是索要密钥材料。

Evidence: Standard-backed PDF 一侧锚定于 Spec: ISO 32000-2, §12.8 。字节范围摘要是在排除签名值后的文件上计算的。放入 Contents 条目中的签名值,是用于公钥签名的 DER 编码 CMS SignedData 对象。 HSM 只生成最内层的签名字节。 NextPDF 围绕它们构建其余结构,并将它们写入标准所定义的结构中。

Evidence: Standard-backed 设备保证由 Spec: 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 写出一个结构上正确的签名。NextPDF 的硬件路径为此符合 PKCS#11 签名接口。
  • 设备与操作者职责。 硬件的防篡改能力、它的 FIPS 140-3 / ISO/IEC 19790 验证状态、密钥生成与保管、PIN 策略、插槽配置、固件以及物理安全。这些没有任何一项由引擎认证。
  • “已测试”不等于“已认证”。 NextPDF 针对具有代表性的令牌类别拥有一条经过验证的路径——智能卡、USB、网络以及通过同一份 PKCS#11 契约接入的云 KMS 形态——这是一项兼容性声明。它不是一项认证、一份已验证模块计数,也不是对你具体设备的主张。下面的硬件类别,是通过一个标准接口实现集成的形态。把它们视为“接缝被实践过的地方”,而绝不要当作对你尚未亲自测试过的型号的保证。
  • 后量子签名是实验性的。 当引擎通过令牌暴露后量子签名时,它是可选启用、受控的,并且验证对象是模拟件,而不是后量子 HSM 固件。PAdESAdES 密码套件目录尚未承认这些套件可用于长期归档。不要把它当作可用于生产的能力。
HSM-backed signing via PKCS#11 — edition availability
Edition Availability
Core

本版本中不提供。 Core 提供签名引擎以及签名提供方接缝,并附带一个本地软件密钥提供方。

Pro

云密钥管理——通过托管 KMS 密钥签名——是一项 Pro 能力,仅在行为层面进行描述。

Enterprise

可用。 通过 PKCS#11 接口进行的硬件令牌签名(以及一个用于 engine/provider 部署的 OpenSSL 命令行桥接)是一项 Enterprise 能力。 可用性是一项能力声明,而不是对任何设备或部署的认证。

这些是 PKCS#11 接缝被实践过的形态。这一列说明“集成看起来是什么样的”,而不是“一份已验证、已认证或已计数的设备清单”。

集成形态如何接入密钥边界保证是谁的属性
智能卡 / PIV 令牌PKCS#11 模块;常见为每次使用一个 PIN在卡上;不可导出卡及其操作者
USB HSMPKCS#11 模块在设备上;不可导出设备及其操作者
网络 / 设备型 HSMPKCS#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 命令行桥接路径。

  • 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 — 定义四个定性级别的密码模块安全标准;它们是设备及其验证的属性,而非调用库的属性。