You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CryptAcquireContext返回“密钥集不存在”及NCrypt相关问题求助

问题:CryptAcquireContext返回“Keyset does not exist”且NGC获取证书属性失败

问题现象

  • 调用CryptAcquireContext(...)获取PROV_RSA_FULL类型加密服务提供程序(CSP)的加密上下文时,始终返回错误,最后错误为Keyset does not exist
  • 枚举到4个PROV_RSA_FULL类型CSP:
    • Microsoft Base Cryptographic Provider v1.0
    • Microsoft Base Smart Card Crypto Provider
    • Microsoft Enhanced Cryptographic Provider v1.0
    • Microsoft Strong Cryptographic Provider
  • 调试输出显示每个CSP均报相同错误
  • 使用NGC的NCryptGetProperty获取NCRYPT_CERTIFICATE_PROPERTY时返回NTE_NOT_FOUND
  • 个人存储中有自签名证书,其他代码可正常获取该证书的属性、扩展属性及公钥

调试输出

CSP: Microsoft Base Cryptographic Provider v1.0
is a PROV_RSA_FULL type provider
Keyset does not exist
...
CSP: Microsoft Base Smart Card Crypto Provider
is a PROV_RSA_FULL type provider
Keyset does not exist
...
CSP: Microsoft Enhanced Cryptographic Provider v1.0
is a PROV_RSA_FULL type provider
Keyset does not exist
...
CSP: Microsoft Strong Cryptographic Provider
is a PROV_RSA_FULL type provider
Keyset does not exist

相关代码

void main()
{
    //-------------------------------------------------------------------
    // Declare and initialize variables. This includes getting a pointer 
    // to the message to be encrypted. This code creates a message
    // and gets a pointer to it. In reality, the message content 
    // usually exists somewhere and a pointer to the message is 
    // passed to the application. 

    BYTE* pbContent = (BYTE*)"Security is our business.";
    // The message
    DWORD cbContent = strlen((char*)pbContent) + 1;
    // Size of message
    HCRYPTPROV hCryptProv;                      // CSP handle
    HCERTSTORE hStoreHandle;
    PCCERT_CONTEXT pRecipientCert;
    PCCERT_CONTEXT RecipientCertArray[1];
    DWORD EncryptAlgSize;
    CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
    CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
    DWORD EncryptParamsSize;
    BYTE* pbEncryptedBlob;
    DWORD    cbEncryptedBlob;

    //-------------------------------------------------------------------
    //  Begin processing.

    printf("About to begin with the message %s.\n", pbContent);
    printf("The message length is %d bytes. \n", cbContent);


    DWORD cbName=0;
    DWORD dwType=0;
    DWORD dwIndex = 0;
    LPWSTR pszName;
    DWORD pdwProvType;
    DWORD pcbProvName;
    

    // Loop through enumerating providers.
    while(CryptEnumProvidersW(
        dwIndex,
        NULL,
        0,
        &pdwProvType,
        NULL,
        &pcbProvName
    ))
    {
        //-----------------------------------------------------------
        // cbName is the length of the name of the next provider 
        // type.

        // Allocate memory in a buffer to retrieve that name.
        if (!(pszName = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, pcbProvName)))
        {
            MyHandleError((char*)std::string::basic_string("ERROR LocalAlloc failed!\n").c_str());
        }

        //-----------------------------------------------------------
        // Get the provider type name.

        if (CryptEnumProvidersW(
            dwIndex++,
            NULL,
            0,
            &pdwProvType,
            pszName,
            &pcbProvName
        ))
        {
            std::wostringstream os;
            os << "CSP: " << pszName << "\n";
            OutputDebugString(os.str().c_str());
            printf("     %4.0d        %ls\n",dwType, pszName);
            if (pdwProvType==PROV_RSA_FULL)
            {
                std::wstring s(L"is a PROV_RSA_FULL type provider");
                OutputDebugString(s.c_str()); 
                //MS_DEF_PROV
            }
        }
        else
        {
           MyHandleError((char*) std::string::basic_string("ERROR CryptEnumProviders.\n").c_str());
        }


        //-------------------------------------------------------------------
        // Get a handle to a cryptographic provider.

        if (CryptAcquireContext(
            &hCryptProv,        // Address for handle to be returned.
            NULL,               // Use the current user's logon name.
            pszName,            // Use the default provider.
            PROV_RSA_FULL,      // Need to both encrypt and sign.
            NULL))              // No flags needed.
        {
            printf("A CSP has been acquired \n");
            break;
        }
        else
        {
            DWORD e = GetLastError();
            std::wstring ermsg = getErrorMsg();
            OutputDebugString(ermsg.c_str());
            std::wostringstream os;
            os << "Cryptographic context could not be acquired, the default container not found.\n";
            OutputDebugString(os.str().c_str());

             // No default container was found. Attempt to create it.
            if (CryptAcquireContext(
                &hCryptProv,
                NULL,
                NULL,
                PROV_RSA_FULL,
                CRYPT_NEWKEYSET))
            {
                std::wostringstream os;
                os << "A PROV_RSA_FULL CSP has been acquired \n";
                OutputDebugString(os.str().c_str());
                AcquiredCryptographicContext = TRUE;
                //break;
            }
            else
            {
                DWORD e = GetLastError();
                std::wstring ermsg = getErrorMsg();
                OutputDebugString(ermsg.c_str());
                MyHandleError((char*)std::string::basic_string("Could not create the default key container.\n").c_str());
            }

    if (hCryptProv != NULL)
    {
        if (!CryptReleaseContext(
            hCryptProv,
            0))
        {
            MyHandleError((char*)std::string::basic_string("FAILED To RELEASE CryptoContext.\n").c_str());
        }
    }
    if(pszName!=NULL)
    {
       LocalFree(pszName);
    }
    }
}

疑问

  • 已知CryptAcquireContext是已弃用API,但NGC也出现类似获取失败问题,是否存在系统配置问题导致两个API同时失效?
  • 如何结合个人存储中的自签名证书成功获取加密上下文以进行消息加密?

内容的提问来源于stack exchange,提问作者John Rainey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:54:51