Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как узнать имя сертификта в контейнере (дискета) через CryptoAPI? [D7, XP]


ANB ©   (2006-08-01 10:58:00) 

Использую Крипто Про.
Провайдер проинициализирован, имя контейнера вытащил.
Просмотрел MSDN, ничего подходящего не увидел, но винда это как то делает.
Цель проста - узнать имя сертификата на дискете - носителе закрытого ключа.


Reindeer Moss Eater   (2006-08-02 11:29:00) [1]

Если имеешь валидный контекст сертификата, то значит у тебя есть например указатель на блоб с сабджектом

pCertContext^.pCertInfo^.Subject

Далее применяешь к этому блобу CertNameToStrA (CertNameToStrW) и получаешь имя владельца в чистом виде

Если нужен издатель, то идешь сюда
pCertContext^.pCertInfo^.Issuer. Там указатель на тот же самый CERT_NAME_BLOB


Reindeer Moss Eater   (2006-08-02 10:59:00) [2]

У сертификата нет имени.
Скажи что хочешь узнать.


ANB   (2006-08-02 10:14:00) [3]

Ну, типа примерно вот так получилось.
Константы ошибок и процедуру проверки результата не привожу - при желании кому нужно сам напишет.


class function CryptoPro.GetCertNameFromCurrentContainer() : String;
var l : Cardinal;
   CryptProv : HCRYPTPROV;
   UserKey : HCRYPTKEY;
   ProvName : String;
   ProvType : Cardinal;
   Container : String;
   Cert_Info : String;
   Cert_Context : PCCERT_CONTEXT;
   TypePara : Cardinal;
   Cert_Name : String;
begin
 {
 // Достать имя и тип первого провайдера
 // Оставляю этот закомментаренный блок на случай, если понадобится узнать имя и тип провайдера
 R := CryptEnumProviders(0, nil, 0, ProvType, nil, l);
 if not R then begin ShowMessage('Ошибка узнавания длинны имени провайдера'); exit; end;
 SetLength(ProvName, l);
 R := CryptEnumProviders(0, nil, 0, ProvType, PChar(ProvName), l);
 if not R then begin ShowMessage('Ошибка узнавания имени провайдера'); exit; end;
 SetLength(ProvName, l - 1);
 ShowMessage('Провайдер ' + IntToStr(ProvType) + ' [' + ProvName + ']');
 AddToLogText('Тип = ' + IntToStr(ProvType) + ' Имя = [' + ProvName + ']');
 AddToLogText('Имя (Hex) = [' + StringToHex(ProvName) + ']');
 }

 ProvType := 75;
 ProvName := 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider';
 CryptProv := 0;
 try
   try
     CheckError(CryptAcquireContext(CryptProv, nil, PChar(ProvName),
                                    ProvType, CRYPT_VERIFYCONTEXT));
   except
     on E : Exception do begin
       raise AddExceptionHeaderFooter(E, CryptoPro_Err_Prov_Connect, '', [ProvName]);
     end;
   end;
   // Узнаем имя контейнера
   // Размер
   l := 0;
   try
     CheckError(CryptGetProvParam(CryptProv, PP_ENUMCONTAINERS, nil, l, CRYPT_FIRST));
   except
     on E : Exception do begin
       raise AddExceptionHeader(E, CryptoPro_Err_Get_Container_Name_Len);
     end;
   end;
   SetLength(Container, l);
   // Собственно имя
   try
     CheckError(CryptGetProvParam(CryptProv, PP_ENUMCONTAINERS, PByte(PChar(Container)), l, CRYPT_FIRST));
   except
     on E : Exception do begin
       raise AddExceptionHeader(E, CryptoPro_Err_Get_Container_Name_Len);
     end;
   end;
 finally
   if (CryptProv <> 0)
   then CryptReleaseContext(CryptProv, 0);
 end;
 // Переподключимся к конкретному контейнеру
 CryptProv := 0;
 try
   try
     CheckError(CryptAcquireContext(CryptProv, PChar(Container), PChar(ProvName),
                                    ProvType, 0));
   except
     on E : Exception do begin
       raise AddExceptionHeaderFooter(E, CryptoPro_Err_Prov_Container_Connect, '', [ProvName, Container]);
     end;
   end;
   try
     CheckError(CryptGetUserKey(CryptProv, AT_KEYEXCHANGE, UserKey));
   except
     on E : Exception do begin
       raise AddExceptionHeader(E, CryptoPro_Err_Get_Key);
     end;
   end;
   try
     CheckError(CryptGetKeyParam(UserKey, KP_CERTIFICATE, nil, l, 0));
   except
     on E : Exception do begin
       raise AddExceptionHeader(E, CryptoPro_Err_Get_Cert_Len);
     end;
   end;
   SetLength(Cert_Info, l);
   try
     CheckError(CryptGetKeyParam(UserKey, KP_CERTIFICATE, PByte(PChar(Cert_Info)), l, 0));
   except
     on E : Exception do begin
       raise AddExceptionHeader(E, CryptoPro_Err_Get_Cert);
     end;
   end;
   Cert_Context := nil;
   try
     Cert_Context := CertCreateCertificateContext(X509_ASN_ENCODING, PByte(PChar(Cert_Info)), l);
     if (Cert_Context = nil) then begin
       raise Exception.Create(CryptoPro_Err_CreateCertificateContext);
     end;
     l := 0;
     l := CertGetNameString(Cert_Context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, @TypePara, nil, l);
     if (l <= 0) then begin
      raise Exception.Create(CryptoPro_Err_Get_Cert_Name_Len);
     end;
     SetLength(Cert_Name, l);
     l := CertGetNameString(Cert_Context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, @TypePara, PChar(Cert_Name), l);
     if (l <= 0) then begin
      raise Exception.Create(CryptoPro_Err_Get_Cert_Name);
     end;
     SetLength(Cert_Name, l - 1);
     Result := Cert_Name;
   finally
     CertFreeCertificateContext(Cert_Context);
   end;
 finally
   if (CryptProv <> 0)
   then CryptReleaseContext(CryptProv, 0);
 end;
end;


ANB   (2006-08-01 16:45:00) [4]

упс. Никто не работал с Крипто АПИ ?
Значится, смог я подключиться к нужному ключу (сертификату) и вытащить его хендл. А чего дальше делать - не знаю.


Наверх

Титульная страница Поиск, карта сайта Написать письмо