![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как узнать имя сертификта в контейнере (дискета) через 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]упс. Никто не работал с Крипто АПИ ?
Значится, смог я подключиться к нужному ключу (сертификату) и вытащить его хендл. А чего дальше делать - не знаю.