Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用CryptoAPI和SignerSign使用附加证书对EXE进行签名_C++_Windows_Winapi_Cryptoapi_Signtool - Fatal编程技术网

C++ 如何使用CryptoAPI和SignerSign使用附加证书对EXE进行签名

C++ 如何使用CryptoAPI和SignerSign使用附加证书对EXE进行签名,c++,windows,winapi,cryptoapi,signtool,C++,Windows,Winapi,Cryptoapi,Signtool,我正在尝试构建一个工具,该工具将根据内核模式代码签名需求对大量文件进行批量签名。我知道signtool可以通过/ac参数为交叉签名信任获取额外的证书,但还没有弄清楚如何使用SignerSign或SignerSignEx来实现这一点。我甚至监视过signtool的API调用,镜像它们似乎不会产生同样的影响 请注意,由于项目限制,signtool或其他命令行实用程序无法用于此目的 有关于如何实现这一点的文档或示例吗?好的,在研究了一段时间后,我终于找到了如何使用交叉证书进行签名的方法。首先,您需要四

我正在尝试构建一个工具,该工具将根据内核模式代码签名需求对大量文件进行批量签名。我知道signtool可以通过/ac参数为交叉签名信任获取额外的证书,但还没有弄清楚如何使用SignerSign或SignerSignEx来实现这一点。我甚至监视过signtool的API调用,镜像它们似乎不会产生同样的影响

请注意,由于项目限制,signtool或其他命令行实用程序无法用于此目的


有关于如何实现这一点的文档或示例吗?

好的,在研究了一段时间后,我终于找到了如何使用交叉证书进行签名的方法。首先,您需要四个或五个证书,具体取决于您的signtool版本,这些证书嵌入到signtool EXE资源的
CERTIFICATE
资源类型下,它们都以
MS
开头。现在,我让我的版本从文件中提取所有证书,因此下面的示例伪代码将解释如何做到这一点。这不仅仅是CryptoAPI调用,而是解释了signtool使用的基本过程。为了简单起见,还省略了所有证书使用验证


