Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
Работа с CryptoAPI используя модуль JwaWinCrypt.
Имеются открытые ключи, из них надо получить информацию:
Срок действия
Кому выдан
Кем выдан
Улучшенный ключ

По первым 3-м пунктам все хорошо, а вот где найти информацию как достать значение "Улучшенный ключ", не могу.
Пример кода подкатом.
+
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, JwaWinCrypt, LazUTF8, JwaWinSta, JwaWinBase, JwaWinType;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }


procedure TForm1.Button1Click(Sender: TObject);
var f: file;
    encCert: PByte;
    encCertLen: DWORD;
    //store: HCERTSTORE;
    context: PCCERT_CONTEXT;
    //n: PPCCERT_CONTEXT;
    encType: DWORD;
    nameBLOB: CERT_NAME_BLOB;
    size: DWORD;
    nameString: PChar;
    s:TStrings;
    FT:JwaWinBase.TFileTime;
begin
   s:=TStringList.Create;
   s.Clear;
   AssignFile(f, 'c:\temp\123.crt');
   reset(f, 1);
   encCertLen := FileSize(f);
   GetMem(encCert, encCertLen);
   BlockRead(f, encCert^, encCertLen);
   CloseFile(f);

   encType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
   context := CertCreateCertificateContext(encType, encCert, encCertLen);

   if context = nil then
   begin
   MessageDlg('Error creating certificate context', mtError, [mbOK], 0);
   exit;
   end;

   nameString := StrAlloc(512);

   FT.dwLowDateTime:=context^.pCertInfo^.NotBefore.dwLowDateTime;
   FT.dwHighDateTime:=context^.pCertInfo^.NotBefore.dwHighDateTime;

   s.Add('context^.pCertInfo^.NotBefore: '+DateTimeToStr(FileTime2DateTime(FT)));

   s.Add('==========================');


   FT.dwLowDateTime:=context^.pCertInfo^.NotAfter.dwLowDateTime;
   FT.dwHighDateTime:=context^.pCertInfo^.NotAfter.dwHighDateTime;

   s.Add('context^.pCertInfo^.NotAfter: '+DateTimeToStr(FileTime2DateTime(FT)));

   s.Add('==========================');



   s.Add('context^.pCertInfo^.Subject');
   nameBLOB := context^.pCertInfo^.Subject;
   size := CertNameToStr(encType, @nameBlob, CERT_X500_NAME_STR,nameString, 512);
   if size > 1 then
         s.Add(UTF8Encode(nameString))
      else
         s.Add('Error');

   s.Add('==========================');

   s.Add('context^.pCertInfo^.Issuer');
   nameBLOB := context^.pCertInfo^.Issuer;
   size := CertNameToStr(encType, @nameBlob, CERT_X500_NAME_STR, nameString, 512);
   if size > 1 then
         s.Add(UTF8Encode(nameString))
      else
         s.Add('Error');

   s.Add('==========================');

   //context^.hCertStore;

   {nameBLOB := context^.pCertInfo^.rgExtension;
   size := CertNameToStr(encType, @nameBlob, CERT_SIMPLE_NAME_STR,nameString, 512);
   if size > 1 then
         s.Add(UTF8Encode(nameString))
      else
         s.Add('Error');}

   //ShowMessage(s.Text);
   Memo1.Lines.Text:=s.Text;
   FreeMem(encCert, encCertLen);
   FreeAndNil(s);
end;

end.


Кто может подсказать, в какую сторону копать.
11 июн 15, 12:33    [17759565]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
MrCat
Guest
Речь про это? (там key usage всё же, а не key)
11 июн 15, 13:41    [17760080]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
MrCat
Речь про это? (там key usage всё же, а не key)

Спасибо, это уже нашел тынц
Только не работает.
CertGetEnhancedKeyUsage(m_pCertContext, 0, nil, usageLength);
  usage := PCERT_ENHKEY_USAGE(AllocMem(usageLength));
  try
    if (CertGetEnhancedKeyUsage(m_pCertContext, 0, usage, usageLength)) then
    begin
      if (usage.cUsageIdentifier = 0) then
      begin
        StringGrid1.Cells[index, certNum] := '<All>';
      end else begin
        for I := 0 to usage.cUsageIdentifier - 1 do
        begin
          usageStr := usage.rgpszUsageIdentifier;
        end;
      end;
    end else begin
      //TODO: It might not exist.
    end;
  finally
    FreeMem(usage, usageLength);
  end;


