Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Наши способы организации безопасного удалённого доступа к рабочим местам и корпоративным ресурсам
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Shuraken  
#1 Оставлено : 12 августа 2020 г. 17:52:47(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Задача: В Delphi подписать PDF видимой ЭЦП. Почитав мануалы, темы, написал следующее:

Код:

uses OleServer, Acrobat_TLB, OleCtrls, ComObj, QStrings;

type
  PAppearance = ^TAppearance;
  TAppearance = record
    pageNumber: Integer;
    coords: array[0..3] of integer;
    appearanceFilter: string;
  end;

function BytesToHex(Value: PAnsiChar; Count: Integer): string;
var
  i: Integer;
begin
  Result := '';
  for i := 0 to Count - 1 do
  begin
    Result := Result + IntToHex(Byte(Value[i]), 2);
  end;
end;

function GetCertificate(Cert: PCCERT_CONTEXT): string;
var
  certValue: string;
begin
  SetLength(certValue, Cert.pCertInfo.SubjectPublicKeyInfo.PublicKey.cbData);
  system.Move(Cert.pCertInfo.SubjectPublicKeyInfo.PublicKey.pbData^, Pointer(certValue)^, Cert.pCertInfo.SubjectPublicKeyInfo.PublicKey.cbData);
  Result := BytesToHex(PAnsiChar(certValue), Cert.pCertInfo.SubjectPublicKeyInfo.PublicKey.cbData);
end;

procedure SignPDF;
var
  gApp: CAcroApp;
  PDDoc: CAcroPDDoc;
  AVDoc: CAcroAVDoc;
  jso: Variant;
  Appearance: PAppearance;
begin
  gApp := CoAcroApp.Create;
  gApp.Show;
  AVDoc := CoAcroAVDoc.Create;
  if AVDoc.Open('c:\1.pdf', 'c:\1.pdf') then
  begin
    PDDoc := AVDoc.GetPDDoc as CAcroPDDoc;
    jso := PDDoc.GetJSObject;
    GetMem(Appearance, SizeOf(TAppearance));
    Appearance^.pageNumber := PDDoc.GetNumPages - 1;
    Appearance^.coords[0] := 122;
    Appearance^.coords[1] := 539;
    Appearance^.coords[2] := 422;
    Appearance^.coords[3] := 122;
    Appearance^.appearanceFilter := 'Shuraken';
    jso.CPSign(GetCertificate(FMyCertificate), '', 1, 'Причина: Хотелка',
               'Местоположение: Санкт-Петербург', '', false, true, integer(Appearance));
  end;
end;

Если ставлю предпоследний параметр в false, то подпись не создаётся. Параметр bShowSignDialogs: Флаг, указывающий будут ли отображены диалог с параметрами подписи и диалог для сохранения файла. Ставлю в true, выводится окно, где выбираю сертификат и подпись - невидимая - создаётся.

Вопросы:
1. Первым параметром передал открытый ключ. Почему он не подхватывается и его приходится выбирать в окне диалога?
2. Как из Delphi проинициализировать и передать последний параметр: appearance? Пробовал как record - ругается. Пропускает лишь integer, поэтому пришлось изгаляться.
3. По какой причине не удаётся создать видимую подпись?

Отредактировано пользователем 12 августа 2020 г. 17:54:21(UTC)  | Причина: Не указана

Offline Shuraken  
#2 Оставлено : 14 августа 2020 г. 12:00:44(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Удалось разобраться. Выкладываю ответ, может пригодится кому-то ещё.

Модифицировал CPPDFDSig.js следующим образом.

