logo Обзор КриптоПро NGate для защищённого доступа к корпоративным ресурсам
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Syrkov Sergey  
#1 Оставлено : 9 сентября 2010 г. 15:47:57(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Добрый день!
У меня такая проблема.
Есть сертификат в контейнере, контейнер на дискете (планируется на токен), как посмотреть серийный номер сертификата через delphi

Если я правильно понимаю, то
1. Нужно достучаться до контейнера, в крипто-про настроен считыватель a:\
2. Выбрать нужный контейнер, допустим он один на дискете.
3. Посмотреть свойства сертификата.

Как это реализовывается? Есть какие-нибудь примеры. Статью из 4-х частей читал, удалось получить список провайдеров, дальше дело встало.
Offline Kirill Sobolev  
#2 Оставлено : 9 сентября 2010 г. 18:51:20(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,731
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 175 раз в 167 постах
Приблизительно так
А сам серийник можно получить из CERT_CONTEXT.
Техническую поддержку оказываем тут
Наша база знаний
Offline Syrkov Sergey  
#3 Оставлено : 9 сентября 2010 г. 20:46:07(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Спасибо! Окольными путями вышел на дельфи, получилось подцепить контейнеры на дискетке...
Вот с CERT_CONTEXT не понял...
Есть какая-нибудь функция которая смотрит сертификат в контейнере?
Offline Kirill Sobolev  
#4 Оставлено : 9 сентября 2010 г. 21:02:04(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,731
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 175 раз в 167 постах
Да, в примере же есть - CryptGetKeyParam (hKey, KP_CERTIFICATE, NULL,&dwUserCertLength, 0).
Техническую поддержку оказываем тут
Наша база знаний
Offline Syrkov Sergey  
#5 Оставлено : 9 сентября 2010 г. 21:23:52(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Вот не доходит как одно к другому прикрутить...
Сейчас у меня есть вот это и все работает...
Хотелось бы прикрутить функцию, которая возвращала бы SN сертификата..

Код:
procedure TfCheck.btCheckClick(Sender: TObject);
var
  hProv: HCRYPTPROV;
  pbData: PBYTE;
  cbData, Flag: Cardinal;
  str:String;
  a:Cardinal;
  pCertContext :PCCERT_CONTEXT;
  begin
memo1.Clear;
  if not CryptAcquireContextA(@hProv, nil, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, CRYPT_VERIFYCONTEXT) then
   showmessage('Err - if 1 CryptAcquireContext')
  else
  begin
    Flag := CRYPT_FIRST;
    if CryptGetProvParam(hProv, PP_ENUMCONTAINERS, nil, @cbData, Flag) then
    begin
      GetMem(pbData, cbData);
      try
        while CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, @cbData, Flag) do
        begin
          Flag := CRYPT_NEXT;
          memo1.Lines.Add(PAnsiChar(pbData));
        end;
      finally
        FreeMem(pbData, cbData);
      end;
    end;
  end;
end;


Самая моя большая проблема, что плохо рублю в сишном коде.
Offline Syrkov Sergey  
#6 Оставлено : 10 сентября 2010 г. 21:44:04(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Кирилл, не могли бы подсказать, имея вот такой вот код:

Код:
procedure TfCheck.btCheckClick(Sender: TObject);
 var
  hProv: HCRYPTPROV;
  Prov:PAnsiChar;
  hKey: HCRYPTKEY;
  pbData: PBYTE;
  cpbData:PAnsiChar;
  cbData, Flag:Cardinal;
  str:String;
  pbUserCert:PBYTE;
  dwUserCertLength:Cardinal;
begin
memo1.Clear;
hKey:=0;
hProv:=0;
Prov:='Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider';
  if not CryptAcquireContextA(@hProv, nil, Prov, 75, CRYPT_VERIFYCONTEXT) then
  Begin
   showmessage('Err - if 1 CryptAcquireContext')
  end
  else
  begin
    Flag := CRYPT_FIRST;
    if CryptGetProvParam(hProv, PP_ENUMCONTAINERS, nil, @cbData, Flag) then
    begin
      GetMem(pbData, cbData);
      try
        while CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, @cbData, Flag) do
        begin
         cpbData:=PAnsiChar(pbData);

         if not CryptAcquireContextA(@hProv, cpbData, Prov, 75, 0) then
           ShowMessage('Не прицепились к контейнеру');

          Flag := CRYPT_NEXT;
          memo1.Lines.Add(PAnsiChar(pbData));

          if not CryptGetUserKey(hProv,AT_KEYEXCHANGE, @hKey) then
           ShowMessage('CryptGetUserKey Error');

          if not CryptGetKeyParam(hKey,KP_CERTIFICATE ,nil,@dwUserCertLength,0) then
           ShowMessage('CryptGetUserPeram Error');

          GetMem(pbUserCert,dwUserCertLength);

          if not CryptGetKeyParam(hKey,KP_CERTIFICATE ,pbUserCert,@dwUserCertLength,0)
           then ShowMessage('Get Cert_SN Error');
          memo1.Lines.Add((PWideChar(pbUserCert)));


        end;
      finally
        FreeMem(pbData, cbData);
        FreeMem(pbUserCert,dwUserCertLength);
      end;
    end;
  end;
