06.06.2003 13:08:27CRL - ничего не выходит Ответов: 37
Олег
1 В каком хранилище Windows 2000 server CA хранит CRL?

2 Почему из файла gost_ca.crl не создается контекст CRL? Ф-я CertCreateCRLContext говорит ASN1Error. Хотя ASN1 разборщик говорит что 0 ошибок.

3 Есть какой-нибудь пример для работы с LDAP применительно к CRL? (я исходники имею ввиду)
 
Ответы:
12.05.2004 14:32:04mike
мне тоже интересен этот вопрос. а именно - программный разбор CRL. в sample я не нашел примера работы с CRL. спасибо.
13.05.2004 12:11:34Kirill Sobolev
1. Локальный компьютер - Промежуточные центры сертификации (HKLM/CA)
2. CRL не в base64 случайно?

Работа с CRL_CONTEXT вообщем-то полностью аналогична работе с CERT_CONTEXT, а какого рода разбор интересует?
13.05.2004 12:28:10mike
c CERT_CONTEXT получаю сначала контекст:
...
store:= CertOpenSystemStore(hprov, ’MY’);
cert:= CertEnumCertificatesInStore(store, nil);
...
и нормально работаю дальше со структурой
с CRL_CONTEXT не могу получить контекст
структуры:
flags:=CERT_STORE_SIGNATURE_FLAG or CERT_STORE_TIME_VALIDITY_FLAG;
CertGetCRLFromStore(store,cert,nil,@flags)
функция CertGetCRLFromStore не отрабатывает.
13.05.2004 12:32:08Kirill Sobolev
А что значит не отрабатывает?
GetLastError возвращает что-нибудь?
13.05.2004 12:41:15Олег
(чего там было то год назад....)

Как сейчас помню- пытался я научиться работать с CRL с целью поиска там заданного сертификата (писал я функцию bool IsCertificateValid(...))
Порылся по хранлищам W2kserver - не нашел CRL. ok, экспортировал его из W2kserver’s CA, и пытался создать контекст CRL. Не вышло. ... Закоментировал эту проверку и дальше писал :)
Нет, не было там Base64 - мой ASN1 разборщик такое бы просто не сожрал. DER там была.
13.05.2004 12:45:21Kirill Sobolev
Тогда сложно сказать )))
Но CertCreateCRLContext создает CRL_CONTEXT из DER без проблем, дело скорее всего было в чем-то другом.
13.05.2004 14:11:21mike
GetLastError возвращает 2148081668
13.05.2004 14:20:23Kirill Sobolev
это CRYPT_E_NOT_FOUND
значит, CRL изданный этим центром отсутствует в хранилище либо он просрочен
13.05.2004 14:38:14mike
мм-да, вроде и не просрочен и во все хранилища для верности запихал,
может это поэтому что я взял CRL с Вашего тестового центра, а не использую какой-то другой
13.05.2004 14:43:34Kirill Sobolev
А CertEnumCRLsInStore его находит?
13.05.2004 15:06:39mike
да вроде отрабатывает
...
crlcnt:= CertEnumCRLsInStore(store,nil);
if crlcnt = nil then
ShowMessage(’NO - ’+IntToStr(GetLastError))
else
ShowMessage(’CertEnumCRLsInStore - YES’);
...
13.05.2004 15:14:50Kirill Sobolev
значит, если CRL свежий, проблема в сертификате издателя. Возможно, для CertGetCRLFromStore вы передаете не тот сертификат.
18.05.2004 16:35:36mike
Еще несколько вопросов:
1. Надо ли полученную структуру PCCRL_CONTEXT чтобы получить из неё серийные номера и даты отзыва сертификатов?
2. Где конкретно в этой структуре лежат
серийные номера и даты отзыва сертификатов?
3. Сколько в принципе может существовать
в хранилище списков CRL одного издателя - 1 или больше, и разных издателей?
18.05.2004 16:42:11Kirill Sobolev
1. Да, надо.
2. Даты и серийные номера лежат в CRL_CONTEXT::CRL_INFO, в массиве rgCRLEntry.
3. Возможно и то и другое
18.05.2004 17:42:29mike
:))
В первом вопросе имелось ввиду надо ли декодировать структуру?
19.05.2004 11:12:38Kirill Sobolev
В каком смысле декодировать? У Вас есть blob СRL в DER, Вы его подсовываете CertCreateCRLContext и все.
19.05.2004 12:07:22mike
Окончательно запутался:
1.Зачем выполнять CertCreateCRLContext, которая возвращает PCCRL_CONTEXT, усли у меня уже есть PCCRL_CONTEXT после чтения из файла
2.Получаю из PCCRL_CONTEXT даты начала действия и след. обновления:
FileTimeToSystemTime(Pinfo^.pCrlInfo^.ThisUpdate,thisupd);
FileTimeToSystemTime(Pinfo^.pCrlInfo^.NextUpdate,nextupd);
ShowMessage(’CRL - действителен c : ’+DateTimeToStr(SystemTimeToDateTime(thisupd))+#10#13+
’CRL - следующее обновление : ’+DateTimeToStr(SystemTimeToDateTime(nextupd)));
С этим нормально, получаю дату отзыва
первого сертификата:
FileTimeToSystemTime(Pinfo^.pCrlInfo^.rgCRLEntry^.RevocationDate,revdate);
ShowMessage(’CRL - дата отзыва : ’+DateTimeToStr(SystemTimeToDateTime(revdate)));
Не могу получить даты и серийные номера
остальных сертификатов, подскажите как их вытащить?
19.05.2004 12:11:55Kirill Sobolev
1. Не понял, а из файла как CRL_CONTEXT получается.
2. Суть в том, что CRL_INFO::rgCRLEntry - это массив отозванных сертифкатов в это CRL, CRL_INFO::cCRLEntry - количество элементов в нем. Но как перебрать элементы в массиве на Паскале, я не подскажу :) не помню уже.
19.05.2004 13:18:56mike
CRL_CONTEXT получаю из файла, переделав
Вашу функцию read_cert_from_file из примеров
Спасибо.
20.05.2004 23:08:54mike
А то, что вместо серийных номеров отозванных сертификатов в формате ’xxxx xxxx xxxx xxxx xxxx’ я получаю 3 для 1-го отозваноого из списка, 5 - для второго и т.д. - 6,7,8,9,11,12.
Это нормально, или нет???
21.05.2004 10:44:23Kirill Sobolev
Нет, не нормально. Серийные номера хранятся в формате CRYPTOAPI_BLOB, как Вы его преобразовываете?
24.05.2004 13:54:10mike
Я пытаюсь получить его из структуры
Pinfo.pCrlInfo.rgCRLEntry.SerialNumber,
где Pinfo.pCrlInfo.rgCRLEntry.SerialNumber.cbdata - размер в байтах,
Pinfo.pCrlInfo.rgCRLEntry.SerialNumber.pbData - указатель на данные,
я правильно понимаю или нет, наставьте на путь истинный, please!
24.05.2004 13:56:53Kirill Sobolev
все правильно, именно отсюда и берется
24.05.2004 15:07:06mike
а номера там в 16-ричном виде лежат, как отображаются, или в каком-то другом?
24.05.2004 15:10:32Kirill Sobolev
да, в 16ричном. в каждом байте лежат по две цифры серийного номера
24.05.2004 16:44:20mike
Спасибо, с серийниками разобрался, подскажите c причиной отзыва.
Лежит в Pinfo.pCrlInfo.rgCRLEntry.rgExtension.Value ?
И что лежит в Pinfo.pCrlInfo.rgCRLEntry.rgExtension.fCritical и Pinfo.pCrlInfo.rgCRLEntry.rgExtension.pszObjId ?
24.05.2004 17:02:17Kirill Sobolev
причина отзыва лежит Value расширения с OID 2.5.29.21. fCritical - это признак того, является ли это расширение критическим или нет. Причина отзыва критическим расширением не является.
24.05.2004 17:22:33mike
У меня все Pinfo.pCrlInfo.rgCRLEntry.rgExtension.pszObjId возвращают 2.5.29.21, хотя визуально я вижу, что причины отзыва разные.
24.05.2004 17:30:37Kirill Sobolev
Конечно :) OID определяет, что в этом расширении содержится причина отзыва, а поле Value собственно уже содержит значение этой причины
24.05.2004 17:46:50mike
Подскажите в каком виде хранится причина отзыва,
надо ли ей делать CertOIDToAlgId(),
хотя наверно нет,
не надо случайно ничего там декодировать?
24.05.2004 17:50:38Kirill Sobolev
ничего не надо делать, код хранится в открытом виде.

