Skip to content

数字签名 (HasSecurity)

HasSecurity trait 提供 setSignature() 方法用于 PAdES 合规的数字签名。TCPDF-Next 通过 PadesOrchestratorTsaClient 与 LTV 模块支持四种签名等级 — 从基本(B-B)到存档(B-LTA)。所有签名方法皆返回 static 以支持链式串接。

快速参考

类 / 枚举用途
CertificateInfo加载签署证书(PEM 或 PKCS#12)
SignatureLevel枚举:PAdES_B_BPAdES_B_TPAdES_B_LTPAdES_B_LTA
TsaClientRFC 3161 时间戳授权客户端
SignatureAppearance可见或不可见的签名小部件
OcspClientRFC 6960 在线撤销检查
CrlFetcherRFC 5280 CRL 发布点获取

签名等级

等级包含内容有效性
B-B(基本)签名 + 签署证书在证书未被撤销期间有效
B-T(时间戳)B-B + RFC 3161 时间戳证明签名在某个时间点之前已存在
B-LT(长期)B-T + 包含 OCSP/CRL 响应的 DSS证书过期后仍可验证
B-LTA(存档)B-LT + 文件时间戳 + 存档循环可无限期验证

加载证书

从 PEM 文件

php
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;

$cert = CertificateInfo::fromFiles(
    certPath: '/path/to/certificate.pem',
    keyPath: '/path/to/private-key.pem',
    password: 'key-password',
    extraCerts: '/path/to/ca-chain.pem',  // 可选的中间证书
);

从 PKCS#12(.p12 / .pfx)

php
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;

$cert = CertificateInfo::fromPkcs12(
    p12Path: '/path/to/certificate.p12',
    password: 'pkcs12-password',
);

签署范例

php
use Yeeefang\TcpdfNext\Core\Document;
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
use Yeeefang\TcpdfNext\Contracts\SignatureLevel;
use Yeeefang\TcpdfNext\Security\Timestamp\TsaClient;

$cert = CertificateInfo::fromFiles(
    certPath: '/path/to/certificate.pem',
    keyPath: '/path/to/private-key.pem',
    password: 'key-password',
);

// PAdES B-B(基本)— 仅签名
$pdf = Document::create()
    ->setSignature($cert, SignatureLevel::PAdES_B_B)
    ->addPage()
    ->setFont('Helvetica', '', 12)
    ->cell(0, 10, 'Signed document (B-B)')
    ->save('signed-bb.pdf');

// PAdES B-T(时间戳)— 签名 + 时间戳
$tsa = new TsaClient('https://freetsa.org/tsr');
$pdf = Document::create()
    ->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
    ->addPage()
    ->cell(0, 10, 'Signed with timestamp (B-T)')
    ->save('signed-bt.pdf');

// PAdES B-LTA(存档)— 完整长期验证
$pdf = Document::create()
    ->setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsa)
    ->addPage()
    ->cell(0, 10, 'Archival signature (B-LTA)')
    ->save('signed-blta.pdf');

TsaClient — 时间戳授权

TsaClient 支持可选的验证机制。Nonce 验证与 DNS 固定默认启用,以防止重放攻击与 SSRF。

php
$tsa = new TsaClient(
    url: 'https://tsa.example.com/timestamp',
    user: 'tsa-user',
    pass: 'tsa-password',
);

B-T 及以上等级皆需要提供 TsaClient。时间戳依据 RFC 3161 标准,向时间戳授权机构(TSA)请求可信的时间证明,确保签名的时间不可否认性。

长期验证(B-LT / B-LTA)

B-LT 与 B-LTA 等级会自动获取并嵌入撤销数据:

  • OcspClient — 根据证书的 AIA 扩展,查询 OCSP 响应者(RFC 6960)
  • CrlFetcher — 从发布点下载 CRL(RFC 5280)
  • DSS(文件安全存储区) — 将 OCSP 响应与 CRL 存储在文件安全存储区中
  • VRI(验证相关信息) — 每个签名的验证数据(可选,依 ETSI 建议)

B-LTA 还会额外添加文件时间戳,启动存档循环 — 文件可通过重新加盖时间戳来无限期延长有效性。

签名外观

默认情况下,签名为不可见。若要创建可见的签名小部件:

php
use Yeeefang\TcpdfNext\Security\Signature\SignatureAppearance;

$pdf = Document::create()
    ->setSignature($cert, SignatureLevel::PAdES_B_T, $tsa)
    ->setSignatureAppearance(
        SignatureAppearance::visible(x: 20, y: 250, w: 80, h: 30)
    )
    ->addPage()
    ->cell(0, 10, 'Document with visible signature')
    ->save('visible-signature.pdf');

若要明确设置不可见签名:

php
$pdf->setSignatureAppearance(SignatureAppearance::invisible());

签名等级比较

特性B-BB-TB-LTB-LTA
数字签名VVVV
签署证书VVVV
RFC 3161 时间戳VVV
DSS(OCSP + CRL)VV
文件时间戳V
存档循环V
证书过期后可验证VV
无限期可验证V

方法参考

php
$pdf->setSignature(
    CertificateInfo   $cert,           // 证书与私密密钥
    SignatureLevel    $level,           // B-B、B-T、B-LT 或 B-LTA
    ?TsaClient        $tsa   = null,   // B-T、B-LT、B-LTA 必须提供
);

返回 static 以支持链式串接。签名在调用 save()output() 时应用。

签名算法通过 phpseclib3 实现:RSA PKCS#1 v1.5(默认,最广泛的兼容性)与 RSASSA-PSS(更强的填充方案,建议新部署使用)。

完整 PKCS#12 范例

php
use Yeeefang\TcpdfNext\Core\Document;
use Yeeefang\TcpdfNext\Security\Signature\CertificateInfo;
use Yeeefang\TcpdfNext\Security\Signature\SignatureAppearance;
use Yeeefang\TcpdfNext\Contracts\SignatureLevel;
use Yeeefang\TcpdfNext\Security\Timestamp\TsaClient;

// 从 PKCS#12 加载证书
$cert = CertificateInfo::fromPkcs12(
    p12Path: '/path/to/certificate.p12',
    password: 'pkcs12-password',
);

// 设置时间戳授权
$tsa = new TsaClient('https://freetsa.org/tsr');

// 创建具有 B-LTA 等级签名的文件
$pdf = Document::create()
    ->setTitle('Signed Contract')
    ->setAuthor('Legal Department')
    ->setSignature($cert, SignatureLevel::PAdES_B_LTA, $tsa)
    ->setSignatureAppearance(
        SignatureAppearance::visible(x: 20, y: 250, w: 80, h: 30)
    )
    ->addPage()
    ->setFont('Helvetica', 'B', 18)
    ->cell(0, 15, 'Service Agreement', newLine: true)
    ->setFont('Helvetica', '', 12)
    ->multiCell(0, 6, 'This document has been digitally signed with a PAdES B-LTA '
        . 'archival signature. The signature includes a trusted timestamp and '
        . 'embedded revocation data for long-term validation.')
    ->save('signed-contract.pdf');

以 LGPL-3.0-or-later 许可证发布。