end;



Я получаю вот это на выходе, если в memo переводить как PWideChar, Там проскакивет имя владельца сертификата. При других типах подобная белибирда.
(Первая строка, - это имя контейнера на дискете)
UserPostedImage

Вот как из этого получить серийник, ну и имя владельца чтоли? Это вобще возможно с данным кодом?
Offline Kirill Sobolev  
#7 Оставлено : 13 сентября 2010 г. 16:35:24(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,731
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 175 раз в 167 постах
Это не белиберда, а скорее всего ASN.1, если функции отрабатывают без ошибок.
Далее вызывайте CertCreateCertificateContext, как в примере - можно будет получить и серийник и имя владельца.
Техническую поддержку оказываем тут
Наша база знаний
Offline Syrkov Sergey  
#8 Оставлено : 13 сентября 2010 г. 18:37:29(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Во-о-о-о. Пасиб!.. Массив с данными получил, но серийник что-то цепляться не хочет... Наверное я тип не тот указываю
Код:

VAR
SIGNER1_NAME : Array[1.1000] of Char;
name_size: DWORD;
...
name_size:=0;
name_size := CertNameToStr(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,@(pUserCert.pCertInfo.SerialNumber),CERT_SIMPLE_NAME_STR,nil ,0);
name_size :=CertNameToStr(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,@(pUserCert.pCertInfo.SerialNumber), CERT_SIMPLE_NAME_STR, @SIGNER1_NAME, name_size);
          memo1.Lines.Add(((SIGNER1_NAME)));


А на выходе пустота.
И еще такой вопросик. А можно как-нибудь вытаскивать значения указывая параметр в процедуру? Что-то типа
Код:

name_size := CertNameToStr(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,@(pUserCert.pCertInfo.Subject),CERT_X500_NAME_STR('CN'),nil ,0);

Отредактировано пользователем 13 сентября 2010 г. 20:32:57(UTC)  | Причина: Не указана

Offline Kirill Sobolev  
#9 Оставлено : 13 сентября 2010 г. 20:51:06(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,731
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 175 раз в 167 постах
Цитата:
А на выходе пустота.

CertNameToStr предназначен для декодирования имен, а не серийных номеров.
Цитата:
И еще такой вопросик. А можно как-нибудь вытаскивать значения указывая параметр в процедуру?

Можно через CertFindRDNAttr, CertRDNValueToStr.
Техническую поддержку оказываем тут
Наша база знаний
Offline Syrkov Sergey  
#10 Оставлено : 13 сентября 2010 г. 21:15:19(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Kirill Sobolev написал:
Цитата:
А на выходе пустота.

CertNameToStr предназначен для декодирования имен, а не серийных номеров.

Ну это я уже понял )) Мне бы что-нибудь, хотябы отдаленное, покопаться.
Offline Syrkov Sergey  
#11 Оставлено : 13 сентября 2010 г. 22:23:20(UTC)
Syrkov Sergey

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

Группы: Участники
Зарегистрирован: 09.09.2010(UTC)
Сообщений: 7
Откуда: Москва

Кстати, вот так получилось вытащить серийник, топорно, тупо, но работает

Код:

st,st1,str:String;

...
str:='0123456789ABCDEF';

st1:='';
 for i:=pUsercert.pCertInfo.SerialNumber.cbData-1 downto 0 do
    Begin
     st:=str[trunc(pUserCert.pCertInfo.SerialNumber.pbData[i]/16)+1]+ str[(pUserCert.pCertInfo.SerialNumber.pbData[i]-trunc(pUserCert.pCertInfo.SerialNumber.pbData[i]/16)*16)+1];
     st1:=st1+' '+st;
    End;
    memo1.Lines.Add('Serial Number: '+st1);
Offline Helior  
#12 Оставлено : 24 декабря 2010 г. 18:58:54(UTC)
Helior

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

Группы: Участники
Зарегистрирован: 24.12.2010(UTC)
Сообщений: 3

А не подскажете, как получить из сертификата список расширений в виде strings?
Offline Kirill Sobolev  
#13 Оставлено : 24 декабря 2010 г. 19:30:21(UTC)
Кирилл Соболев

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

Группы: Участники
Зарегистрирован: 25.12.2007(UTC)
Сообщений: 1,731
Мужчина
Откуда: КРИПТО-ПРО