CRLReason ::= ENUMERATED {
unspecified (0),
keyCompromise (1),
cACompromise (2),
affiliationChanged (3),
superseded (4),
cessationOfOperation (5),
certificateHold (6),
removeFromCRL (8) }

(из RFC 2459)
25.05.2004 9:10:27mike
Да, спасибо, почему спрашивал на счет декодирования, у меня вместо 0,1..8 возвращается 0110, 1110, 2110, 3110..8110
Можно конечно использовать только первый символ только некрасиво получается
25.05.2004 9:31:59Kirill Sobolev
упс, это я наврал, прошу прощения.
надо конечно же сделать CryptDecodeObject с параметром szOID_CRL_REASON_CODE
26.05.2004 10:50:20mike
Не понимаю, я правильно делаю или нет:
CryptDecodeObject(encType,szOID_CRL_REASON_CODE,pbEncoded,cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,nil,@pcbStructInfo);
GetMem(pvStructInfo,pcbStructInfo);
CryptDecodeObject(encType,szOID_CRL_REASON_CODE,pbEncoded,cbEncoded,CRYPT_DECODE_NOCOPY_FLAG,nil,@pcbStructInfo)
26.05.2004 10:56:07Kirill Sobolev
А почему оба вызова CryptDecodeObject одинаковые? Во втором вместо nil должно быть pvStructInfo
02.06.2004 11:05:57mike
Получаю даты из сертификата или из CRL, даты получаются нормально, но на 4 часа меньше, чем при просмотре самого сертификата или CRL, разницап между Москвой и Гринвичем или что?
что делать - добавлять везде по 4 часа?
02.06.2004 11:13:14Kirill Sobolev
Да. Из MSDN: "Time is UTC-time encoded as a eight-byte date/time precise to seconds with a two digit year (that is, YYMMDDHHMMSS plus 2 bytes)." 4 часа конечно можно прибавлять, но это не очень хороший выход, лучше воспользоваться функцией FileTimeToLocalFileTime.