Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Задача: В 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)
| Причина: Не указана
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Удалось разобраться. Выкладываю ответ, может пригодится кому-то ещё.
Модифицировал 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"';
И они корректно подхватываются.
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Теперь пытаюсь разобраться с передаваемым сертификатом, чтобы подписывание шло в автоматическом режиме без дополнительных диалоговых окон. Использую тестовый сертификат КриптоПро с алгоритмом подписи ГОСТ Р 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
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,322 Сказал «Спасибо»: 549 раз Поблагодарили: 2208 раз в 1723 постах
|
Автор: 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, т.е. сам сертификат, а не его ОК, отпечаток..? |
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Автор: Андрей * а разве в .js не написано... что там сертификат в hex, т.е. сам сертификат, а не его ОК, отпечаток..?
Благодарю за идею. Попробовал указать путь к файлу - результат не изменился. А так действовал по руководству, где сказано следующее: certificateHEX String Обязательный параметр. Массив байт сертификата, используемого для создания ЭП, в виде строки шестнадцатеричных цифр. Сертификат должен быть установлен в хранилище «Личные» текущего пользователя и иметь ссылку на закрытый ключ.
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,322 Сказал «Спасибо»: 549 раз Поблагодарили: 2208 раз в 1723 постах
|
Автор: Shuraken Автор: Андрей * а разве в .js не написано... что там сертификат в hex, т.е. сам сертификат, а не его ОК, отпечаток..?
Благодарю за идею. Попробовал указать путь к файлу - результат не изменился. А так действовал по руководству, где сказано следующее: certificateHEX String Обязательный параметр. Массив байт сертификата, используемого для создания ЭП, в виде строки шестнадцатеричных цифр. Сертификат должен быть установлен в хранилище «Личные» текущего пользователя и иметь ссылку на закрытый ключ. Путь? Нужно сертификат... массив байт в HEX. |
|
1 пользователь поблагодарил Андрей * за этот пост.
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Автор: Андрей * Путь? Нужно сертификат... массив байт в HEX.
Благодарю, разобрался. Необходимо выгрузить PCCERT_CONTEXT.pbCertEncoded. Ещё один момент. Откуда брать URL службы штампов времени? Можно пример? Отредактировано пользователем 14 августа 2020 г. 17:31:28(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,322 Сказал «Спасибо»: 549 раз Поблагодарили: 2208 раз в 1723 постах
|
|
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Каждый параметр даётся с боем :-) Указываю в вызове функции 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 в отладчике, чтобы увидеть, какие параметры подхватываются, а какие нет. Или объясните, как подхватить заданное оформление.
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 30.05.2018(UTC) Сообщений: 38 Сказал(а) «Спасибо»: 7 раз Поблагодарили: 2 раз в 2 постах
|
Разобрался со штампом времени. Для проставления необходимо в 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
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close