总结和澄清:
使用折纸,从签名的 pdf 中提取证书(在例如 Adobe Reader 中签名)我无法验证签名:
origami = Origami::PDF.read(File.open('/path/to/file.pdf', 'r'))
pdf_signature = origami.signature[:Contents]
cert = OpenSSL::PKCS7.new(pdf_signature).certificates.first
origami.verify(trusted_certs: [cert]) #=> false
据我所知,这应该始终是正确的。那么,也许 Adobe 在签署 PDF 时使用了不同的字节范围,它需要一个 SHA?我如何让该验证工作?
如果有任何帮助,在对折纸大师进行更改后,我能够从 storecontext 中获得确切的 OpenSSL 错误:V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - 我认为这意味着它来自 X509::Store 它设置。
完整背景
我正在尝试验证 PDF 的数字签名。这是我所拥有的:
我使用 Adobe Acrobat 签名的 PDF(尝试了 Pro 10 和 Reader DC)
密钥是在 Acrobat Pro 中生成的,我可以访问 .p12,或者导出为 FDF、PKCS#7 或只是“证书文件”。还尝试通过 Apple 的“钥匙串访问”加载此“证书文件”并将其导出为 .pem 这给出的结果与OpenSSL::PKCS7.new(File.read('/path/to/exported.p7c')).certificates.first.to_pem
给出的结果相同:
openssl pkcs7 -print_certs -inform der -in pkcs7file.p7c -out certificate.cer
所以,我很确定我已经正确提取了证书。
此外,我可以验证 PDF 中嵌入了完全相同的证书 -
pdf_signature = origami.signature[:Contents]
OpenSSL::PKCS7.new(pdf_signature).certificates.first.to_pem #=> Same as above
使用 Origami gem,我尝试加载证书并尝试验证:
cert = OpenSSL::X509::Certificate.new(File.read('/path/to/pem.cer'))
Origami::PDF.read(File.open('/path/to/file.pdf', 'r')).verify(trusted_certs: [cert])
Origami 的输出确认文档已签名,但该verify(..)
方法返回 false。
请注意,通过这个优秀答案中的代码工作正常,但它似乎只有在您使用 openssl 生成 X.509 密钥对时才有效(例如,根据该代码的 ruby-land 绑定)。不幸的是,我需要使用用户机器上预先存在的 Adobe 祝福签名。
也就是说,除此之外,我几乎没有什么限制;我可以要求用户以对我们有用的任何其他方式导出他们的证书(如果需要,我什至可以在他们的机器上运行一些简单的代码),但我不能在过程中传输私钥。我不必使用 Origami 进行验证,但它必须是可从 ubuntu 服务器上的 ruby 访问的命令。用户都在使用最新软件的 Mac 上运行。