Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Gorilka  
#1 Оставлено : 1 октября 2009 г. 19:45:29(UTC)
Gorilka

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

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

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

Код Delphi:
В hCertMyStore храним хэндл открытого хранилища "MY", это переменная формы.
iCertID имеет вид 'Сертификат № '+vSerialNumber+' выдан '+vIssuer, разбирается правильно
Цитата:
function TfrmCrypto.CertIDToContext(iCertID:string):PCCERT_CONTEXT;
var vSearchMask:CERT_INFO;
vSearchSerialNumber:string;
vSearchIssuer:string;
pSerialNumber:PByte;
vInd:integer;
begin
//Сертификаты ищутся по "маске", для того чтобы найти сертификат, сначала надо создать похожую структуру
Result:=nil;
if not Assigned(hCertMyStore) then
if not CertOpenMyStore then //Тут стандартная функция открытия хранилища "MY"
begin
//Хранилище сертификатов не открыто
Exit;
end;
//Разбираем идентификатор
iCertID:=Copy(iCertID, 14, Length(iCertID));
vInd:=pos(' ', iCertID);
vSearchIssuer:=Copy(iCertID, vInd+7, Length(iCertID));
vSearchSerialNumber:=AnsiLowerCase(Copy(iCertID, 1, vInd-1));
//Инициализируем структуру сертификата
FillChar(vSearchMask, SizeOf(CERT_INFO), #0);
vSearchMask.dwVersion := CERT_V3;
//Обрабатываем серийный номер сертификата
vInd:=Length(vSearchSerialNumber) div 2; //Так как представление HEX то байтов в 2 раза меньше
vSearchMask.SerialNumber.cbData:=vInd;
vSearchMask.SerialNumber.pbData:=GetMemory(vInd);
pSerialNumber:=vSearchMask.SerialNumber.pbData;
while (vInd > 0) do
begin
pSerialNumber^:=StrToInt('0x'+Copy(vSearchSerialNumber, vInd*2-1, 2));
inc(pSerialNumber);
dec(vInd);
end;
//Обрабатывыем имя издателя
//Сначала получаем размер структуры издателя
CertStrToName(X509_ASN_ENCODING, PAnsiChar('CN = '+vSearchIssuer), CERT_X500_NAME_STR, nil, nil, vSearchMask.Issuer.cbData, nil);
vSearchMask.Issuer.pbData := GetMemory(vSearchMask.Issuer.cbData);
//А теперь вносим данные о нем
CertStrToName(X509_ASN_ENCODING, PAnsiChar('CN = '+vSearchIssuer), CERT_X500_NAME_STR, nil, vSearchMask.Issuer.pbData, vSearchMask.Issuer.cbData, nil);
// Ищем сертификат
Result:=CertFindCertificateInStore(hCertMyStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, @vSearchMask, nil);
if not Assigned(Result) then
begin
//Поиск провалился, чего быть не должно, эксепшн
Exit;
end;
end;


Result возвращает nil, если не сложно, подскажите где косяк?
Offline Gorilka  
#2 Оставлено : 1 октября 2009 г. 20:31:13(UTC)
Gorilka

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

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

Вот возникла одна идейка, не подскажите, по поводу флага CERT_FIND_SUBJECT_CERT
в MSDN написано
Цитата:
Searches for a certificate with both an issuer and a serial number that match the issuer and serial number in the CERT_INFO structure.

Поиск идет по полному совпадению? То есть если у меня в маске поиска задано только поле CN, а остальные поля не заданы, он найдет? Или ему всетаки надо полное совпадение структур issuer?
Offline Kirill Sobolev  
#3 Оставлено : 1 октября 2009 г. 21:44:11(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Цитата:
Result возвращает nil, если не сложно, подскажите где косяк?

Сравните то, что получается в vSearchMask.SerialNumber с тем что лежит в PCCERT_CONTEXT.
Цитата:
Или ему всетаки надо полное совпадение структур issuer?

Полное.
Техническую поддержку оказываем тут
Наша база знаний
Offline Gorilka  
#4 Оставлено : 1 октября 2009 г. 22:29:30(UTC)
Gorilka

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

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

Спасибо, уже решил проблему, правда "через назад", идея о полном совпадении структуры issuer оказалась верной.
Для будущих поколений, возможно кому-нибудь пригодится

Код Delphi:
Добавление к предыдущим коментариям - TCharArray=array [0.255] of Char;

Цитата:
function TfrmCrypto.CertIDToContext(iCertID:string):PCCERT_CONTEXT;
var vSearchMask:CERT_ID;
vSearchSerialNumber:string;
vSearchIssuer:string;
pSerialNumber:PByte;
vInd:integer;
vIssuerName:PWideChar;
pBufContext:PCCERT_CONTEXT;
vBufStrIssuer:TCharArray;
begin
//Сертификаты ищутся по "маске", для того чтобы найти сертификат, сначала заполняем структуру CERT_ID
if not Assigned(hCertMyStore) then
if not CertOpenMyStore then
begin
//Хранилище сертификатов не открыто
Exit;
end;
//Разбираем идентификатор
iCertID:=Copy(iCertID, 14, Length(iCertID));
vInd:=pos(' ', iCertID);
vSearchIssuer:=Copy(iCertID, vInd+7, Length(iCertID));
vSearchSerialNumber:=AnsiLowerCase(Copy(iCertID, 1, vInd-1));
//Инициализируем структуру сертификата
FillChar(vSearchMask, SizeOf(CERT_ID_ISSUER_SERIAL_NUMBER), #0);
//Обрабатываем серийный номер сертификата
vInd:=Length(vSearchSerialNumber) div 2; //Так как представление HEX то байтов в 2 раза меньше
vSearchMask.dwIdChoice:=CERT_ID_ISSUER_SERIAL_NUMBER;//Поиск по IssuerSerialNumber
vSearchMask.IssuerSerialNumber.SerialNumber.cbData:=vInd;
vSearchMask.IssuerSerialNumber.SerialNumber.pbData:=GetMemory(vInd);
pSerialNumber:=vSearchMask.IssuerSerialNumber.SerialNumber.pbData;
while (vInd > 0) do
begin
pSerialNumber^:=StrToInt('0x'+Copy(vSearchSerialNumber, vInd*2-1, 2));
inc(pSerialNumber);
dec(vInd);
end;
//Обрабатывыем имя издателя. Придется извращаться, так как чтобы найти по Issuer необходимо передать полную структуру.
GetMem(vIssuerName, Length(vSearchIssuer)*2+1);
StringToWideChar(vSearchIssuer, vIssuerName, Length(vSearchIssuer)*2+1);
pBufContext:=CertFindCertificateInStore(hCertMyStore, X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_STR, vIssuerName, nil);
CertNameToStr(pBufContext.dwCertEncodingType, @pBufContext.pCertInfo.Issuer, CERT_X500_NAME_STR, vBufStrIssuer, 255);
vSearchIssuer:=vBufStrIssuer;
//Получаем размер структуры издателя
CertStrToName(X509_ASN_ENCODING, PAnsiChar(vSearchIssuer), CERT_X500_NAME_STR, nil, nil, vSearchMask.IssuerSerialNumber.Issuer.cbData, nil);
vSearchMask.IssuerSerialNumber.Issuer.pbData := GetMemory(vSearchMask.IssuerSerialNumber.Issuer.cbData);
//А теперь вносим данные о нем
CertStrToName(X509_ASN_ENCODING, PAnsiChar(vSearchIssuer), CERT_X500_NAME_STR, nil, vSearchMask.IssuerSerialNumber.Issuer.pbData, vSearchMask.IssuerSerialNumber.Issuer.cbData, nil);
// Ищем сертификат
Result:=CertFindCertificateInStore(hCertMyStore, X509_ASN_ENCODING, 0, CERT_FIND_CERT_ID, @vSearchMask, nil);
if not Assigned(Result) then
begin
//Поиск провалился, чего быть не должно, эксепшн
Exit;
end;
end;

Отредактировано пользователем 1 октября 2009 г. 22:35:27(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.