Аутентификация Windows API получить корневой сертификат

Я хочу пройти по цепочке сертификатов двоичного файла PE, подписанного с помощью аутентификации, с помощью Windows API.

Чтобы получить хранилище сертификатов, я последовал примеру Microsoft:
https://support.microsoft.com/en-us/help/323809/how-to-get-information-from-authenticode-подписанныеисполняемыефайлы
При этом я получаю листовой сертификат и промежуточный сертификат, но не корневой сертификат. Протестировано с различными бинарными файлами Windows (например, explorer.exe)
Я попробовал следующие циклы для обхода хранилища:

while (pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_ANY, NULL, pCertContext));
while (pCertContext = CertEnumCertificatesInStore(hStore, pCertContext));

Корневой сертификат не включен в подпись аутентификации?
Я пропустил какую-то опцию?


person user2369952    schedule 16.07.2018    source источник
comment
корневой сертификат может находиться в другом хранилище   -  person RbMm    schedule 16.07.2018
comment
спасибо RbMm, вы имеете в виду системный магазин? Вы знаете, как я могу найти соответствующий корневой сертификат?   -  person user2369952    schedule 16.07.2018
comment
почему бы не использовать CertGetCertificateChain   -  person RbMm    schedule 16.07.2018
comment
Спасибо, это все. Сначала найдите конечный сертификат, затем постройте цепочку с CertGetCertificateChain. Вы можете найти pCertContext в pChainContext->rgpChain[0]->rgpElement[i]->pCertContext   -  person user2369952    schedule 16.07.2018


Ответы (1)


Спасибо @RbMm за ваше предложение с CertGetCertificateChain, которое решает мой вопрос.
Чтобы получить всю цепочку, нужно начать с листового сертификата (складировать швы для начала сверху вниз).

Адаптировано из https://docs.microsoft.com/de-de/windows/desktop/SecCrypto/example-c-program-creating-a-certificate-chain:

CERT_INFO CertInfo;

CertInfo.Issuer = pSignerInfo->Issuer;
CertInfo.SerialNumber = pSignerInfo->SerialNumber;

pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&CertInfo, NULL);
if (!pCertContext) {
    _tprintf(_T("CertFindCertificateInStore failed with %x\n"), GetLastError());
    __leave;
}

CERT_ENHKEY_USAGE        EnhkeyUsage;
CERT_USAGE_MATCH         CertUsage;
CERT_CHAIN_PARA          ChainPara;

EnhkeyUsage.cUsageIdentifier = 0;
EnhkeyUsage.rgpszUsageIdentifier = NULL;
CertUsage.dwType = USAGE_MATCH_TYPE_AND;
CertUsage.Usage = EnhkeyUsage;
ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
ChainPara.RequestedUsage = CertUsage;

if (!CertGetCertificateChain(
    NULL,                  // use the default chain engine
    pCertContext,          // pointer to the end certificate
    NULL,                  // use the default time
    NULL,                  // search no additional stores
    &ChainPara,            // use AND logic and enhanced key usage 
                           //  as indicated in the ChainPara 
                           //  data structure
    dwFlags,
    NULL,                  // currently reserved
    &pChainContext)) {
    cerr << "Error on CertGetCertificateChain" << endl;
    __leave;
}

PCERT_SIMPLE_CHAIN    rgpChain   = NULL;
PCERT_CHAIN_ELEMENT   rgpElement = NULL;

rgpChain = pChainContext->rgpChain[0];

for (int j = 0; j < rgpChain->cElement; j++) {
    rgpElement = rgpChain->rgpElement[j];
    PrintCertificateInfo(rgpElement->pCertContext);
    cout << endl;
}
person user2369952    schedule 16.07.2018