ruby - 使用 Adob​​e PKCS#7 证书在 Origami 中进行签名 PDF 验证

标签 ruby pdf adobe pkcs#7 origami

总结和澄清:

使用折纸,从签名的 pdf 中提取证书(在 Adob​​e 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

据我所知,这应该始终是正确的。那么 Adob​​e 在签署 PDF 时是否使用了不同的 SHA 字节范围?我怎样才能让验证工作?

如果有任何帮助的话,在仔细检查折纸大师上的更改后,我能够从商店上下文中获取确切的 OpenSSL 错误:V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - 我认为这意味着来自它设置的 X509::Store。


完整背景

我正在尝试验证 PDF 的数字签名。这是我得到的:

我使用 Adob​​e Acrobat 签名的 PDF(尝试过 Pro 10 和 Reader DC)

key 是在 Acrobat Pro 中生成的,我可以访问 .p12,或者导出为 FDF、PKCS#7 或只是“证书文件”。还尝试通过 Apple 的“钥匙串(keychain)访问”加载此“证书文件”并将其导出为 .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。

请注意,处理 this excellent answer 中的代码工作正常,但似乎只有在使用 openssl 生成 X.509 key 对时才有效(例如,根据该代码的 ruby​​-land 绑定(bind))。不幸的是,我需要使用用户计算机上预先存在的 Adob​​e 签名。

话虽如此,除此之外我几乎没有什么限制;我可以要求用户以对我们有用的任何其他方式导出他们的证书(如果需要,我什至可以在他们的计算机上运行一些简单的代码),但我不能在过程中传输私钥。我不必使用 Origami 进行验证,但它必须是可从 ubuntu 服务器上的 ruby​​ 访问的命令。用户都在使用相当最新的软件的 Mac 上运行。

最佳答案

我已经离原来的问题有点远了,但也不是很多:

证书需要正确的扩展名

原代码中from Harry Fairbanks' very useful answer,扩展至关重要:


extension_factory = OpenSSL::X509::ExtensionFactory.new
extension_factory.issuer_certificate = cert
extension_factory.subject_certificate = cert

cert.add_extension extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
cert.add_extension extension_factory.create_extension('keyUsage', 'digitalSignature,keyCertSign')
cert.add_extension extension_factory.create_extension('subjectKeyIdentifier', 'hash')

所以...按照该答案的其余部分,如果将​​证书保存到 pemfile,扩展名也不会被保存

我能够创建 PDF,使用从 Acrobat reader 导出的 key 通过 Origami 对其进行签名,然后执行以下操作:

cert = OpenSSL::PKCS7.new(pdf_signature).certificates.first

origami.verify(trusted_certs: [cert]) #=> false

## ... then run the extension factory snippet above

origami.verify(trusted_certs: [cert]) #=> true

成功!事实上,就连 Adob​​e Acrobat Reader 也很高兴 - 我无法让它与 Origami 生成的自签名证书有关。

...但是,当我使用 Adob​​e Acrobat Reader 签署文档时,使用相同的 key ,在证书上执行相同的魔法咒语,我仍然得到 false来自验证调用。


注意:有人告诉我这实际上对某些人有效。不知道为什么它对我来说失败了 - 当我有机会玩时,我会再试一次。现在将其标记为已回答!

关于ruby - 使用 Adob​​e PKCS#7 证书在 Origami 中进行签名 PDF 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58769162/

相关文章:

mysql - 将 Adob​​e Analytics 连接到 MYSQL

javascript - 允许在加盖自定义动态图章后编辑表单字段

java - 如何将从 HTTP GET 响应获取的文件保存在磁盘文件 java 上

azure - Azure Key Vault 中的 AATL 文档签名证书

ruby-on-rails - 帖子中的真实性 token 无效

ruby-on-rails - 将resque连接到其他键值数据库而不是redis?

pdf - 使用 MikTex 在 Windows 中安装 pstricks

pdf - 摆脱 matlab 图的 pdf 输出周围的空白

ruby - 如何将已弃用的 iconv 更改为 String#encode 以进行无效的 UTF8 更正

ruby-on-rails - 如何编写这些资源的路由?