powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CryptoAPI - Как получить все атрибуты поля Subject?
20 сообщений из 20, страница 1 из 1
CryptoAPI - Как получить все атрибуты поля Subject?
    #39822988
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как получить все атрибуты поля Subject?
Так чтобы у меня был массив записей из 2-х параметров - имя_атрибута, значение_атрибута :
Код: pascal
1.
[(PropName: "CN", PropValue: "Microsoft Root Certificate Authority 2011"), ...]

Причем, как я понимаю, там могут быть совершенно нестандартные атрибуты типа ИНН, КПП и проч.
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823081
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

самый простой способ - прочитать Subject функцией CertNameToStr. для нее есть три константы
const CERT_SIMPLE_NAME_STR = 1;
const CERT_OID_NAME_STR = 2;
const CERT_X500_NAME_STR = 3;

последние две как раз дают результат с именами атрибутов.
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823090
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

Я получаю строку Subject таким способом, вопрос в том как распарсить эту строку
К примеру :
авторC=US, S=California, L=San Jose, O="Adobe Systems, Incorporated", OU=Digital ID Class 3 - Microsoft Software Validation v2, OU=Acrobat Engineering, CN="Adobe Systems, Incorporated"
Стандартным SplitString(str, ',') тут не обойтись - запятые внутри значений атрибутов все ломают
С TStringList та же хрень
Подумал, может есть в API готовые функции перебора списка атрибутов
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823092
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerПодумал, может есть в API готовые функции перебора списка атрибутовда, есть
курить надо
PCERT_NAME_INFO
PCERT_RDN
PCERT_RDN_ATTR
CertRDNValueToStr
вначале декодировать Subject как X509_UNICODE_NAME
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823096
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talkerполучаю строку Subject таким способом, вопрос в том как распарсить эту строку
CertNameToStr с комбинацией параметров CERT_X500_NAME_STR or CERT_NAME_STR_CRLF_FLAG
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823313
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

Набросал код:
Код: 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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
var
  i: Integer;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  pCertNameInfo: PCERT_NAME_INFO;
  vRDNAttr: PCERT_RDN_ATTR;
  psz: PWideChar;
begin
  // откроем хранилище
  vCertStore := CertOpenSystemStore( 0, PChar( 'MY' ));
  try
    // ищем сертификат
    vCertContext := Cert_FindCertificate_BySHA1(PWideChar( edtSHA1FingerPrint.Text ), vCertStore);
    try
      // декодируем Subject
      if CryptDecodeObject(
        X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
        X509_UNICODE_NAME, //X509_NAME,
        vCertContext.pCertInfo.Subject.pbData,
        vCertContext.pCertInfo.Subject.cbData,
        CRYPT_DECODE_NOCOPY_FLAG,
        nil,
        @cbStructInfo
      )
      then
      begin
        GetMem(pvStructInfo, cbStructInfo);
        try
          CryptDecodeObject(
            X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
            X509_UNICODE_NAME, //X509_NAME,
            vCertContext.pCertInfo.Subject.pbData,
            vCertContext.pCertInfo.Subject.cbData,
            CRYPT_DECODE_NOCOPY_FLAG,
            pvStructInfo,
            @cbStructInfo
          );

          pCertNameInfo := PCERT_NAME_INFO(cbStructInfo);

          // перебираем массив атрибутов Subject-а
          for I := 0 to pCertNameInfo.cRDN-1 do
          begin
            vRDNAttr := pCertNameInfo.rgRDN[i].rgRDNAttr;
            CertRDNValueToStr(vRDNAttr.dwValueType, @(vRDNAttr.Value), nil, size);
            if size > 0 then
            begin
              GetMem(psz, size);
              CertRDNValueToStr(vRDNAttr.dwValueType, @(vRDNAttr.Value), psz, size);
              Memo1.Lines.Append(psz);
            end;
          end;
        finally
          FreeMem(pvStructInfo, cbStructInfo);
        end;
      end;

    finally
      Win32Check( CertFreeCertificateContext( vCertContext ));
    end;
  finally
    Win32Check( CertCloseStore( vCertStore, CERT_CLOSE_STORE_CHECK_FLAG ));
  end;
end;


