【发布时间】:2017-07-06 13:18:43
【问题描述】:
我正在使用 PHP 在服务器端签署 PDF 文件,我希望 Adobe Reader 在生成的 PDF 上显示此横幅,说明文件已成功签署:
我正在使用 TCPD 库 中的代码来实现这一点(我必须修改一些代码以满足我的需要)。 我的工作基于 Adobe 官方文档中的这两个文档:doc1 和 doc2。
我做什么:
-
将签名标签添加到 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); 计算和替换 ByteRange
-
像这样计算文件的哈希:
$hash_result = hash('sha256', $pdfdoc); -
使用 forge.js 对生成的哈希客户端签名:我使用我解析的 PFX 文件,然后使用 PFX 中包含的数据创建 PKCS7。
将哈希发送到服务器。
- 在内容标签中为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 可以被 Adobe 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 文件,并且在没有这些字段的情况下显示蓝色横幅。