Статус: Активный участник
  Группы: Участники
 Зарегистрирован: 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,987   Сказал «Спасибо»: 605 раз Поблагодарили: 2350 раз в 1846 постах
  
	 
	
     | 
    
        
            
		      
                Автор: 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,987   Сказал «Спасибо»: 605 раз Поблагодарили: 2350 раз в 1846 постах
  
	 
	
     | 
    
        
            
		      
                Автор: 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,987   Сказал «Спасибо»: 605 раз Поблагодарили: 2350 раз в 1846 постах
  
	 
	
     | 
    
         | 
 | 
            
	 
        
    
    | 
         
             
     | 
    
         
            
         
     | 
    | 
        
	
     | 
        
        
        
    
        
            
            
    
        
	Статус: Активный участник
  Группы: Участники
 Зарегистрирован: 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