2012-08-22 63 views
11

我需要插入一個數字簽名到現有的PDF文件,使用Rails應用服務器。 (基本上,客戶端上傳PDF文件和服務器與本地標誌證書它們)插入數字簽名到現有的PDF文件

我一直在使用JSignpdf插入數字簽名轉換成PDF文件,並開始探查寶石紅寶石......

我已經發現另一個便攜文件在rubypdf網站http://soft.rubypdf.com/software/pdf-digital-signe上完成這項工作,但找不到任何寶石,甚至沒有示例代碼在ruby中這樣做。

我也看了Digital signature verification with OpenSSL,但不明白如何實際簽署一個已經存在的文件,與當地的證書文件。

我也在http://code.google.com/p/origami-pdf/高峯期,但對於假設「簡單」(至少在概念上)的任務來說,這似乎有點苛刻。

任何意見/建議?

謝謝

+1

任務只是「假設」簡單,但在各個層面上都有許多警告和複雜性。這就是爲什麼你找不到任何東西的原因之一 - 我懷疑有人會投入大量精力爲Ruby開發一個工業品質的PDF簽名者。如果你可以用某種方式調用外部類,我會爲.NET/Mono建議一些好的組件。 –

+0

嘿@ EugeneMayevski'EldoSCorp,我想SOGETI是用Origami做的,現在我已經把它放在這裏了,稍微研究一下Origami和OpenSSL的領域。請享用。 – MrWater

+0

@MrWater:請您提供一些示例代碼,說明如何使用jSignPDF將數字簽名添加到使用Java的PDF中? – tarekahf

回答

11

經過一番研究,重複到OpenSSL documentation和探索Origami solution,我建立了下面的代碼,並設法將本地生成的簽名/證書插入到pdf文檔中。現在我只需要弄清楚如何將這個與外部生成的證書一起使用(查看下面的版本2,我在哪裏解決了它)。我已經打開了一個新的question,您可以在這裏找到關於我在OpenSSL和DER encoded證書上遇到的困難的一些詳細信息。

制定第2版,我也花了一些時間琢磨如何添加註釋 - 這樣的簽名在Adobe Reader變得可見 - 而無需添加新的頁面到文檔中。從origami documentation,我找到了get_page方法,這解決了我最後一個問題。我正在使用Adobe Reader X進行記錄。

希望對您有所幫助,我會;-)。

VERSION 1 - 生成證書和密鑰文件,並將它們直接插入到文檔中

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 => "[email protected]", 
    :reason => "Proof of Concept" 
) 

# Save the resulting file 
pdf.save(OUTPUTFILE) 

VERSION 2 - 使用現有證書籤署一份PDF文檔

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 => "[email protected]", 
    :reason => "Proof of Concept" 
) 

# Save the resulting file 
pdf.save(OUTPUTFILE) 
+0

我有類似的要求,但我正在使用Java。我認爲jSignPDF或jPDFSecure應該這樣做。我想知道您使用哪個庫將數字簽名/證書添加到PDF? – tarekahf

+0

@MrWater這給了我'method_missing':對於Origami :: Page(NoMethodError)沒有方法'add_annot'。你有什麼暗示可能是錯誤的原因? – ManuKaracho

+1

@tarekahf只有現在我看到了這一點。如果我記得(這是在2012年),我正在使用Jsignpdf應用程序,而不是lib,所以不能直接回答你。也許你應該嘗試檢查如何使用命令行中的'java -jar JSignPdf.jar --help',如http://jsignpdf.sourceforge.net/中所述,也許有人從你的應用程序調用命令行? – MrWater

-2

如果你對薪酬的一個項目工作,你可能要考慮jPDFSecure,爲開發者數字簽名PDF文檔和PDF文檔更改安全設置建一個商業的Java庫。使用jPDFSecure,您的應用程序或Java小程序可以加密PDF文檔,設置權限和密碼,以及創建和應用數字簽名。 jPDFSecure針對性能進行了優化,並建立在Qoppa專有PDF技術之上,因此不需要任何第三方軟件或驅動程序。

jPDFSecure具有一個簡單的接口,以從文件加載,網絡驅動器,網址和甚至輸入流,其可以被生成的運行或直接從一個數據庫來的PDF文檔。更改安全設置後,jPDFSecure可以在Java EE應用程序服務器中運行時將文檔保存到文件,java.io.OutputStream或javax.servlet.ServletOutputStream,以直接將文件輸出到瀏覽器。

jPDFSecure是獨立於平臺,並且可以在任何支持Java,包括Windows,Mac OSX和Linux的任何環境中使用。

+1

如何將這與紅寶石?爲什麼jPDFSecure會比jSignpdf更好? – MrWater