Не компилируется , останавливается на первом же CryptDecodeObject и говорит - "E2033 Types of actual and formal var parameters must be identical"
Не могу понять где ошибка...
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823343
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

предположу, что vCertContext ^ ...

а может не мучиться ?
Ghost WriterCertNameToStr с комбинацией параметров CERT_X500_NAME_STR or CERT_NAME_STR_CRLF_FLAG
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823368
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

Блин, слона то и не приметил - or CERT_NAME_STR_CRLF_FLAG :))
Так конечно все сильно проще

Хотя, в принципе, хорошо бы понять почему предыдущий вариант не работает...
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823426
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

в JwaWinCrypt у CryptDecodeObject параметр pcbStructInfo: DWORD а не PDWORD, убери @ перед cbStructInfo
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823484
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

Убрал, больше не ругается тут
Ругается на строке
Код: pascal
1.
vRDNAttr := pCertNameInfo.rgRDN[i].rgRDNAttr;

E2016 Array type required
Вроде, по документации это массив
https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/ns-wincrypt-cert_name_info rgRDN - Array of pointers to CERT_RDN structures.
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823505
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

Вот так заработало:
Код: 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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
type
  CERT_RDN_ARRAY = array of CERT_RDN;
var
  i: Integer;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  pCertNameInfo: PCERT_NAME_INFO;
  vRDNAttr: PCERT_RDN_ATTR;
  psz: PWideChar;
  RDNValueSize: DWORD;
begin
  // откроем хранилище
  vCertStore := CertOpenSystemStore( 0, PChar( 'MY' ));
  try
    // ищем сертификат
    vCertContext := Cert_FindCertificate_BySHA1(PWideChar( edtSHA1FingerPrint.Text ), vCertStore);
    try
      // декодируем Subject
      if CryptDecodeObject(
        X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
        X509_UNICODE_NAME, //X509_NAME,
        vCertContext.pCertInfo.Subject.pbData,
        vCertContext.pCertInfo.Subject.cbData,
        CRYPT_DECODE_NOCOPY_FLAG,
        nil,
        cbStructInfo
      )
      then
      begin
        GetMem(pvStructInfo, cbStructInfo);
        try
          CryptDecodeObject(
            X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
            X509_UNICODE_NAME, //X509_NAME,
            vCertContext.pCertInfo.Subject.pbData,
            vCertContext.pCertInfo.Subject.cbData,
            CRYPT_DECODE_NOCOPY_FLAG,
            pvStructInfo,
            cbStructInfo
          );

          pCertNameInfo := PCERT_NAME_INFO(pvStructInfo);

          // перебираем массив атрибутов Subject-а
          for i := 0 to (pCertNameInfo.cRDN-1) do
          begin
            vRDNAttr := CERT_RDN_ARRAY(pCertNameInfo.rgRDN)[i].rgRDNAttr;
            CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, RDNValueSize);
            if RDNValueSize > 0 then
            begin
              GetMem(psz, RDNValueSize);
              CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, psz, RDNValueSize);
              Memo1.Lines.Append(psz);
            end;
          end;
        finally
          FreeMem(pvStructInfo, cbStructInfo);
        end;
      end;

    finally
      Win32Check( CertFreeCertificateContext( vCertContext ));
    end;
  finally
    Win32Check( CertCloseStore( vCertStore, CERT_CLOSE_STORE_CHECK_FLAG ));
  end;
end;


Одно "но" - на выходе получил список ЗНАЧЕНИЙ атрибутов, без их ИМЕН
авторMicrosoft Root Certificate Authority 2011
Microsoft Corporation
Redmond
Washington
US

А имена как получить ?
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823516
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerА имена как получить ?@vRDNAttr.pszObjId + CryptFindOIDInfo
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823532
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-TalkerSQL-Talker,

Вот так заработало:
Код: 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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
type
  CERT_RDN_ARRAY = array of CERT_RDN;
var
  i: Integer;
  pvStructInfo: PVOID;
  cbStructInfo: DWORD;
  pCertNameInfo: PCERT_NAME_INFO;
  vRDNAttr: PCERT_RDN_ATTR;
  psz: PWideChar;
  RDNValueSize: DWORD;