Поблагодарили: 175 раз в 167 постах
Если это вопрос про использование CryptoAPI, то расширения хранятся в массиве CERT_CONTEXT::pCertInfo->rgExtension[]
Техническую поддержку оказываем тут
Наша база знаний
Offline Helior  
#14 Оставлено : 24 декабря 2010 г. 21:22:36(UTC)
Helior

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

Группы: Участники
Зарегистрирован: 24.12.2010(UTC)
Сообщений: 3

Меня интересуют эти расширения


[IMG]http://www.imghost.in/?di=512932073348[/IMG]


А в cert.pCertInfo.rgExtension.pszObjId совершенно другое.
Или это надо CryptDecodeObject`ом вытаскивать, или я совсем не в ту сторону смотрю...
Есть ли где-нибудь наглядный пример подобной разборки сертификата?

Отредактировано пользователем 24 декабря 2010 г. 21:23:41(UTC)  | Причина: Не указана

Offline Dmitriy3008  
#15 Оставлено : 24 декабря 2010 г. 23:22:54(UTC)
Dmitriy3008

Статус: Активный участник

Группы: Участники
Зарегистрирован: 30.08.2009(UTC)
Сообщений: 52

Сказал(а) «Спасибо»: 4 раз
Поблагодарили: 2 раз в 2 постах
Helior, два примерно одинаковых способа:

1)

Код:
type
  PCharArr = ^TCharArr;
  TCharArr = array[0..0] of PChar;

procedure CertGetEnhKeyUsage(Context: PCCERT_CONTEXT; Strings: TStrings);
var
  pEnhKeyUsage: PCERT_ENHKEY_USAGE;
  cbStructInfo: DWORD;
  I: Cardinal;
begin
  if not Assigned(Strings) then
    raise Exception.Create('ругаемся, что объект не создан...');

  if CertGetEnhancedKeyUsage(Context, 0, nil, @cbStructInfo) then
  begin
    GetMem(pEnhKeyUsage, cbStructInfo);
    try
      if CertGetEnhancedKeyUsage(Context, 0, pEnhKeyUsage, @cbStructInfo) then
      begin
        for I := 0 to pEnhKeyUsage^.cUsageIdentifier -1 do
          Strings.Add(PCharArr(pEnhKeyUsage^.rgpszUsageIdentifier)[I]);
      end;
    finally
      FreeMem(pEnhKeyUsage, cbStructInfo);
    end;
  end;
end;


2)
Код:
type
  PCharArr = ^TCharArr;
  TCharArr = array[0..0] of PChar;

procedure CertGetEnhKeyUsage(Context: PCCERT_CONTEXT; Strings: TStrings);
var
  pExtension: PCERT_EXTENSION;
  pEnhKeyUsage: PCERT_ENHKEY_USAGE;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  I: Cardinal;
begin
  if not Assigned(Strings) then
    raise Exception.Create('ругаемся, что объект не создан...');

  pExtension := CertFindExtension(szOID_ENHANCED_KEY_USAGE,
    Context^.pCertInfo^.cExtension, Context^.pCertInfo^.rgExtension);

  if Assigned(pExtension) and Win32Check(CryptDecodeObject(X509_ASN_ENCODING,
    X509_ENHANCED_KEY_USAGE, pExtension^.Value.pbData, pExtension^.Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, nil, @cbStructInfo)) then
  begin
    GetMem(pvStructInfo, cbStructInfo);
    try
      CryptDecodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE,
        pExtension^.Value.pbData, pExtension^.Value.cbData, 0, pvStructInfo, @cbStructInfo);

      pEnhKeyUsage := PCERT_ENHKEY_USAGE(pvStructInfo);

      for I := 0 to pEnhKeyUsage^.cUsageIdentifier -1 do
        Strings.Add(PCharArr(pEnhKeyUsage^.rgpszUsageIdentifier)[I]);

    finally
      FreeMem(pvStructInfo, cbStructInfo);
    end;
  end;
end;

Ты не из казначейства?
thanks 1 пользователь поблагодарил Dmitriy3008 за этот пост.
MotoArhangel оставлено 18.04.2015(UTC)
Offline Helior  
#16 Оставлено : 25 декабря 2010 г. 2:28:39(UTC)
Helior

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

Группы: Участники
Зарегистрирован: 24.12.2010(UTC)
Сообщений: 3

Спасибо, товарищ )))))
Ты меня прям спас, а то я спать не мог.
Сижу теперь курю код.
Да, из казначейства. По расширениям понял?
Offline Dmitriy3008  
#17 Оставлено : 29 декабря 2010 г. 3:46:11(UTC)
Dmitriy3008

Статус: Активный участник

Группы: Участники
Зарегистрирован: 30.08.2009(UTC)
Сообщений: 52

Сказал(а) «Спасибо»: 4 раз
Поблагодарили: 2 раз в 2 постах
Да, по расширениям. Рад помочь коллеге.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.