Origami & OpenSSL error while validating digital signature of a pdf in rails

前端 未结 1 1619
误落风尘
误落风尘 2021-01-19 09:07

I need to verify the digital signature of a PDF that i receive, i searched for a couple of gems and i found Origami pdf reader and openssl to parse the certificate. I have

1条回答
  •  清酒与你
    2021-01-19 09:41

    
    # 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```
    
    

    0 讨论(0)
提交回复
热议问题