Подпишите PDF с помощью обычного JavaScript

Поскольку WebCrypto API развивается и поддерживается Chrome и Firefox, я хотел бы использовать его для цифровой подписи PDF-документа. Вокруг не так много литературы, но я нашел несколько примеров [1] и библиотеку PKI.js [2]. В примерах описан процесс подписания, но в конце возвращается подпись. Я ожидал, что мой PDF-файл Base64 снова вернется в виде подписанной строки Base64, но, к сожалению, этого не происходит. PKI.js, насколько мне известно, не позволяет подписать мой PDF-файл в формате Base64.

Есть ли способ подписать PDF только с помощью JavaScript и WebCrypto API? Закрытый ключ можно ввести в <textarea> или, что еще лучше, сохранить в настройках сертификата браузера.

Base64 PDF (из REST API) Подписать с помощью JS и сертификата Подписанный Base64 PDF (отправить в REST)


person ssc-hrep3    schedule 19.10.2015    source источник


Ответы (4)


Это технически возможно, на самом деле это один из сценариев, которые мы имели в виду, когда создавали PKIjs (вот почему существует этот образец) - https://pkijs.org/examples/PDFexample.html

При этом для подписания требуется работа с самой структурой PDF, которая требует либо специального парсера, либо модификаций существующего (например, pdfjs).

Короче говоря, подписание PDF-файла в браузере потребует много работы, но мы над этим работаем.

person rmhrisk    schedule 20.10.2015
comment
Я хочу подписать обычный текст, возможно ли это с помощью этой библиотеки? Я не нашел примера, который мог бы прочитать закрытый ключ p12 cert + и создать подпись. - person Michael Chourdakis; 03.07.2016
comment
С ним можно подписать что угодно. В этом примере подписываются произвольные файлы - pkijs.org/examples/CMSSigned_complex_example.html в этом примере показан импорт PKCS # 12s - pkijs.org/examples/PKCS12SimpleExample.html см. unmitigatedrisk.com/?p=543, чтобы узнать о некоторых ограничениях и примечаниях по реализации. - person rmhrisk; 04.07.2016

Существует PDFSign.js, библиотека, которая может подписывать PDF-файл в браузере. . Он использует forge для подписи. Если PKI.js поддерживает отдельные подписи pkcs7, то заменить forge будет несложно.

person user3481465    schedule 25.12.2015

Раскрытие информации: я работаю в CISPL.

На данный момент WebCrypto API не предоставляет доступ к (Windows) или каким-либо другим хранилищам ключей или локальному крипто-устройству USB / Smartcard.

Также в большинстве сценариев подписи, для требования защиты файла PDF в пределах границ сервера, не рекомендуется отправлять полный файл PDF в браузер или на сервер API подписи.

Таким образом, хорошая практика - создать хэш PDF для подписи, отправить хеш в браузер и использовать javascript через расширение браузера для доступа к некоторому приложению, работающему в локальной системе, для доступа к локальному хранилищу ключей (или USB / смарт-карте) и создания подписи и отправки обратно ( PKCS7 или контейнер CMS в случае подписи PDF) на сервер, где подпись может быть вставлена ​​обратно в PDF, из которого был создан хэш для подписи и отправлен в браузер или на сервер API подписи.

Для сценариев подписи на основе браузера моя компания предоставляет одно такое бесплатное расширение браузера Signer.Digital и библиотеку .NET, необходимую на сервере. Локальную систему (хост, работающий за браузером Chrome в Windows) можно загрузить по адресу сайт загрузки cNET При установке этого хоста и перезапуске Chrome автоматически добавляется Signer.Digital Chrome Extension и / или Signer.Digital Расширение Firefox

Фактическая работа этого расширения проиллюстрирована здесь вместе с полным просмотром кода и ссылкой для загрузки на рабочий пример исходного кода проекта VS 2015.

Javascript для вызова метода из расширения:

 //Calculate Sign for the Hash by Calling function from Extension SignerDigital
 SignerDigital.signPdfHash(hash, $("#CertThumbPrint").val(), "SHA-256")      //or "SHA256"
  .then(
         function (signDataResp) {
           //Send signDataResp to Server
     },
         function (errmsg) {
             //Send errmsg to server or display the result in browser.
           }
  );

В случае успеха возвращает подпись pkcs7 в кодировке Base64 - используйте подходящую библиотеку или библиотеку, предоставленную Signer.Digital для вставки подписи в pdf

