0

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

CryptGenKey() 的 dwError 返回 80090008。

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

#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;
}

谢谢。

4

1 回答 1

1

SChannel 提供程序不支持AT_SIGNATURERSA 密钥,仅支持AT_EXCHANGE. 它主要是早期 TLS(当时还是 SSL)的保留,当时使用 RSA 加密交换密钥,而不是同意使用用 RSA 签名签署的 Diffie-Hellman 密钥协议......然后,大概“好吧,每个人都知道如何SChannel 提供者的行为,为什么要改变它?”。(我看到的最接近被写下来的是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 密码学团队不鼓励使用 CAPI 编写新代码(除了我刚刚编写的内容之外,我没有其他书面证据;主要是因为与他们会面)。CNG 具有对开发人员更友好的 API,并且功能更强大。CNG 在 Windows Vista 中重新发布,因此它在每个受支持的 Windows 版本中都可用。CAPI 不再服务于“好吧,它有更多的覆盖范围”的目的,它只是“旧的、粗糙的、遗留的 API”(除非你正在为不受支持的操作系统编写代码,比如 XP)。

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

于 2017-07-21T15:35:48.733 回答