//输入:字符串pfx文件路径、字符串交叉证书文件路径、字符串密码、字符串文件到签名
Certificate\u Store signer\u collection=CertOpenStore(CERT\u Store\u PROV\u collection,0,NULL,CERT\u Store\u CREATE\u NEW\u标志,NULL);
Certificate_Store signer_Store=CertOpenStore(CERT_Store_PROV_MEMORY,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,NULL,
证书存储\延迟\关闭\直到最后一次\自由\标志\证书存储\只读\标志,空);
文件pfx\u File=File::open(pifx\u文件路径,通用读取,打开现有);
文件映射pfx\U映射=文件映射::映射(pfx\U文件);
CRYPT_DATA_BLOB pfx_BLOB={pfx_mapping.size(),pfx_mapping.DATA()};
证书\u存储签名者\u pfx=PFXImportCertStore(&pfx\u blob,密码,CRYPT\u用户\u密钥集);
//CertEnumCertificateSinstare
适用于(证书:签名人\u pfx){
signer_store.add(certificate);//CertAddCertificateContextToStore
}
签名者集合。添加(签名者存储);//CertAddStoreToCollection
证书签署人;
用于(证书:签名者\集合){
//假设第一个证书是签名者,则需要更好的验证。
签名者=CertDuplicateCertificateContext(证书);
打破
}
如果(签名者!=NULL){
抛出NoSginerException();
}
证书存储附加集合;
if(交叉证书文件路径!=NULL){
证书存储交叉收集;
证书商店交叉商店;
证书交叉证书=证书::加载(交叉证书文件路径);
//CryptQueryObject(证书查询对象文件、交叉证书文件路径、,
//证书\u查询\u内容\u标志\u证书、证书\u查询\u格式\u标志\u全部,
//0,NULL,NULL,NULL,NULL,NULL,NULL,&交叉证书);
cross\u collection=CertOpenStore(CERT\u STORE\u PROV\u collection,0,NULL,CERT\u STORE\u CREATE\u NEW\u标志,NULL);
交叉集合。添加(签名者集合);
cross_store=CertOpenStore(CERT_store_PROV_内存,PKCS_7_ASN_编码,X509_ASN_编码,空,
证书存储\延迟\关闭\直到最后一次\自由\标志\证书存储\只读\标志,空);
交叉存储。添加(交叉证书);
交叉收集。添加(交叉存储);
证书存储ms_root_Store=CertOpenStore(sz_CERT_Store_PROV_MEMORY,0,NULL,
证书存储(创建)(新)标志|证书存储(延迟)(关闭)(直到)最后(自由)标志(空));
//这是从MS代码验证根中收集嵌入式证书的地方。
对于(资源资源:Program_Resources::Resources_下的(“证书”){//EnumResourceNames,Find/Load/Lock |资源
Certificate=Certificate::from_blob(resource.size(),resource.data());
//CERT_BLOB BLOB={resource.size(),resources.data()};
//CryptQueryObject(证书、查询和对象),
//证书查询内容标志证书查询内容标志序列化证书,
//证书\查询\格式\标志\全部,0,空,空,空,空,空,空,
//证书);
ms_root_store.add(证书);
}
交叉收集。添加(证书);
静态常量DWORD链\标志=证书\链\禁用\传递1 \质量\过滤|
证书\u链\u返回\u质量较低\u上下文|
证书\链\撤销\检查\链\排除\根;
静态常数CERT_CHAIN_PARA CHAIN_PARAMS={sizeof(CERT_CHAIN_PARA)};
Certificate\u Chain=Certificate\u Chain::get(HCCE\u LOCAL\u机器,签名者,NULL,
交叉集合和链参数,链标志,NULL);
//CertGetCertificateCain(HCCE_本地_机器,签名者,空,
//交叉集合和链参数、链标志、NULL和链);
Certificate\u Store additional\u Store=CertOpenStore(CERT\u Store\u PROV\u MEMORY,
PKCS_7_ASN_编码| X509_ASN_编码,NULL,证书存储_延迟_关闭_直到最后一个自由标志|
证书存储区只读标志,空);
对于(DWORD l=0;l!=链->cLowerQualityChainContext;++l){
PCCERT_CHAIN_CONTEXT low_CHAIN=pChain->rgpLowerQualityChainContext[l];
对于(DWORD c=0;c!=低链->链;++c){
PCERT_SIMPLE_CHAIN SIMPLE_CHAIN=低链->rgpChain[c];
对于(DWORD e=0;e!=简单链->加速;++e){
PCERT_CHAIN_ELEMENT=simple_CHAIN->rgpElement[e];
添加(元素->pCertContext);
}
}
}
附加集合=CertOpenStore(CERT\u STORE\u PROV\u collection,0,NULL,CERT\u STORE\u CREATE\u NEW\u标志,NULL);
附加集合。添加(附加存储);
}
签名者\文件\信息文件\信息={sizeof(签名者\文件\信息)};
file_info.pwszFileName=要签名的文件;
德沃德指数=0;
签名者主题信息主题信息={sizeof(签名者主题信息)};
subject_info.pdwIndex=&index;
subject\u info.dwSubjectChoice=签名者\u subject\u文件;
受试者信息
// inputs: string pfx_file_path, string cross_cert_file_path, string password, string file_to_sign

Certificate_Store signer_collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
Certificate_Store signer_store = CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL,
    CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_STORE_READONLY_FLAG, NULL);

File pfx_file = File::open(pifx_file_path, GENERIC_READ, OPEN_EXISTING);
File_Mapping<BYTE> pfx_mapping = File_Mapping<BYTE>::map(pfx_file);

CRYPT_DATA_BLOB pfx_blob = { pfx_mapping.size(), pfx_mapping.data() };
Certificate_Store signer_pfx = PFXImportCertStore(&pfx_blob, password, CRYPT_USER_KEYSET);

// CertEnumCertificatesInStore
for (Certificate certificate: signer_pfx) {
    signer_store.add(certificate); // CertAddCertificateContextToStore
}

signer_collection.add(signer_store); // CertAddStoreToCollection

Certificate signer;
for (Certificate certificate: signer_collection) {
    // Assumes first certificate is the signer, need better validation.
    signer = CertDuplicateCertificateContext(certificate);
    break;
}

if (signer != NULL) {
    throw NoSginerException();
}

