2012-08-22 34 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