Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.08.20;
Скачать: CL | DM;

Вниз

Как узнать имя сертификта в контейнере (дискета) через CryptoAPI?   Найти похожие ветки 

 
ANB ©   (2006-08-01 10:58) [0]

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


 
ANB ©   (2006-08-01 16:45) [1]

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


 
ANB ©   (2006-08-02 10:14) [2]

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


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;


 
Reindeer Moss Eater ©   (2006-08-02 10:59) [3]

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


 
Reindeer Moss Eater ©   (2006-08-02 11:29) [4]

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

pCertContext^.pCertInfo^.Subject

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

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



Страницы: 1 вся ветка

Текущий архив: 2006.08.20;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.056 c
4-1146456876
kernel
2006-05-01 08:14
2006.08.20
Add resource


15-1153820130
Ling
2006-07-25 13:35
2006.08.20
Помогите найти


2-1154032666
susergey
2006-07-28 00:37
2006.08.20
ShellExecute


4-1146038577
tvv
2006-04-26 12:02
2006.08.20
Работа с оборудованием


2-1154425301
Damager
2006-08-01 13:41
2006.08.20
TAction компоненты + XPMan