Después de algunas investigaciones, recurriendo al OpenSSL documentation y explorando el Origami solution, construí el siguiente código y logré insertar una firma/certificado generado localmente en un documento pdf. Ahora solo necesito descubrir cómo usar esto con un certificado generado externamente (verifique la versión 2 a continuación, donde lo resolví). Abrí un nuevo question donde puede encontrar algunos detalles sobre una dificultad que tuve con los certificados OpenSSL y DER encoded.
Para desarrollar la versión 2, también pasé un tiempo preguntándome cómo agregar una anotación, para que la firma se vuelva visible en el lector de Adobe, sin agregar una página nueva al documento. Desde origami documentation, encontré el método get_page, que resolvió mi último problema al respecto. Estoy usando Adobe Reader X, para el registro.
Espero que encuentres útil esto como lo haré ;-).
VERSIÓN 1 - Generar certificado y archivo de clave, e insertarlos directamente en el documento
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)
Versión 2 - Uso existente certificados para firmar un documento 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)
La tarea es solo "supuestamente" simple, pero tiene muchas salvedades y complejidades en todos los niveles. Esa es una de las razones por las que no se puede encontrar nada. Dudo que se invierta un esfuerzo significativo en el desarrollo de un firmante de PDF de calidad industrial para Ruby. Sugeriría un par de buenos componentes para .NET/Mono si puede llamar a clases externas de alguna manera. –
Hola @ EugeneMayevski'EldoSCorp, supongo que SOGETI lo hizo con Origami, y ahora lo he puesto aquí, después de explorar los reinos de Origami y OpenSSL por un tiempo. Disfrutar. – MrWater
@MrWater: ¿podría proporcionarnos algún código de muestra que muestre cómo puede usar jSignPDF para agregar firmas digitales a su PDF utilizando Java? – tarekahf