Смущает это: usageStr := usage.rgpszUsageIdentifier;
Пробовал по этому примеру, не могу вернуть коды. Количество правильное. А вот дальше что попало.
11 июн 15, 13:53    [17760192]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
MrCat
Guest
Ну, что в цикле всё время одно значение берётся, это ладно, описка. Но по идее, во втором параметре структуры должен быть массив указателей на строки. Т.е. что-то типа PPChar, а Вы с ним как с PChar обращаетесь. Плюс я бы ещё насчёт кодировки озаботился. Когда шерстятся теги ASN.1, то кроме указателя возвращается и кодировка данных, а тут - указатель на строку и всё. Это всегда ANSI-строка? Хотя, логично - OID - это три точки и 4 числа, ему UNICODE не нужен.
11 июн 15, 14:28    [17760489]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
MrCat
Ну, что в цикле всё время одно значение берётся, это ладно, описка. Но по идее, во втором параметре структуры должен быть массив указателей на строки. Т.е. что-то типа PPChar, а Вы с ним как с PChar обращаетесь. Плюс я бы ещё насчёт кодировки озаботился. Когда шерстятся теги ASN.1, то кроме указателя возвращается и кодировка данных, а тут - указатель на строку и всё. Это всегда ANSI-строка? Хотя, логично - OID - это три точки и 4 числа, ему UNICODE не нужен.

   If (CertGetEnhancedKeyUsage(context, 0, nil, size)) THEN
   begin
     Usage:=PCERT_ENHKEY_USAGE(AllocMem(size));
   end;
   If (CertGetEnhancedKeyUsage(context, 0, Usage, size)) THEN
      s.Add(FloatToStr(Usage^.cUsageIdentifier));
      for n := 1 to Usage^.cUsageIdentifier do
        begin
          s.Add(UTF8Encode(Usage[n].rgpszUsageIdentifier));
        end;

