ruby-on-rails - 在 Rails 中验证 pdf 的数字签名时出现折纸和 OpenSSL 错误
问题描述
我需要验证我收到的 PDF 的数字签名,我搜索了几个 gem,我找到了 Origami pdf reader 和 openssl 来解析证书。我有两个证书文件,一个是 .cer 和子过滤器adbe.x509.rsa_sha1类型 ,另一个是扩展名 .p7c 和子过滤器 PKCS7 。我使用 openssl gem 来读取 .cer 类型的证书,当我尝试使用 pdf 验证它时,它给了我错误NotImplementedError: Unsupported signature method "adbe.x509.rsa_sha1"并且当我尝试读取 .p7c 文件时,OpenSSL 给了我错误OpenSSL::X509::CertificateError:嵌套 asn1 错误
如果有任何其他用于相同目的的宝石,如何克服这些错误?
我已经参考了这个堆栈溢出问题,但它有助于我的代码与该问题中的代码相似。
cert = OpenSSL::X509::Certificate.new(File::read('2.p7c'))
它抛出第二个错误
cert = OpenSSL::X509::Certificate.new(File::read('a.cer'))
pdf.verify(trusted_certs: [cert])
它给了我第一个错误
谢谢
解决方案
# REFERENCE
# https://www.rubydoc.info/gems/origami/Origami/PDF
# https://github.com/gdelugre/origami/blob/master/test/test_pdf_sign.rb
# https://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/X509/Certificate.html
# Usage
# ruby pdf_signer.rb some_file.pdf
require 'openssl'
require 'stringio'
require "time"
# require 'byebug' Not necessary but useful
begin
require 'origami'
rescue LoadError
$: << File.join(__dir__, "../../lib")
require 'origami'
end
include Origami
input_file = ARGV[0]
OUTPUT_FILE = "#{File.basename(__FILE__, ".rb")}.pdf"
puts "Generating a RSA key pair."
key = OpenSSL::PKey::RSA.new 2048
puts "Generating a self-signed certificate."
name = OpenSSL::X509::Name.parse 'CN=origami/DC=example'
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = 0
cert.not_before = Time.now
cert.not_after = Time.now + 3600
cert.public_key = key.public_key
cert.subject = name
cert.issuer = name
cert.sign key, OpenSSL::Digest::SHA256.new
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')
#################################################
# Read input PDF
#################################################
pdf = PDF.read(input_file)
page = pdf.get_page(1)
#################################################
# prepare annotation data ( visable time_stamp )
#################################################
width = 200.0
height = 50.0
x = page.MediaBox[2].to_f - width - height
y = height
size = 8
now = Time.now
text_annotation = Annotation::AppearanceStream.new
text_annotation.Type = Origami::Name.new("XObject")
text_annotation.Resources = Resources.new
text_annotation.Resources.ProcSet = [Origami::Name.new("Text")]
text_annotation.set_indirect(true)
text_annotation.Matrix = [ 1, 0, 0, 1, 0, 0 ]
text_annotation.BBox = [ 0, 0, width, height ]
text_annotation.write("Signed at #{now.iso8601}", x: size, y: (height/2)-(size/2), size: size)
# Add signature annotation (so it becomes visibles in PDF document)
signature_annotation = Annotation::Widget::Signature.new
signature_annotation.Rect = Rectangle[llx: x, lly: y+height, urx: x+width, ury: y]
signature_annotation.F = Annotation::Flags::PRINT
signature_annotation.set_normal_appearance(text_annotation)
page.add_annotation(signature_annotation)
############################
# Sign the PDF with the specified keys
pdf.sign( cert,
key,
method: 'adbe.pkcs7.detached',
annotation: signature_annotation,
location: "Canada",
contact: "someone@localhost.com",
reason: "Proof of concept")
# Save the resulting file
pdf.save(OUTPUT_FILE)
puts "PDF file saved as #{OUTPUT_FILE}."
# Now that we have signed and saved, lets re-open it and prove the concept
document = PDF.read(OUTPUT_FILE)
document.signature.inspect
begin
puts "******"
puts document.verify(trusted_certs: [cert])
puts "******"
rescue StandardError => e
puts e.message
end
#puts document.author
open 'cert_123.crt', 'w' do |io|
io.write cert
end
cert_2 = OpenSSL::X509::Certificate.new(File.read('cert_123.crt'))
puts "$" * 40
puts document.verify(trusted_certs: [cert_2])
puts "$" * 40
# To verify that all of this has worked use adobe acrobat reader or similar
# product in which you can inspect the signatures. Not all PDF readers will
# allow you to read these signatures```
推荐阅读
- html - ngForm Angular2中的单选按钮
- bitbucket - 通过 appcenter 访问私有仓库作为依赖项
- python - 从文件 Python 中读取浮点数
- java - 如何从 url 获取文本并将其放在 textView 中?
- javascript - 在 Confluence 的 Javascript 中添加自定义快捷键
- mongodb - Mongo查询检查子对象是否存在
- docker - docker login 失败并出现 400 错误请求,对于 Docker 版本 18.09.7,构建 2d0083d
- javascript - 如何使字符串人类可读?
- python - 如何在一定时间范围内从文本中提取
- r - 为什么 scale_y_continuous 在饼图上比条形图效果更好?