使用 PHP 的 openssl_pkcs7_sign 签署 pdf 时出错

Error signing pdf with PHP's openssl_pkcs7_sign

我正在使用 TCPDF 生成 pdf 文档并对其进行签名。 TCPDF 本身只是调用 PHP 的 openssl_pkcs7_sign 函数,在我看来它是在调用基于 source code.

的 C 的 PKCS7_sign 函数

直到最近一切都运行良好。然后我更改了证书提供商。我刚刚更新了私钥、证书和证书链:

$pdf->setSignature(
                $this->public_certificate_path, 
                $this->private_key_path, 
                $this->private_key_password, 
                $this->extra_certificates_path, 
                1);

我在 extra_certificates_path 文件中以 PEM 格式复制了新的根证书和中间证书。我使用 openssl 验证了这个文件,它看起来不错。

现在,当我在 Adob​​e Reader 中打开签名的 PDF 时,它会显示这些错误:

请参阅下面的屏幕截图。

知道哪里出了问题吗?

分析OP共享的示例文件可以理解问题所在:文档中嵌入的签名容器超出了最初为其保留的大小。

因此,解决方案是为签名容器预留更多space。

事实上,OP 确认:

Indeed there was a place that specified the max signature length. I changed it, and it works.

此外,OP 表示他对如何识别问题感兴趣。

对于许多 PDF 问题,首先要使用 PDF 内部浏览器(如 iText RUPS 或 PDFBox PDFDebugger)检查 PDF。不过,在这种情况下,文本查看器和十六进制查看器就足够了。

使用文本查看器找到签名值字典(此处印刷精美,缩短了 Contents 条目):

10 0 obj
<<
  /Type /Sig
  /Filter /Adobe.PPKLite
  /SubFilter /adbe.pkcs7.detached
  /ByteRange[0 78679 90423 6699]
  /Contents<308217b7...563934bf>
  /Reference [
  <<
    /Type /SigRef
    /TransformMethod /DocMDP
    /TransformParams << /Type /TransformParams /P 1 /V /1.2 >>
  >> ]
  /M (D:20171129170713+00'00')
>>
endobj

ByteRange 条目表示 Contents 值(十六进制编码的签名容器)应该从文件偏移量 78679 到 90423-1 .使用十六进制查看器可以快速验证 Contents 值 (<308217b7...563934bf>) 的起始索引是否匹配,但结束索引位于比预期更晚的索引处。

你看,嵌入了一个太大的签名容器。 ;)