powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CryptoAPI - Уникальный идентификатор сертификата
11 сообщений из 11, страница 1 из 1
CryptoAPI - Уникальный идентификатор сертификата
    #39816570
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне нужен уникальный идентификатор сертификата. В интернетах предлагают использовать для этих целей Issuer + SerialNumber.
Нашел в доках функцию CertGetCertificateContextProperty которая с параметром CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID возвращает хэш Издателя + сер.номер
авторMD5 hash of the issuer name and serial number from this certificate
https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-certgetcertificatecontextproperty#cert_issuer_serial_number_md5_hash_prop_id

Написал функцию:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
// Получить уникальный Id сертификата (MD5 hash of the issuer name and serial number from this certificate)
function Cert_GetCertUID(aCertContext: PCCERT_CONTEXT): string;
var
  Data: PChar;
  DataLen: DWORD;
  i: Integer;
  Res: string;
begin
  Res := '';

  if CertGetCertificateContextProperty(
    aCertContext,
    CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
    nil,
    DataLen
  )
  then
  begin
    GetMem(Data, DataLen);

    if CertGetCertificateContextProperty(
      aCertContext,
      CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
      @Data[0],
      DataLen
    )
    then
      for i := 1 to DataLen do
        Res := Res + Format('%.2x', [PBYTE(@Data[i - 1])^]);
  end;

  Result := Res;
end;



Все бы хорошо, но вместо ожидаемого поведения когда для одного и того же сертификата, возвращаемое значение всегда одно и то же, получил такое:
если ее вызвать несколько раз подряд то первые 2-3-4 раза (по разному всякий раз) значения возвращаются разные, а потом "стабилизируется" и возвращается одинаковый результат.

Но после перезапуска программы, опять все по новой естественно.

Явно где-то слажал. А вот где?
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816587
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как минимум так
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
function Cert_GetCertUID(aCertContext: PCCERT_CONTEXT): string;
var
  Data: array of Byte;
  DataLen: DWORD;
begin
  Result := '';
  DataLen := 0;
  if CertGetCertificateContextProperty(
    aCertContext,
    CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
    nil,
    DataLen
  )
  then begin
    SetLength(Data, DataLen);
    if CertGetCertificateContextProperty(
      aCertContext,
      CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
      @Data[0],
      DataLen
    )
    then begin
      SetLength(Result, DataLen * 2);
      BinToHex(Data[0], PChar(Result), DataLen);
    end;
  end;
end;



А если вспомнить, что MD5 хеш имеет фиксированную длину 128 бит = 16 байт, то вообще вот так

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
function Cert_GetCertUID(aCertContext: PCCERT_CONTEXT): string;
const
  DataLen = 16;
var
  Data: array[0 .. DataLen - 1] of Byte;
  DataLenTmp: DWORD;
begin
  DataLenTmp := DataLen;

  if CertGetCertificateContextProperty(
    aCertContext,
    CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
    @Data[0],
    DataLenTmp
  )
  then begin
    SetLength(Result, DataLen * 2);
    BinToHex(Data[0], PChar(Result), DataLen);
  end else
    Result := '';
end;

...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816604
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Т.е. ключевая ошибка в том что не учел, что в отличие от старых версий Delphi , Char теперь равен WideChar, что состовляет 2 байта а не один

Спасибо большое, все глаза проглядел, но не мог увидеть в чем трабла ))
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816617
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerТ.е. ключевая ошибка в том что не учел, что в отличие от старых версий Delphi , Char теперь равен WideChar, что состовляет 2 байта а не одини ещеpcbData

A pointer to a DWORD value that specifies the size, in bytes, of the buffer pointed to by the pvData parameter. When the function returns, the DWORD value contains the number of bytes to be stored in the buffer.

To obtain the required size of a buffer at run time, pass NULL for the pvData parameter, and set the value pointed to by this parameter to zero . If the pvData parameter is not NULL and the size specified in pcbData is less than the number of bytes required to contain the data, the function fails, GetLastError returns ERROR_MORE_DATA, and the required size is placed in the variable pointed to by the pcbData parameter.
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816618
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talkerключевая ошибкаНу и вызов GetMem подразумевает FreeMem
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816703
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

Ага, спасибо!
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39816906
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

Чем sha1 не угодил, который ОС сама и показывает в окне при просмотре сертификата, вкладка Состав?

Связка Issuer + SerialNumber - нужна для расшифровки, чтобы определить перечень сертификатов, сверить с доступными и
определить какую связку (сертификат - контейнер) использовать.
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39817944
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sql2012,

sha1 это - "certificate fingerprint" ?
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39817974
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

Именно.
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39817981
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, здорово!

SHA1 получаю функцией CertGetCertificateContextProperty с параметром CERT_SHA1_HASH_PROP_ID

А функцией CertFindCertificateInStore с параметром CERT_FIND_SHA1_HASH в один ход производится поиск в хранилище по этому отпечатку.

В предыдущем варианте для поиска нужно перебирать сертификаты с помощью CertEnumCertificatesInStore а тут короче.

Спасибо!
...
Рейтинг: 0 / 0
CryptoAPI - Уникальный идентификатор сертификата
    #39817992
Фотография Romka-Fes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerМне нужен уникальный идентификатор сертификата
есть GUID )))
p.s. http://www.opennet.ru/opennews/art.shtml?num=50674
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CryptoAPI - Уникальный идентификатор сертификата
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]