Вставить цифровую подпись в существующий файл pdf

Мне нужно вставить цифровую подпись в уже существующие файлы pdf, используя сервер приложений rails. (Обычно клиенты загружают файлы pdf, и сервер подписывает их локальным сертификатом)

Я использовал JSignpdf для вставки цифровых подписей в файлы pdf и начал искать драгоценные камни для рубина ...

Я нашел еще один переносимый файл для этой работы на сайте rubypdf http://soft.rubypdf.com/software/pdf-digital-signe, но не может найти ни одного драгоценного камня или даже примера кода для этого в ruby.

Я также просмотрел проверку цифровой подписи с помощью OpenSSL, но не мог понять, как чтобы фактически подписать уже существующий документ с помощью локального файла сертификата.

Я также обратил внимание на http://code.google.com/p/origami-pdf/, но это кажется немного резким для якобы «простой» (по крайней мере, концептуально) задачи.

Есть идеи / предложения?

Спасибо


person MrWater    schedule 22.08.2012    source источник
comment
Задача только предположительно проста, но имеет множество недостатков и сложностей на всех уровнях. Это одна из причин, по которой вы ничего не можете найти - я сомневаюсь, что кто-то потратит значительные усилия на разработку средства подписи PDF промышленного качества для Ruby. Я бы предложил пару хороших компонентов для .NET / Mono, если вы можете каким-то образом вызывать внешние классы.   -  person Eugene Mayevski 'Callback    schedule 22.08.2012
comment
Привет, @ EugeneMayevski'EldoSCorp, я полагаю, что SOGETI сделал это с помощью Origami, и теперь я поместил его сюда, после небольшого исследования царств Origami и OpenSSL. Наслаждаться.   -  person MrWater    schedule 29.08.2012
comment
@MrWater: не могли бы вы предоставить образец кода, показывающий, как вы можете использовать jSignPDF для добавления цифровых подписей в ваш PDF-файл с помощью Java?   -  person tarekahf    schedule 29.09.2016


Ответы (2)


После некоторого исследования, возвращаясь к документации OpenSSL и изучив решение Origami, я создал приведенный ниже код и смог вставить локально сгенерированная подпись / сертификат в PDF-документ. Теперь мне просто нужно выяснить, как использовать это с внешним сгенерированным сертификатом (проверьте версию 2 ниже, где я решил это). Я открыл новый вопрос, в котором вы можете найти некоторые подробности о моей трудности с OpenSSL. и сертификаты в кодировке DER.

При разработке версии 2 я также потратил некоторое время на размышления, как добавить аннотацию, чтобы подпись стала видимой в Adobe Reader, без добавления новой страницы в документ. В документации по оригами я нашел метод get_page, который решил мою последнюю проблему по этому поводу. Для протокола, я использую Adobe 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 => "[email protected]", 
  :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 => "[email protected]", 
  :reason => "Proof of Concept"
)

# Save the resulting file
pdf.save(OUTPUTFILE)
person MrWater    schedule 29.08.2012
comment
У меня похожие требования, но я использую Java. Я думаю, что jSignPDF или jPDFSecure должны подойти. Я хотел бы знать, какую библиотеку вы использовали для добавления цифровой подписи / сертификата в PDF? - person tarekahf; 29.09.2016
comment
@MrWater это дает мне method_missing': No method add_annot 'для Origami :: Page (NoMethodError). есть подсказка, в чем может быть причина ошибки? - person ManuKaracho; 29.04.2017
comment
@tarekahf только сейчас увидел это. Если я помню (это было в 2012 году), я использовал приложение Jsignpdf, а не lib, поэтому не могу ответить вам напрямую. Возможно, вам стоит попробовать и проверить, как использовать командную строку с 'java -jar JSignPdf.jar --help', как указано в jsignpdf.sourceforge.net и, может быть, как-нибудь вызвать командную строку из вашего приложения? - person MrWater; 10.05.2017
comment
@ManuKaracho не совсем, и я не изучал этот код уже несколько лет, поэтому не могу вспомнить, с какими ошибками я наткнулся в то время. Вы пробовали отлаживать печать на экран? (logger.debug) - person MrWater; 10.05.2017
comment
@ManuKaracho Измените page.add_annot (sigannot) на page.add_annotation (sigannot), чтобы исправить ошибку No method `add_annot '. - person Jacek Jońca-Jasiński; 28.12.2019
comment
Привет, @MrWater, как ты получил сертификат в версии 2? Из списка утвержденных списков доверия Adobe неясно, как лучше всего это сделать. - person VegaStudios; 08.06.2020

Если вы работаете над платным проектом, вы можете рассмотреть коммерческий Java-сервис jPDFSecure. библиотека, созданная для разработчиков для цифровой подписи PDF-документов и изменения настроек безопасности PDF-документов. С jPDFSecure ваше приложение или Java-апплет может шифровать PDF-документы, устанавливать разрешения и пароли, а также создавать и применять цифровые подписи. jPDFSecure оптимизирован для производительности и построен на основе проприетарной технологии PDF Qoppa, поэтому нет необходимости в каком-либо стороннем программном обеспечении или драйверах.

jPDFSecure имеет простой интерфейс для загрузки PDF-документов из файлов, сетевых дисков, URL-адресов и даже входных потоков, которые могут создаваться во время выполнения или поступать непосредственно из базы данных. После изменения настроек безопасности jPDFSecure может сохранить документ в файл, java.io.OutputStream или javax.servlet.ServletOutputStream при запуске на сервере приложений Java EE для вывода файла непосредственно в браузер.

jPDFSecure не зависит от платформы и может использоваться в любой среде, поддерживающей Java, включая Windows, Mac OSX и Linux.

person Susan Sims    schedule 23.08.2012
comment
И как мне интегрировать это с рубином? Почему jPDFSecure лучше, чем jSignpdf? - person MrWater; 23.08.2012
comment
Наверное рекламный бот - person Richard Howell-Peak; 03.02.2021