使用PHP< openssl_pkcs7_sign签署pdf时出错

时间:2017-12-06 11:52:37

标签: openssl cryptography pdf-generation tcpdf php-openssl

我正在使用TCPDF生成pdf文档并对其进行签名。 TCPDF本身只调用PHP的openssl_pkcs7_sign函数,在我看来,它基于source code调用C&#39 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验证了此文件,看起来很好。

现在,当我在Adobe Reader中打开已签名的PDF时,会显示以下错误:

  • 打开文件时,它说
      

    此文件已损坏但正在修复

  • 顶部的蓝丝带说
      

    认证无效

  • 当我打开签名面板时,它说
      

    通过%s认证

  • 错误详情说
      

    此签名中包含的格式或信息存在错误(支持信息:SigDict / Contents非法数据)

  • 当我点击"证书详情"时,没有任何反应

见下面的截图。

知道可能出现什么问题吗?

enter image description here

1 个答案:

答案 0 :(得分:3)

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

因此,解决方案是为签名容器保留更多空间。

事实上,OP确认了:

  

确实有一个地方指定了最大签名长度。我改变了它,它有效。

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

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

使用文本查看器可以找到签名值字典(在此处打​​印得非常漂亮,内容条目缩短了):

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

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