В случае неудачи возвращает сообщение об ошибке, начиная с ошибки SDHost:

Цифровая подпись из браузера

Цифровая подпись из браузера

  1. Сервер отправляет хеш данных / документа / контента для подписи в браузер.
  2. Браузер использует Signer.Digital Browser Extension Javascript API для вызова действия от Signer.Digital Browser Extension Host.
  3. В Windows хост расширения браузера использует хранилище сертификатов Microsoft и базовый CSP для подписания хэша.
  4. В Linux хост расширения браузера использует библиотеку PKCS # 11 .SO Crypto Device для подписания хэша.
  5. Необработанная подпись (подпись хэша) или контейнер подписи возвращаются в браузер подписавшим. Хост расширения цифрового браузера.
  6. В случае крипто-устройства, а именно. USB-токен или смарт-карта, закрытый ключ пользователя никогда не выходит из устройства, но хэш для подписи отправляется на устройство для его подписи.
  7. Веб-приложение (Javascript в браузере) отправляет подпись обратно на сервер, и ее можно изменить в PDF-документе, XML или Json или по мере необходимости.
person Bharat Vasant    schedule 14.04.2019
comment
его хорошая практика ... - ну, какая хорошая практика, зависит от того, какому приложению вы доверяете больше. Ваш ответ предполагает, что серверное приложение заслуживает доверия, что ему можно доверять предоставление хеш-кода для PDF-файла, который пользователь хочет подписать. Это предположение может быть неверным для пользователя, впервые работающего с каким-либо серверным приложением, у которого на своем компьютере есть приложение для подписи, которому он доверяет. - person mkl; 23.04.2019
comment
@mki, я говорю о pdf, который создается на сервере. Если у пользователя есть PDF-файл на своем компьютере, то есть множество доступных инструментов, включая наиболее часто используемый Acrobat Reader для подписи PDF-документа ... Но вопрос заключается в подписи с использованием JavaScript, что означает, что документ находится на сервере, а подпись - в браузере. - person Bharat Vasant; 23.04.2019
comment
Я говорю о pdf, создаваемом на сервере. - даже тогда, если я не верю, что этот сервер отправит мне правильный хеш, я (как пользователь) хочу иметь возможность вместо этого применить подпись, загрузив PDF-файл, подписав его локально с помощью доверенного программного обеспечения, а затем снова загрузив подписанный PDF-файл. Однако я должен признать, что произвольные расширения браузера на самом деле не считаются здесь надежным программным обеспечением, поэтому здесь действительно не имеет значения, передает ли вариант использования мне только хеш или весь документ ... - person mkl; 23.04.2019
comment
Некоторыми примерами являются подписание счета-фактуры или заказа на поставку, только что подготовленного мной в веб-приложении моей компании (например, CRM или веб-программное обеспечение для бухгалтерского учета), и я хочу, наконец, поставить подпись. Другой пример - eReturn, который я только что предварительно просмотрел в веб-приложении компании или веб-интерфейсе поставщиков услуг eReturn, тогда я не предпочитаю просматривать XML или Json возврата перед подписанием .. Просто пытаюсь помочь доверенным делам ... вы хотите, чтобы я заменить хорошую практику общепринятой ?! :) - person Bharat Vasant; 24.04.2019
comment
Не нужно ничего менять. Если у пользователя есть основания доверять рассматриваемому серверу (например, при наличии соответствующей сертификации CC), это решение имеет свое очарование. - person mkl; 24.04.2019
comment
Привет, @BharatVasant, можете ли вы предоставить это и для ядра .net? - person صفي; 06.11.2020
comment
Да, у нас есть основная библиотека .Net и готовое приложение. - person Bharat Vasant; 06.11.2020

Вы можете подписать любой файл (в том числе pdf) с помощью openpgp.js

https://openpgpjs.org/openpgpjs/doc/#create-and-verify-detached-signatures

(прокрутите вниз до 'create-and-verify-detached-signatures')

Прочтите файл как Uint8Array и подпишите его своим закрытым ключом.

person user2677034    schedule 31.12.2019
comment
Всякий раз, когда люди хотят подписать и подчеркнуть тот факт, что они хотят подписывать PDF-файлы, они часто имеют в виду, что они хотят подписывать с использованием встроенных подписей PDF, а не использовать отдельные, отдельные файлы подписей. Это подразумевает, что для совместимых подписей форматы PKCS # 1 / PKCS # 7 основаны на сертификатах X.509, а не на форматах PGP. - person mkl; 31.12.2019