Windows CryptoAPI:CryptSignHash与CALG_SHA_256和私钥从我的密钥库 [英] Windows CryptoAPI: CryptSignHash with CALG_SHA_256 and private key from MY keystore

查看:4287
本文介绍了Windows CryptoAPI:CryptSignHash与CALG_SHA_256和私钥从我的密钥库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Windows上生成数字签名(从XP SP3,但目前正在测试与Windows 7)与CryptoAPI将与以下openssl命令兼容:

I am trying to generate digital signatures on Windows (from XP SP3, but currently testing with Windows 7) with CryptoAPI that will be compatible with the following openssl commands:

openssl dgst -sha256 -sign <parameters> (for signing)
openssl dgst -sha256 -verify <parameters> (for validation)



我想使用WindowsMY密钥库中的私钥进行签名。

I want to use a private key from the Windows "MY" keystore for signing.

我设法使用SHA1摘要算法,通过使用以下CryptoAPI函数(省略参数为简洁)签名文件:

I managed to sign files using the SHA1 digest algorithm by using the following CryptoAPI functions (omitting parameters for brevity):

CertOpenStore
CertFindCertificateInStore
CryptAcquireCertificatePrivateKey
CryptCreateHash (with CALG_SHA1)
CryptHashData
CryptSignHash

生成的签名与openssl dgst -sha1 -verify兼容(一旦字节顺序颠倒)。

The generated signature is compatible with "openssl dgst -sha1 -verify" (once the byte order is reversed).

我的问题是:当我尝试使用CALG_SHA_256与CryptCreateHash,它失败,错误80090008(NTE_BAD_ALGID)。 Googling 周围,我发现我需要使用特定的提供程序(PROV_RSA_AES)而不是默认的提供程序。由于我将有一个提供者句柄,我还需要替换CryptAcquireCertificatePrivateKey通过CryptGetUserKey。所以我修改了我的程序看起来像:

My problem is: when I try to use CALG_SHA_256 with CryptCreateHash, it fails with error 80090008 (NTE_BAD_ALGID). By googling around, I found that I needed to use a specific provider (PROV_RSA_AES) instead of the default one. Since I would have a provider handle, I would also need to replace CryptAcquireCertificatePrivateKey by CryptGetUserKey. So I modified my program to look like:

CryptAcquireContext (with PROV_RSA_AES)
CertOpenStore
CertFindCertificateInStore
CryptGetUserKey
CryptCreateHash (with CALG_SHA256)
CryptHashData
CryptSignHash

不幸的是,这没有按预期工作:CryptGetUserKey失败,错误8009000D(NTE_NO_KEY)。如果我删除CryptGetUserKey调用,程序运行,直到CryptSignHash,失败,错误80090016(NTE_BAD_KEYSET)。我知道密钥集确实存在和工作正常,因为我能够使用它签名SHA1摘要。

Unfortunately, this didn't work as expected: CryptGetUserKey failed with error 8009000D (NTE_NO_KEY). If I remove the CryptGetUserKey call, the program runs until CryptSignHash, which fails with error 80090016 (NTE_BAD_KEYSET). I know the keyset does exist and works fine, since I was able to use it to sign the SHA1 digest.

我试图从证书上下文中的信息再次获取上下文我从CertFindCertificateInStore获得:我能做的最好的是一个成功的CryptGetUserKey调用,但CryptSignHash总是会失败,同样的错误。

I tried acquiring the context again with information from the certificate context I got from CertFindCertificateInStore: the best I could do was a successful CryptGetUserKey call, but CryptSignHash would always fail with the same error.

我想使用的私钥是2048位长,但我不希望它是一个问题,因为它与SHA1摘要一起工作。

The private key I am trying to use is 2048 bits long, but I don't expect it to be a problem since it works with the SHA1 digest. I am at a loss, so any suggestion would be very welcome!

推荐答案

问题最可能是Windows上的证书知道哪个提供商其私钥被存储。当您导入您的证书时,它会把密钥放入某个提供者类型(可能是PROV_RSA_FULL),当您以后尝试通过证书访问密钥时,它可能会在同一提供程序类型。

The problem is most likely to be that certificates on Windows "know" in which provider their private keys are stored. When you import your cert it would put the key into a certain provider type (probably PROV_RSA_FULL), when you then later try to access the key via the certificate it will probably end up in the same provider type.

您可能需要打开证书的相关上下文(请查看 CertGetCertificateContextProperty 与CERT_KEY_PROV_HANDLE_PROP_ID选项)。
使用该句柄,您可以尝试从原始提供者上下文导出密钥,并重新导入一个新的PROV_RSA_AES密钥(假设密钥可导出)。

You probably need to open the associated context for the certificate (have a look at CertGetCertificateContextProperty with the CERT_KEY_PROV_HANDLE_PROP_ID option). With that handle yyou could try exporting the key from the original provider context and reimporting into a new PROV_RSA_AES one (assuming the key is exportable).

这篇关于Windows CryptoAPI:CryptSignHash与CALG_SHA_256和私钥从我的密钥库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