CryptoAPI RSA Schannel 提供商错误

CryptoAPI RSA Schannel Provider error

我正在尝试使用 "Microsoft RSA SChannel Cryptographic Provider" 生成数字签名。获取容器句柄后,我使用 CryptGenKey() 生成签名。但是这个函数returns FALSE。

CryptGenKey() 的 dwError returns80090008。

同样适用于任何其他提供程序类型。此外,当我尝试为同一提供商创建密钥交换对时,它工作正常。我做错了什么?

#include <Windows.h>
#include <wincrypt.h>

int main()
{
    HCRYPTPROV phProv = 0;
    LPTSTR pszContainer = NULL;
    DWORD dwFlags = 0;
    bool flag;
    DWORD_PTR dwError;
    HCRYPTKEY phKey;

    flag = CryptAcquireContext(&phProv, pszContainer,
        MS_DEF_RSA_SCHANNEL_PROV, PROV_RSA_SCHANNEL, dwFlags);
    if (!flag)
    {
        flag = CryptAcquireContext(&phProv, pszContainer,
            MS_DEF_RSA_SCHANNEL_PROV, PROV_RSA_SCHANNEL, CRYPT_NEWKEYSET);
    }
    dwError = GetLastError();

    flag = CryptGenKey(phProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &phKey);
    dwError = GetLastError();

    flag = CryptGetUserKey(phProv, AT_SIGNATURE, &phKey);
    dwError = GetLastError();

    return 0;
}

谢谢。

SChannel 提供商不支持 AT_SIGNATURE RSA 密钥,仅支持 AT_EXCHANGE。这主要是早期 TLS(当时还是 SSL)的遗留问题,当时使用 RSA 加密交换密钥,而不是使用 RSA 签名签署的 Diffie-Hellman 密钥协议达成一致……然后,大概 "well, everybody knows how the SChannel provider behaves, why change it?"。 (我看到最接近的是 https://msdn.microsoft.com/en-us/library/windows/desktop/aa387690(v=vs.85).aspx,它显示 CALG_RSA_KEYX 而没有谈论 CALG_RSA_SIGN。)

在 CAPI 中,一个 AT_EXCHANGE 密钥可以同时加密和签名,而一个 AT_SIGNATURE 密钥只能进行签名。

总的来说,Windows 密码学团队不鼓励用 C 编写新代码API(除了我刚刚写的,我没有其他书面证据;主要是来自与他们)。 CNG 对开发人员更友好 API,并且功能更强大。 CNG 在 Windows Vista 中重新运回,因此它在每个支持的 Windows 版本中都可用。 CAPI 不再服务于 "well, it has more coverage" 的目的,它只是 "the old, crufty, legacy API"(除非您正在为不受支持的操作系统编写代码,例如 XP)。

如果您使用的是 CAPI,我不知道您为什么要使用 SChannel 提供程序。 PROV_RSA_AES via MS_ENH_RSA_AES_PROV 是 CAPI 拥有的功能最强大的 RSA(基于 SHA-2 的 PKCS 签名)。但与 CNG 中的软件提供商相比,它已经过时了(PSS 签名,带有 SHA-2 的 OAEP,并支持大于 2^32 的 public 指数值(好吧,这不是常见的需求,但它是 CNG 固定的东西)).