Insert digital signature into existing pdf file

前端 未结 2 707
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-02 21:30

I need to insert a digital signature into already existing pdf files, using a rails application server. (Basically, clients upload pdf files and the server signs them with a

相关标签:
2条回答
  • 2020-12-02 22:00

    After some research, recurring to the OpenSSL documentation and exploring the Origami solution, i built the code below, and managed to insert a locally generated signature/certificate into a pdf document. Now I just need to figure out how to use this with an external generated certificate (check version 2 below, where i solved it). I've opened a new question where you can find some details on a difficulty i had with OpenSSL and DER encoded certificates.

    To develop version 2, i also spent some time wondering how to add an annotation - so the signature becomes visible in Adobe reader - without adding a new page to the document. From origami documentation, i found the get_page method, which solved my last problem on this. I'm using Adobe Reader X, for the record.

    Hope you find this useful as I will ;-).

    VERSION 1 - Generate certificate and key file, and insert them directly into the document

    require 'openssl'
    
    begin
      require 'origami'
    rescue LoadError
      ORIGAMIDIR = "C:\RailsInstaller\Ruby1.9.3\lib\ruby\gems\1.9.1\gems\origami-1.2.4\lib"
      $: << ORIGAMIDIR
      require 'origami'
    end
    include Origami
    
    # Code below is based on documentation available on
    # http://www.ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL.html
    key = OpenSSL::PKey::RSA.new 2048
    
    open 'private_key.pem', 'w' do |io| io.write key.to_pem end
    open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
    
    cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
    pass_phrase = 'Origami rocks'
    
    key_secure = key.export cipher, pass_phrase
    
    open 'private_key.pem', 'w' do |io|
      io.write key_secure
    end
    
    #Create the certificate
    
    name = OpenSSL::X509::Name.parse 'CN=nobody/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
    
    
    OUTPUTFILE = "test.pdf"
    
    contents = ContentStream.new.setFilter(:FlateDecode)
    contents.write OUTPUTFILE,
      :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30
    
    pdf = PDF.read('Sample.pdf')
    
    
    # Open certificate files
    
    #sigannot = Annotation::Widget::Signature.new
    #sigannot.Rect = Rectangle[:llx => 89.0, :lly => 386.0, :urx => 190.0, :ury => 353.0]
    
    #page.add_annot(sigannot)
    
    # Sign the PDF with the specified keys
    pdf.sign(cert, key, 
      :method => 'adbe.pkcs7.sha1',
      #:annotation => sigannot, 
      :location => "Portugal", 
      :contact => "myemail@email.tt", 
      :reason => "Proof of Concept"
    )
    
    # Save the resulting file
    pdf.save(OUTPUTFILE)
    

    VERSION 2 - Use existing certificates to sign a pdf document

    require 'openssl'
    
    begin
      require 'origami'
    rescue LoadError
      ORIGAMIDIR = "C:\RailsInstaller\Ruby1.9.3\lib\ruby\gems\1.9.1\gems\origami-1.2.4\lib"
      $: << ORIGAMIDIR
      require 'origami'
    end
    include Origami
    
    INPUTFILE = "Sample.pdf"
    @inputfile = String.new(INPUTFILE)
    OUTPUTFILE = @inputfile.insert(INPUTFILE.rindex("."),"_signed")
    CERTFILE = "certificate.pem"
    RSAKEYFILE = "private_key.pem"
    passphrase = "your passphrase"
    
    key4pem=File.read RSAKEYFILE
    
    key = OpenSSL::PKey::RSA.new key4pem, passphrase
    cert = OpenSSL::X509::Certificate.new(File.read CERTFILE)
    
    pdf = PDF.read(INPUTFILE)
    page = pdf.get_page(1)
    
    # Add signature annotation (so it becomes visibles in pdf document)
    
    sigannot = Annotation::Widget::Signature.new
    sigannot.Rect = Rectangle[:llx => 89.0, :lly => 386.0, :urx => 190.0, :ury => 353.0]
    
    page.add_annot(sigannot)
    
    # Sign the PDF with the specified keys
    pdf.sign(cert, key, 
      :method => 'adbe.pkcs7.sha1',
      :annotation => sigannot, 
      :location => "Portugal", 
      :contact => "myemail@email.tt", 
      :reason => "Proof of Concept"
    )
    
    # Save the resulting file
    pdf.save(OUTPUTFILE)
    
    0 讨论(0)
  • 2020-12-02 22:10

    If you're working on a project for pay, you might want to consider jPDFSecure, a commercial Java library built for developers to digitally sign PDF documents and change security settings on PDF Documents. With jPDFSecure, your application or java applet can encrypt PDF documents, set permissions and passwords, and create and apply digital signatures. jPDFSecure is optimized for performance and is built on top of Qoppa's proprietary PDF technology so there is no need for any third party software or drivers.

    jPDFSecure has a simple interface to load PDF documents from files, network drives,URLs and even input streams, which can be generated runtime or come directly from a database. After changing security settings, jPDFSecure can save the document to a file, a java.io.OutputStream or a javax.servlet.ServletOutputStream when running in a Java EE application server to output the file directly to a browser.

    jPDFSecure is platform independent and can be used in any environment that supports Java, including Windows, Mac OSX and Linux.

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