是什么让 Adob​​e Reader 显示 "Signed" 面板?

What makes Adobe Reader display the "Signed" panel?

我正在使用 PHP 在服务器端签署 PDF 文件,我希望 Adob​​e Reader 在生成的 PDF 上显示此横幅,说明该文件已成功签署:

我正在使用 TCPDF 库 中的代码来实现此目的(我不得不修改一些代码以满足我的需要)。 我的工作基于 Adob​​e 官方文档中的这两个文档:doc1 and doc2.

我的工作:

  1. 将签名标签添加到 PDF 文件:

    // The ID of the last object of the PDF + 1 
    $sigobjid = preg_match_all("/([0-9]+) 0 obj/", $pdfdoc, $output_array);
    $sigobjid = end($output_array[1]) + 1;
    // Write the signature tags where needed
    $index_to_write = strrpos($pdfdoc,"endobj") + 6;
    $signature_tag = PHP_EOL . $sigobjid . ' 0 obj '. PHP_EOL . '<< /Type /Sig /Filter /Adobe.PPKLite /SubFilter /adbe.pkcs7.detached '. TCPDF_STATIC::$byterange_string . ' /Contents<'.str_repeat('0', $tcpdf->get_signature_max_length()).'> >>' . PHP_EOL . 'endobj';
    $pdfdoc = substr_replace($pdfdoc, $signature_tag, $index_to_write, 0);
    
  2. 计算并替换 ByteRange

  3. 像这样计算文件的哈希值:

    $hash_result = hash('sha256', $pdfdoc);
    
  4. 使用 forge.js 对生成的哈希客户端进行签名:我使用我解析的 PFX 文件,然后使用包含的数据创建 PKCS7在 PFX 中。

  5. 将哈希发送到服务器。

  6. 将签名添加到 Content 标签中的 PDF。

编辑: 感谢@mkl 的评论,我还尝试使用 AcroForm 将我的 Sig 对象引用到我的 PDF 文件中:

11 0 obj
<< /Type /Sig /Filter /Adobe.PPKLite /SubFilter /adbe.pkcs7.detached /ByteRange[0 2846 14590 507] /Contents< ...
endobj
12 0 obj
<</AcroForm 11 0 R >>
endobj

它也不起作用。我应该如何填写 AcroForm 字段?

生成的 PDF 可由 Adob​​e 阅读 Reader 但蓝色横幅没有出现,为什么?

好的,我自己解决了,所以对于那些想知道的人,您需要这些字段:

1 0 obj
<<
/Type /Catalog /AcroForm << /Fields [12 0 R 13 0 R] /NeedAppearances false  /SigFlags 3 /DR << /Font << /F1 14 0 R >> >> /DA (/F1 0 Tf 0 g) /Q 0 >> /Perms << /DocMDP 11 0 R >>
>>
endobj

4 0 obj
<<
/Type /Page
...
endobj

11 0 obj
<< /Type /Sig /Filter /Adobe.PPKLite /SubFilter /adbe.pkcs7.detached /ByteRange[0 3153 14897 922] /Contents<...> /Reference [ << /Type /SigRef /DigestMethod /SHA256 /TransformMethod /DocMDP /TransformParams << /Type /TransformParams /P 2 /V /1.2 >> >> ] >>
endobj

12 0 obj
<< /Type /Annot /Subtype /Widget /Rect [510.236220 572.598661 552.755906 615.118346] /P 4 0 R /F 4 /FT /Sig /T (Signer Name) /Ff 0 >>
endobj

13 0 obj
<< /Type /Annot /Subtype /Widget /Rect [510.236220 572.598661 552.755906 615.118346] /P 4 0 R /F 4 /FT /Sig /T (Signer Name) /Ff 0  /V 11 0 R >>
endobj

14 0 obj
<</Type /Font /Subtype /Type1 /BaseFont /Helvetica /Name /F1 /Encoding /WinAnsiEncoding >>
endobj

你基本上需要:

  • 1 字体 对象(本例中为对象 14)
  • 1 Sig 对象 (obj 11) 在 'contents' 字段中包含签名
  • 1 页面 对象(对象 4)
  • 2 Annot 对象(对象 12 和 13)引用带有 P 标志的第一个页面对象和带有 V 标志
  • 1 AcroForm 主字段 Catalog (obj 1) 在 Fields 数组中引用你的 2 Annot 对象,引用你的字体F1 字段,以及您在 DocMDP 字段中的签名。

编辑: DocMDP 字段不是强制性的,只需要一个 Annot。也不需要 Font