begin
  // откроем хранилище
  vCertStore := CertOpenSystemStore( 0, PChar( 'MY' ));
  try
    // ищем сертификат
    vCertContext := Cert_FindCertificate_BySHA1(PWideChar( edtSHA1FingerPrint.Text ), vCertStore);
    try
      // декодируем Subject
      if CryptDecodeObject(
        X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
        X509_UNICODE_NAME, //X509_NAME,
        vCertContext.pCertInfo.Subject.pbData,
        vCertContext.pCertInfo.Subject.cbData,
        CRYPT_DECODE_NOCOPY_FLAG,
        nil,
        cbStructInfo
      )
      then
      begin
        GetMem(pvStructInfo, cbStructInfo);
        try
          CryptDecodeObject(
            X509_ASN_ENCODING or PKCS_7_ASN_ENCODING,
            X509_UNICODE_NAME, //X509_NAME,
            vCertContext.pCertInfo.Subject.pbData,
            vCertContext.pCertInfo.Subject.cbData,
            CRYPT_DECODE_NOCOPY_FLAG,
            pvStructInfo,
            cbStructInfo
          );

          pCertNameInfo := PCERT_NAME_INFO(pvStructInfo);

          // перебираем массив атрибутов Subject-а
          for i := 0 to (pCertNameInfo.cRDN-1) do
          begin
            vRDNAttr := CERT_RDN_ARRAY(pCertNameInfo.rgRDN)[i].rgRDNAttr;
            CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, nil, RDNValueSize);
            if RDNValueSize > 0 then
            begin
              GetMem(psz, RDNValueSize);
              CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, psz, RDNValueSize);
              Memo1.Lines.Append(psz);
            end;
          end;
        finally
          FreeMem(pvStructInfo, cbStructInfo);
        end;
      end;

    finally
      Win32Check( CertFreeCertificateContext( vCertContext ));
    end;
  finally
    Win32Check( CertCloseStore( vCertStore, CERT_CLOSE_STORE_CHECK_FLAG ));
  end;
end;


Одно "но" - на выходе получил список ЗНАЧЕНИЙ атрибутов, без их ИМЕН
авторMicrosoft Root Certificate Authority 2011
Microsoft Corporation
Redmond
Washington
US

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

Спасибо, увидел
Код: pascal
1.
GetMem(psz, RDNValueSize);
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39823928
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost WriterSQL-TalkerА имена как получить ?@vRDNAttr.pszObjId + CryptFindOIDInfoСделал:
Код: pascal
1.
pInfo := CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, PChar(vRDNAttr.pszObjId), 0);


И так мне думается будет лучше чем вариант с CertNameToStr + CERT_X500_NAME_STR or CERT_NAME_STR_CRLF_FLAG , т.к. тут мы значения получаем в чистом виде - без лишних кавычек, к примеру.
А вариант CertNameToStr + CERT_X500_NAME_STR or CERT_NAME_STR_CRLF_FLAG - если в значении есть кавычки, он их удваивает и все значение оборачивает еще в кавычки. Нужно такие варианты отслеживать, убирать кавычки, т.е. - прилаживать свои костыли, в то время как все уже написано :))
Спасибо.
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39824056
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Только сейчас обратил внимание, CertRDNValueToStr не всегда возвращает мне полное значение
Код: pascal
1.
CertRDNValueToStr(vRDNAttr.dwValueType, @vRDNAttr.Value, psz, RDNValueSize);

У меня в сертификате есть поля "ИНН" и "E" (email) для них возвращется только первый символ и все.
В чем может быть проблема?
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39824068
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Причем, вот:
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39824070
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То есть это атрибут с именем "ИНН" и значение его = "007728551528"
а тут после каждого символа идет #0
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39824097
Ghost Writer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SQL-Talker,

чему равно vRDNAttr.dwValueType ?
попробуй просто CertRDNValueToStr(CERT_RDN_UNICODE_STRING, ...
...
Рейтинг: 0 / 0
CryptoAPI - Как получить все атрибуты поля Subject?
    #39824121
SQL-Talker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ghost Writer,

Помогло ))
А значение vRDNAttr.dwValueType было = 3 ( CERT_RDN_NUMERIC_STRING )
Получается, тип данных vRDNAttr.Value не совпадал с типом указанным в vRDNAttr.dwValueType. Не ожидал такого подвоха
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / CryptoAPI - Как получить все атрибуты поля Subject?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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