【问题标题】:Insert digital signature into existing pdf file将数字签名插入现有的 pdf 文件
【发布时间】:2012-08-22 17:02:47
【问题描述】:

我需要使用 Rails 应用程序服务器将数字签名插入到现有的 pdf 文件中。 (基本上,客户端上传pdf文件,服务器用本地证书签名)

我一直在使用 JSignpdf 将数字签名插入到 pdf 文件中,并开始为 ruby​​ 寻找 gems...

我在 ruby​​pdf 网站http://soft.rubypdf.com/software/pdf-digital-signe 上找到了另一个可移植文件来完成这项工作,但在 ruby​​ 中找不到任何 gem 甚至示例代码来完成这项工作。

我也查看了Digital signature verification with OpenSSL,但不明白如何使用本地证书文件实际签署现有文档。

我在 http://code.google.com/p/origami-pdf/ 也达到了顶峰,但这对于所谓的“简单”(至少在概念上)任务来说似乎有点苛刻。

有什么想法/建议吗?

谢谢

【问题讨论】:

  • 这项任务只是“假设”简单,但在各个层面都有许多警告和复杂性。这就是您找不到任何东西的原因之一——我怀疑有人会投入大量精力为 Ruby 开发工业级质量的 PDF 签名器。如果你能以某种方式调用外部类,我会推荐几个好的 .NET/Mono 组件。
  • 嘿@EugeneMayevski'EldoSCorp,我猜SOGETI 是用Origami 做的,现在我把它放在这里,在探索了Origami 和OpenSSL 的领域之后。享受吧。
  • @MrWater:您能否提供一些示例代码,展示如何使用 jSignPDF 通过 Java 向 PDF 添加数字签名?

标签: ruby pdf digital-signature


【解决方案1】:

经过一些研究,重复到OpenSSL documentation 并探索Origami solution,我构建了下面的代码,并设法将本地生成的签名/证书插入到 pdf 文档中。现在我只需要弄清楚如何将它与外部生成的证书一起使用(查看下面的版本 2,我在其中解决了它)。我打开了一个新的question,您可以在其中找到有关我在使用 OpenSSL 和DER encoded 证书时遇到的困难的一些详细信息。

为了开发第 2 版,我还花了一些时间想知道如何添加注释 - 以便签名在 Adob​​e 阅读器中可见 - 而不向文档添加新页面。从origami documentation,我找到了get_page 方法,它解决了我的最后一个问题。我正在使用 Adob​​e Reader X,作为记录。

希望你觉得这对我有用 ;-)。

版本 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 => "myemail@email.tt", 
  :reason => "Proof of Concept"
)

# Save the resulting file
pdf.save(OUTPUTFILE)

版本 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 => "myemail@email.tt", 
  :reason => "Proof of Concept"
)

# Save the resulting file
pdf.save(OUTPUTFILE)

【讨论】:

  • 我有类似的要求,但我使用的是 Java。我认为 jSignPDF 或 jPDFSecure 应该这样做。我想知道您使用哪个库向 PDF 添加数字签名/证书?
  • @MrWater 这给了我method_missing': No method add_annot' 用于 Origami::Page (NoMethodError)。你有提示错误的原因是什么?
  • @tarekahf 现在我才看到这个。如果我记得(这是在 2012 年)我使用的是 Jsignpdf 应用程序,而不是 lib,所以无法直接回答您。也许您应该尝试检查如何使用带有“java -jar JSignPdf.jar --help”的命令行,如jsignpdf.sourceforge.net 中所述,并且可能以某种方式从您的应用程序中调用命令行?
  • @ManuKaracho 不是真的,而且我已经有几年没有研究过这段代码了,所以我真的不记得我当时偶然发现了什么错误。您是否尝试过打印到屏幕进行调试? (logger.debug)
  • @ManuKaracho 将 page.add_annot(sigannot) 更改为 page.add_annotation(sigannot) 应该可以修复 No method `add_annot' 错误。
【解决方案2】:

如果您正在从事付费项目,您可能需要考虑jPDFSecure,这是一个商业 Java 库,专为开发人员构建,用于对 PDF 文档进行数字签名并更改 PDF 文档的安全设置。使用 jPDFSecure,您的应用程序或 Java 小程序可以加密 PDF 文档、设置权限和密码,以及创建和应用数字签名。 jPDFSecure 针对性能进行了优化,并建立在 Qoppa 的专有 PDF 技术之上,因此不需要任何第三方软件或驱动程序。

jPDFSecure 有一个简单的界面,可以从文件、网络驱动器、URL 甚至输入流中加载 PDF 文档,这些文件可以在运行时生成或直接来自数据库。更改安全设置后,jPDFSecure 可以在 Java EE 应用服务器中运行时将文档保存到文件、java.io.OutputStream 或 javax.servlet.ServletOutputStream 以将文件直接输出到浏览器。

jPDFSecure 独立于平台,可用于任何支持 Java 的环境,包括 Windows、Mac OSX 和 Linux。

【讨论】:

  • 我如何将它与 ruby​​ 集成?为什么 jPDFSecure 会比 jSignpdf 更好?
  • 可能是一个广告机器人
猜你喜欢
  • 1970-01-01
  • 2011-04-28
  • 2019-04-03
  • 1970-01-01
  • 2019-06-14
  • 2013-05-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多