Certificate_Store additional_collection;
if (cross_cert_file_path != NULL) {
    Certificate_Store cross_collection;
    Certificate_Store cross_store;

    Certificate cross_certificate = Certificate::load(cross_cert_file_path);
    // CryptQueryObject(CERT_QUERY_OBJECT_FILE, cross_cert_file_path, 
    //  CERT_QUERY_CONTENT_FLAG_CERT, CERT_QUERY_FORMAT_FLAG_ALL,
    //  0, NULL, NULL, NULL, NULL, NULL, &cross_certificate);

    cross_collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
    cross_collection.add(signer_collection);

    cross_store = CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL,
        CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG | CERT_STORE_READONLY_FLAG, NULL);
    cross_store.add(cross_certificate);
    cross_collection.add(cross_store);

    Certificate_Store ms_root_store = CertOpenStore(sz_CERT_STORE_PROV_MEMORY, 0, NULL,
        CERT_STORE_CREATE_NEW_FLAG | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL);
    // This is where the embedded certificates from the MS Code Validation roots are collectioned.
    for (Resource resource: Program_Resources::resources_under("CERTIFICATE")) { // EnumResourceNames, Find/Load/Lock|Resource
        Certificate certificate = Certificate::from_blob(resource.size(), resource.data());
        // CERT_BLOB blob = { resource.size(), resources.data() };
        // CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 
        //  CERT_QUERY_CONTENT_FLAG_CERT | CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT,
        //  CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, NULL, NULL, NULL,
        //  &certificate);
        ms_root_store.add(certificate);
    }

    cross_collection.add(certificate);

    static const DWORD CHAIN_FLAGS = CERT_CHAIN_DISABLE_PASS1_QUALITY_FILTERING |
        CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS |
        CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
    static const CERT_CHAIN_PARA CHAIN_PARAMS = { sizeof(CERT_CHAIN_PARA) };
    Certificate_Chain chain = Certificate_Chain::get(HCCE_LOCAL_MACHINE, signer, NULL,
        cross_collection, &CHAIN_PARAMS, CHAIN_FLAGS, NULL);
    // CertGetCertificateChain(HCCE_LOCAL_MACHINE, signer, NULL,
    //  cross_collection, &CHAIN_PARAMS, CHAIN_FLAGS, NULL, &chain);

    Certificate_Store additional_store = CertOpenStore(CERT_STORE_PROV_MEMORY,
        PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, NULL, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG |
        CERT_STORE_READONLY_FLAG, NULL);
    for (DWORD l = 0; l != chain->cLowerQualityChainContext; ++l) {
        PCCERT_CHAIN_CONTEXT low_chain = pChain->rgpLowerQualityChainContext[l];
        for (DWORD c = 0; c != low_chain->cChain; ++c) {
            PCERT_SIMPLE_CHAIN simple_chain = low_chain->rgpChain[c];
            for (DWORD e = 0; e != simple_chain->cElement; ++e) {
                PCERT_CHAIN_ELEMENT element = simple_chain->rgpElement[e];
                additional_store.add(element->pCertContext);
            }
        }
    }

    additional_collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
    additional_collection.add(additional_store);
}

SIGNER_FILE_INFO file_info = { sizeof(SIGNER_FILE_INFO) };
file_info.pwszFileName = file_to_sign;

DWORD index = 0;
SIGNER_SUBJECT_INFO subject_info = { sizeof(SIGNER_SUBJECT_INFO) };
subject_info.pdwIndex = &index;
subject_info.dwSubjectChoice = SIGNER_SUBJECT_FILE;
subject_info.pSignerFileInfo = &file_info;

SIGNER_CERT_STORE_INFO store_info = { sizeof(SIGNER_CERT_STORE_INFO) };
store_info.dwCertPolicy = SIGNER_CERT_POLICY_STORE;
store_info.pSigningCert = signer;
store_info.hCertStore = additional_collection;

SIGNER_CERT cert_info = { sizeof(SIGNER_CERT) };
cert_info.dwCertChoice = SIGNER_CERT_STORE;
cert_info.pCertStoreInfo = &store_info;

SIGNER_ATTR_AUTHCODE authcode_attr = { sizeof(SIGNER_ATTR_AUTHCODE) };

SIGNER_SIGNATURE_INFO signature_info = { sizeof(SIGNER_SIGNATURE_INFO) };
signature_info.algidHash = CALG_SHA;
signature_info.dwAttrChoice = SIGNER_AUTHCODE_ATTR;
signature_info.pAttrAuthcode = &authcode_attr;

SIGNER_PROVIDER_INFO provider_info = { sizeof(SIGNER_PROVIDER_INFO) };
provider_info.pwszProviderName = L"";
provider_info.dwPvkChoice = PVK_TYPE_KEYCONTAINER;
provider_info.pwszKeyContainer = L"";

HRESULT hr = SignerSign(&subject_info, &cert_info, &signature_info, &provider_info, NULL, NULL, NULL);