перед строкой
CPSign = app.trustedFunction(function(certificateHEX, pin, pdfLockMode, signReason, signLocation, signContactInfo, timeStamp, bShowCertificatesDialog, bShowSignDialogs, appearance, cadesType) {

Добавил 2 переменные
var myCoords = {left: 539, bottom: 122, right: 422, top: 439};
var myAppearance = {pageNumber: 0, coords: [myCoords.left, myCoords.bottom, myCoords.right, myCoords.top], appearanceFilter: "fancy" };

Изменил строку
if (typeof (appearance) === 'undefined') appearance = null;
на
if (typeof (appearance) === 'undefined') appearance = myAppearance;

Прямо в функцию не вставлял, поскольку почему-то не подхватывались координаты из Delphi.

Изменил строку
var appearanceCoords = [0, 0, 0, 0];
на
var appearanceCoords = [myCoords.left, myCoords.bottom, myCoords.right, myCoords.top];

закомментировал строку
if (typeof (appearance.coords) !== 'undefined') appearanceCoords = appearance.coords;

В Delphi, перед вызовом CPSign инициализирую переменные.

jso := PDDoc.GetJSObject;
jso.myCoords.left := 10;
jso.myCoords.bottom := 12;
jso.myCoords.right := 422;
jso.myCoords.top := 239;
jso.MyAppearance.PageNumber := PDDoc.GetNumPages - 1;
jso.MyAppearance.appearanceFilter := '"MyFilter"';

И они корректно подхватываются.
Offline Shuraken  
#3 Оставлено : 14 августа 2020 г. 15:50:54(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Теперь пытаюсь разобраться с передаваемым сертификатом, чтобы подписывание шло в автоматическом режиме без дополнительных диалоговых окон. Использую тестовый сертификат КриптоПро с алгоритмом подписи ГОСТ Р 34.11-2012/34.10-2012 256 бит. Передаю открытый ключ '044030df6b9.....'. На закладке "Подписи" выводится "Неподписанные поля подписи\CPPDFDSig signature на странице 2", и чтобы подписать, требуется щёлкнуть мышкой по полю подписи и выбрать сертификат с этим открытым ключом. После этого подписывает.
Передаю этот же открытый ключ в другом виде - '04 40 30 df 6b 9....', передаю отпечаток сертификата, серийный номер, пустую строку в CPSign - результат один и тот же: ничего не ломается и не подписывается Подписывается только при вызове диалога подписи.
Как это исправить?

КриптоПро CSP 4.0.9944,
КриптоПро PDF 2.0.1180
Windows 8.1
Offline Андрей *  
#4 Оставлено : 14 августа 2020 г. 15:56:16(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Автор: Shuraken Перейти к цитате
Теперь пытаюсь разобраться с передаваемым сертификатом, чтобы подписывание шло в автоматическом режиме без дополнительных диалоговых окон. Использую тестовый сертификат КриптоПро с алгоритмом подписи ГОСТ Р 34.11-2012/34.10-2012 256 бит. Передаю открытый ключ '044030df6b9.....'. На закладке "Подписи" выводится "Неподписанные поля подписи\CPPDFDSig signature на странице 2", и чтобы подписать, требуется щёлкнуть мышкой по полю подписи и выбрать сертификат с этим открытым ключом. После этого подписывает.
Передаю этот же открытый ключ в другом виде - '04 40 30 df 6b 9....', передаю отпечаток сертификата, серийный номер, пустую строку в CPSign - результат один и тот же: ничего не ломается и не подписывается Подписывается только при вызове диалога подписи.
Как это исправить?

КриптоПро CSP 4.0.9944,
КриптоПро PDF 2.0.1180
Windows 8.1


а разве в .js не написано... что там сертификат в hex, т.е. сам сертификат, а не его ОК, отпечаток..?
Техническую поддержку оказываем тут
Наша база знаний
Offline Shuraken  
#5 Оставлено : 14 августа 2020 г. 16:04:10(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Автор: Андрей * Перейти к цитате

а разве в .js не написано... что там сертификат в hex, т.е. сам сертификат, а не его ОК, отпечаток..?

Благодарю за идею. Попробовал указать путь к файлу - результат не изменился. А так действовал по руководству, где сказано следующее: certificateHEX String Обязательный параметр. Массив байт сертификата, используемого для создания ЭП, в виде строки шестнадцатеричных цифр. Сертификат должен быть установлен в хранилище «Личные» текущего пользователя и иметь ссылку на закрытый ключ.

Offline Андрей *  
#6 Оставлено : 14 августа 2020 г. 16:10:56(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Автор: Shuraken Перейти к цитате
Автор: Андрей * Перейти к цитате

а разве в .js не написано... что там сертификат в hex, т.е. сам сертификат, а не его ОК, отпечаток..?

Благодарю за идею. Попробовал указать путь к файлу - результат не изменился. А так действовал по руководству, где сказано следующее: certificateHEX String Обязательный параметр. Массив байт сертификата, используемого для создания ЭП, в виде строки шестнадцатеричных цифр. Сертификат должен быть установлен в хранилище «Личные» текущего пользователя и иметь ссылку на закрытый ключ.



Путь? Нужно сертификат... массив байт в HEX.

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
Shuraken оставлено 14.08.2020(UTC)
Offline Shuraken  
#7 Оставлено : 14 августа 2020 г. 17:00:11(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Автор: Андрей * Перейти к цитате

Путь? Нужно сертификат... массив байт в HEX.


Благодарю, разобрался. Необходимо выгрузить PCCERT_CONTEXT.pbCertEncoded.

Ещё один момент. Откуда брать URL службы штампов времени? Можно пример?

Отредактировано пользователем 14 августа 2020 г. 17:31:28(UTC)  | Причина: Не указана

Offline Андрей *  
#8 Оставлено : 14 августа 2020 г. 19:01:05(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 9,582
Мужчина
Российская Федерация

Сказал «Спасибо»: 345 раз
Поблагодарили: 1379 раз в 1065 постах
Техническую поддержку оказываем тут
Наша база знаний
Offline Shuraken  
#9 Оставлено : 17 августа 2020 г. 11:13:02(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Каждый параметр даётся с боем :-)
Указываю в вызове функции CPSign timestamp = 'http://testca.cryptopro.ru/tsp/tsp.srf' или 'http://ocsp.ntssoft.ru/tsp/tsp.srf' - штамп времени не ставится.
Запускаю CPSign с параметрами bShowCertificatesDialog=true, bShowSignDialogs=true. В окне выбора сертификата включена галочка "Добавить штамп времени на подпись", но не указана служба tsp. Перед этим установил КриптоПро ЭЦП Browser plug-in 2.0, КриптоПро ЭЦП SDK 2.0

Также столкнулся с проблемой appearanceFilter. В оформлении цифровых подписей создал два шаблона: "t_est", "test". В CPPDFDSig перед вызовом функции CPSign объявил три переменные.

var myCoords = {left: 539, bottom: 122, right: 422, top: 439};
var filter = {Name: "test" };
var myappearance = {pageNumber: 0, coords: [myCoords.left, myCoords.bottom, myCoords.right, myCoords.top], appearanceFilter: filter.Name };

код signatureField.signatureSetSeedValue({ appearanceFilter: appearance.appearanceFilter });
заменил на signatureField.signatureSetSeedValue({ appearanceFilter: filter.Name });

код if (typeof (appearance.coords) !== 'undefined') appearanceCoords = appearance.coords;
заменил на if (typeof (appearance.coords) !== 'undefined') appearanceCoords = [myCoords.bottom, myCoords.left, myCoords.right, myCoords.top]; //appearance.coords

Если вызываю CPSign с параметрами bShowCertificatesDialog=false, bShowSignDialogs=false, то создаётся видимая подпись со стандартным, а не заданным оформлением.
bShowSignDialogs=true - видимая подпись, но подхватывается первое оформление из списка, а не заданное.

Непонятно следующее. В коде Delphi пишу
jso := PDDoc.GetJSObject;
jso.myappearance.pageNumber := PDDoc.GetNumPages - 1; - номер подхватывается без вопросов и печать ставится на последней странице.

Задаю myCoords в Delphi, и в коде координаты подхватываются без проблем.

Но оформление не подхватывается ни из кода Delphi, ни из кода CPPDFDSig. Скажите пожалуйста, как выполнить код CPSign в отладчике, чтобы увидеть, какие параметры подхватываются, а какие нет. Или объясните, как подхватить заданное оформление.
Offline Shuraken  
#10 Оставлено : 18 августа 2020 г. 19:42:58(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Разобрался со штампом времени. Для проставления необходимо в CPSign передать cadestype = 5 или cadestype = 93.
Также разобрался с шаблоном оформления подписи. Если вызвать CPSign с параметром bShowSignDialogs=true, то в диалоговом окне будет выбор шаблона. bShowSignDialogs=false, и за параметры оформления отвечает переменная var signatureParameters = { reason: signReason, location: signLocation, contactInfo: signContactInfo, oCustomAppearance: customAppearance };
Если изменить эту переменную на
var signatureParameters = { reason: signReason, location: signLocation, contactInfo: signContactInfo, appearance: "fancy"};
то подставится шаблон оформления под названием fancy и можно установить bShowSignDialogs=false
Offline TatyanaMal  
#11 Оставлено : 21 августа 2020 г. 11:43:58(UTC)
TatyanaMal

Статус: Сотрудник

Группы: Администраторы, Участники
Зарегистрирован: 08.11.2013(UTC)
Сообщений: 53
Российская Федерация

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 6 раз в 5 постах
Добрый день.
Добавьте отладочный вывод в скрипт, чтобы убедиться что происходит корректная инициализация в этом месте:
signatureField.signatureSetSeedValue({ appearanceFilter: appearance.appearanceFilter })

Отладочный вывод будет отображаться в консоли Acrobat (подробнее можно посмотеть в документации https://www.cryptopro.ru...180/cryptopropdf_ecp.pdf раздел 2.1.3)
Там же описано про отладку, но отладчик в Acrobat не очень хорошо работает.
thanks 1 пользователь поблагодарил TatyanaMal за этот пост.
Shuraken оставлено 21.08.2020(UTC)
Offline Shuraken  
#12 Оставлено : 21 августа 2020 г. 11:53:35(UTC)
Shuraken

Статус: Участник

Группы: Участники
Зарегистрирован: 30.05.2018(UTC)
Сообщений: 27
Российская Федерация

Сказал(а) «Спасибо»: 4 раз
Автор: TatyanaMal Перейти к цитате
Добрый день.
Добавьте отладочный вывод в скрипт, чтобы убедиться что происходит корректная инициализация в этом месте:
signatureField.signatureSetSeedValue({ appearanceFilter: appearance.appearanceFilter })

Отладочный вывод будет отображаться в консоли Acrobat (подробнее можно посмотреть в документации https://www.cryptopro.ru...180/cryptopropdf_ecp.pdf раздел 2.1.3)
Там же описано про отладку, но отладчик в Acrobat не очень хорошо работает.


Благодарю, я сделал немного по-другому - через signatureParameters. Проверяю свою переменную и в зависимости от значения объявляю переменную так
signatureParameters = { reason: signReason, location: signLocation, contactInfo: signContactInfo, appearance: "fancy"};
или так
signatureParameters = { reason: signReason, location: signLocation, contactInfo: signContactInfo, oCustomAppearance: customAppearance };
Это работает, как надо.
Offline ВикторияV  
#13 Оставлено : 31 августа 2020 г. 16:55:09(UTC)
ВикторияV

Статус: Новичок

Группы: Участники
Зарегистрирован: 31.08.2020(UTC)
Сообщений: 1
Российская Федерация
Откуда: СПб

да уж ну и запариться пришлось ) полезные выводы некоторые спасибо советую интересный сериал Пацаны от Амазон

Отредактировано пользователем 2 сентября 2020 г. 14:09:30(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.