Сам до такого дошел, но массив не полный, на ключе который проверяю Usage^.cUsageIdentifier=12, а на 5 ке цикл вываливается :(.
Про это можно по подробней? Просто там был кусок кода из того что я нашел в сети для примера, пытаюсь под себя прикрутить.
11 июн 15, 14:38    [17760560]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
Плюс я бы ещё насчёт кодировки озаботился. Когда шерстятся теги ASN.1, то кроме указателя возвращается и кодировка данных, а тут - указатель на строку и всё. Это всегда ANSI-строка?
Вот про это можно по подробней.
11 июн 15, 14:43    [17760606]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
MrCat
Guest
Я про CERT_RDN_ATTR.dwValueType, и сразу было понятно что делать с Value.
11 июн 15, 14:56    [17760715]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
MrCat
Guest
Я бы написал так. Не проверял, просто продемонстрировать идею. Насчёт кодировки, в которой возвращается OID - не в курсе, возможно, действительно надо ещё decode from UTF8
var 
  Count: Integer;
  pStrs: PPChar;
  pStr: PChar;
...
  if CertGetEnhancedKeyUsage(context, 0, Usage, size) then
  begin
     Count := Usage^.cUsageIdentifier;
     s.Add(IntToStr(Count));
 
     pStrs := Usage.rgpszUsageIdentifier;
     for n := 0 to Pred(Count) do
     begin
       pStr := pStrs^[n];
       s.Add(StrPas(pStr));
     end;
  end;
11 июн 15, 15:04    [17760782]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
Ghost Writer
Member

Откуда: Россия
Сообщений: 780
angel_zar,

я когда-то тут подсказывал http://www.cryptopro.ru/forum2/default.aspx?g=posts&m=15919#post15919
попробуйте
11 июн 15, 16:18    [17761296]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
Всем спасибо, получилось так.
If (CertGetEnhancedKeyUsage(context, 0, nil, size)) THEN
   begin
     Usage:=PCERT_ENHKEY_USAGE(AllocMem(size));
   end;
   If (CertGetEnhancedKeyUsage(context, 0, Usage, size)) THEN
      s.Add('Count:'+FloatToStr(Usage^.cUsageIdentifier));
      for n := 0 to Usage^.cUsageIdentifier-1 do
        begin
         UsageT:=(PCharArr(Usage^.rgpszUsageIdentifier)[n])[0];
         s.Add(String(UsageT));
        end;       

Сейчас тестируем, на разных ключах.
15 июн 15, 08:37    [17770577]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
sql2012
Member

Откуда: РФ
Сообщений: 661
angel_zar
Всем спасибо, получилось так.
If (CertGetEnhancedKeyUsage(context, 0, nil, size)) THEN
   begin
     Usage:=PCERT_ENHKEY_USAGE(AllocMem(size));
   end;
   If (CertGetEnhancedKeyUsage(context, 0, Usage, size)) THEN
      s.Add('Count:'+FloatToStr(Usage^.cUsageIdentifier));
      for n := 0 to Usage^.cUsageIdentifier-1 do
        begin
         UsageT:=(PCharArr(Usage^.rgpszUsageIdentifier)[n])[0];
         s.Add(String(UsageT));
        end;       

Сейчас тестируем, на разных ключах.


Тестируешь, потому что не уверен в правильности расстановки begin\end или в криптографических функциях?
16 июн 15, 06:23    [17774190]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
[quot sql2012]
angel_zar
Тестируешь, потому что не уверен в правильности расстановки begin\end или в криптографических функциях?

Что бы быть уверенным, что будет работать правильно, а так тут черновой вариант, просто разобраться, как это работает.
Весь код будет обернут в класс, с обработками ошибок.
16 июн 15, 14:15    [17776617]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
sql2012
Member

Откуда: РФ
Сообщений: 661
[quot angel_zar]
sql2012
пропущено...

Что бы быть уверенным, что будет работать правильно, а так тут черновой вариант, просто разобраться, как это работает.
Весь код будет обернут в класс, с обработками ошибок.


Когда CertGetEnhancedKeyUsage вернет false, будешь к Usage=nil обращаться и получишь AV...
16 июн 15, 16:37    [17777595]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
angel_zar
Member

Откуда: Барнаул
Сообщений: 895
sql2012
Когда CertGetEnhancedKeyUsage вернет false, будешь к Usage=nil обращаться и получишь AV...

Я это прекрасно вижу, это фактически копи-паст, с некоторыми изменениями.
17 июн 15, 06:28    [17779860]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Lazarus CryptoAPI пара вопросов.  [new]
SQL-Talker
Member

Откуда: Если есть на свете рай, это - ...
Сообщений: 322
angel_zar
Всем спасибо, получилось так.
If (CertGetEnhancedKeyUsage(context, 0, nil, size)) THEN
   begin
     Usage:=PCERT_ENHKEY_USAGE(AllocMem(size));
   end;
   If (CertGetEnhancedKeyUsage(context, 0, Usage, size)) THEN
      s.Add('Count:'+FloatToStr(Usage^.cUsageIdentifier));
      for n := 0 to Usage^.cUsageIdentifier-1 do
        begin
         UsageT:=(PCharArr(Usage^.rgpszUsageIdentifier)[n])[0];
         s.Add(String(UsageT));
        end;       

Сейчас тестируем, на разных ключах.


Привет, народ.

Мне нужно выяснить содержится ли в параметре "Улучшенный ключ" OID "Подписывание документа" - "1.3.6.1.4.1.311.10.3.12"
Насколько я понял, в процитированном коде, в
PCharArr(Usage^.rgpszUsageIdentifier)[n]
как раз и должен содержаться этот OID,
но у меня там получается строка типа
автор
#$2E31#$2E33#$2E36#$2E31#$2E34#$2E31'ㄳ'#$2E31'〱㌮'#$312E'2'#$2E31#$2E33#$2E36#$2E31#$2E35#$2E35#$2E37#$2E33'2'
- по-видимому символы из юникода
а
Usage^.rgpszUsageIdentifier
содержит
автор
'а9›'#2'ш9›'#2'1.3.6.1.4.1.311.10.3.12'

хотя там должно быть два OID-а

Подскажите, как мне правильно получить OID-ы там содержащиеся?
14 май 19, 19:15    [21884736]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
SQL-Talker
Member

Откуда: Если есть на свете рай, это - ...
Сообщений: 322
И да, использовал определения типа PCharArr (с форума КриптоПро):
type
  PCharArr = ^TCharArr;
  TCharArr = array[0..0] of PChar;
14 май 19, 19:18    [21884740]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
Ghost Writer
Member

Откуда: Россия
Сообщений: 780
SQL-Talker
И да, использовал определения типа PCharArr (с форума КриптоПро):
В какой среде пишите? тот код я писал под Delphi 7. В лазарусе всё также работает с маленькой поправкой:
PCharArr(pbEnhanced^.rgpszUsageIdentifier)^[I]
14 май 19, 22:09    [21884818]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
Ghost Writer
Member

Откуда: Россия
Сообщений: 780
В Delphi 10.2 (Токио вроде зовётся)
type
  PCharArr = ^TCharArr;
  TCharArr = array[0..0] of PAnsiChar;
14 май 19, 22:20    [21884824]     Ответить | Цитировать Сообщить модератору
 Re: Lazarus CryptoAPI пара вопросов.  [new]
SQL-Talker
Member

Откуда: Если есть на свете рай, это - ...
Сообщений: 322
Ghost Writer,

Все заработало, спасибо!
15 май 19, 10:29    [21885029]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить