如何检查PDF是否有任何类型的数字签名

如何检查PDF是否有任何类型的数字签名,pdf,digital-signature,Pdf,Digital Signature,我需要了解PDF是否有任何类型的数字签名。我必须管理巨大的PDF,例如每个500 MB,所以我只需要找到一种方法来区分未签名和已签名的PDF(这样我就可以将刚签名的PDF发送到管理它们的方法)。迄今为止发现的任何过程都涉及到试图通过Bouncycastle libs(在我的例子中,是Java)来提取证书:如果存在,则对pdf进行签名;如果不存在,或引发异常,则不对(原文如此!)。但这显然是在消耗时间/内存,而不是资源浪费实现的例子 是否有任何与语言无关的快速方法,例如打开PDF文件,读取第一个字

我需要了解PDF是否有任何类型的数字签名。我必须管理巨大的PDF,例如每个500 MB,所以我只需要找到一种方法来区分未签名和已签名的PDF(这样我就可以将刚签名的PDF发送到管理它们的方法)。迄今为止发现的任何过程都涉及到试图通过Bouncycastle libs(在我的例子中,是Java)来提取证书:如果存在,则对pdf进行签名;如果不存在,或引发异常,则不对(原文如此!)。但这显然是在消耗时间/内存,而不是资源浪费实现的例子

是否有任何与语言无关的快速方法,例如打开PDF文件,读取第一个字节并找到一个信息,告诉该文件已签名? 或者,是否有任何参考手册详细说明如何在内部制作PDF


提前感谢您

您将希望使用PDF库,而不是自己尝试实现这一点,否则您将在处理线性化文档、过滤器、增量更新、对象流、交叉引用流等方面陷入困境

关于参考材料;根据我粗略的搜索,Adobe似乎不再向任何人和所有人提供ISO 32000:2008规范的版本,尽管该规范主要是ISO一致性语言的翻译

因此,假设PDF v1.7参考,最相关的部分将是8.7(数字签名)、3.6.1(文档目录)和8.6(交互式表单)

基本流程将是:

  • 阅读文档目录中的“Perms”和“AcroForm”条目
  • 阅读“Perms”字典中的“DocMDP”、“UR”或“UR3”条目。如果存在这些条目,那么很可能您有一个经过认证的文档或一个启用了读卡器的文档
  • 阅读“AcroForm”条目;(请确保您没有“XFA”条目,因为用Porgy和Bess的Fraizer的话说:Dat是一个复杂因素!)。基本上,您希望首先检查是否存在(可选)的“SigFlags”条目,在这种情况下,非零值将指示Fields数组中存在签名。否则,您需要遍历“Fields”数组的每个条目,查找“FT”(字段类型)条目设置为“Sig”(签名)且“V”(值)条目不为空的字段字典

  • 使用能够使用文档的交叉引用表导航到正确的间接对象的PDF库应该比对文档进行强制搜索以获取证书更快、资源消耗更少。

    这不是最佳解决方案,但它是另一种解决方案。。。您可以选择检查“Sigflags”并在第一次匹配时停止:

    grep -m1 "/Sigflags" ${PDF_FILE}
    
    或者在目录中获取此类文件:

    grep -r --include=*.pdf -m1 -l "/Sigflags" . > signed_pdfs.txt
    
    grep -r --include=*.pdf -m1 -L "/Sigflags" . > non_signed_pdfs.txt
    
    Grep可以非常快速地处理大文件。您可以在批处理中运行它一定时间,然后处理生成的列表(.txt文件)

    请注意,可以在签名后增量修改文件,并且可能不会对最后一个版本进行签名。这就是“签名”的实际含义

    无论如何,如果文件没有/Sigflags字符串,几乎可以肯定它从未被签名

    注意,一致性阅读器开始向后读取(从文件末尾开始),因为有一个交叉引用表,其中说明了每个对象的位置

    我建议您使用检查文件的内部结构。它支持在文件上执行It命令。例如:

     $ peepdf -C "search /SigFlags" signed.pdf 
    
       [6]
    
      $ peepdf -C "search /SigFlags" non-signed.pdf 
    
        Not found!!
    

    但我还没有测试它的性能。您可以使用它浏览PDF的内部结构并从中学习。查看附件中的PDF示例。

    使用命令行,您可以使用poppler utils软件包(适用于Ubuntu 20.04)中的pdfsig工具检查文件是否具有数字签名

    将生成包含签名详细数据和验证数据的输出。如果需要扫描pdf文件树并获取已签名pdf的列表,可以使用bash命令,如:

    find ./path/to/files -iname '*.pdf'  \
    -exec bash -c 'pdfsig "$0";  \
    if [[ $? -eq 0 ]]; then  \
    echo "$0" >> signed-files.txt; fi' {} \;
    
    您将在本地目录的signed-files.txt文件中获得已签名文件的列表


    我发现这比尝试从pdf文件中grep一些文本要可靠得多(例如,立陶宛签名服务生成的pdf文件不包含前面答案中提到的字符串“SigFlags”)。

    该测试有多确定?PDF确实有一个标志,该标志应由签名PDF设置。但是,此标志也可以由未签名的PDF设置,并且签名的PDF可能没有设置该标志。不过,通常情况下,国旗的使用是相当忠实的。测试这个标志就足够了吗?顺便说一句,pdf的大小并不重要,通常只需要解析一小部分。显然,我可以将未签名的文件发送给签名文件处理器,但这样的处理器会耗费时间/资源,因此任何误报都会减慢整个应用程序的速度。但是,如果“标志检查”只产生(稀疏地)误报,而不提供误报,也可以。如果不允许误报,你将不得不按照Patrick的答案进行概括。根据您的输入PDF如何遵循PDF规范,您甚至可能需要检查更多内容:过去有一些PDF处理程序根本不更新AcroForm字典,只通过向某些页面添加注释来添加字段。要识别此类处理器的签名,您还必须访问所有页面注释阵列。“看起来Adobe不再向任何人和所有人提供其ISO 32000:2008规范版本”-请查看“快速链接”部分正上方的底部。在我的特定情况下,它没有任何用处,但对于使用脚本的人来说,这无疑是一个很好的信息。谢谢
    find ./path/to/files -iname '*.pdf'  \
    -exec bash -c 'pdfsig "$0";  \
    if [[ $? -eq 0 ]]; then  \
    echo "$0" >> signed-files.txt; fi' {} \;