【问题标题】:What makes Adobe Reader display the "Signed" panel?是什么让 Adob​​e Reader 显示“已签名”面板?
【发布时间】:2017-07-06 13:18:43
【问题描述】:

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

我正在使用 TCPD 库 中的代码来实现这一点(我必须修改一些代码以满足我的需要)。 我的工作基于 Adob​​e 官方文档中的这两个文档:doc1doc2

我做什么:

  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 文件,然后使用 PFX 中包含的数据创建 PKCS7

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

  6. 内容标签中为PDF添加签名。

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

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 读取,但没有出现蓝色横幅,为什么?

【问题讨论】:

  • 可以分享PDF吗?
  • 我并不是很喜欢 PHP,但您展示的代码似乎只专注于创建签名字典。您是否也在其他地方创建了一个签名表单字段(或找到一个空的现有字段)并将您的签名字典分配为它的值?如果你不这样做,那么这就是(至少部分)问题,要让 PDF 查看器找到签名字典,它必须是 PDF AcroForm 结构中签名字段的值。
  • @mkl 感谢您的回答!我不知道 AcroForm 结构,因为它在文档中几乎没有提及。我试图添加一个像这样的引用 > 11 是我的 Sig 对象的 ID,但它也不起作用,什么也没有出现。你能告诉我 AcroForm 应该包含什么吗?
  • “我不知道 AcroForm 结构,因为它在文档中几乎没有提到。” - 嗯,ISO 32000-1 的第 12.7 小节(超过 30 页)(您称为“doc1”)处理 AcroForm 表单。请阅读。作为提示:文档目录中的 AcroForm 条目应指向交互式表单字典。在这种情况下,您应该正确设置 SigFlags 并将 Fields 设置为表单字段的数组,即至少一个签名字段,其 V 值为您的签名字典,其 T 值为字段名称,其 AP 值包含外观。
  • 谢谢!我的意思是没有示例,这对于广泛使用的文件类型来说很奇怪。我不确定这些字段,因为我有我自己签名的 PDF 文件,并且在没有这些字段的情况下显示蓝色横幅。

标签: php pdf tcpdf


【解决方案1】:

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

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 字体对象(本例中为 obj 14)
  • 1 Sig 对象(obj 11)包含“内容”字段中的签名
  • 1 页面对象(obj 4)
  • 2 Annot 对象(obj 12 和 13)引用带有 P 标志的第一个页面对象和带有 V 标志的 Sig 对象
  • Catalog (obj 1) 中的 1 个 AcroForm 字段引用 Fields 数组中的 2 Annot 对象,在 F1 中引用您的字体> 字段,并在 DocMDP 字段中签名。

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

【讨论】:

    猜你喜欢
    • 2018-01-09
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多