【问题标题】:Using primitive function with key stored in Microsoft KSP将原始函数与存储在 Microsoft KSP 中的密钥一起使用
【发布时间】:2015-01-23 15:26:35
【问题描述】:

我的问题是关于 CNG API 和 Microsoft 提供商的用例。我不编写代码示例是因为我寻求您的帮助,了解与 CSP API 相比,在我的应用程序中使用 CNG API 的最佳方式。

我构建了一个应用程序,它使用通过以下步骤存储的对称密钥:

  • 使用 CertFindCertificateInStore 枚举“我的”存储中的证书
  • 对于找到的每个证书,使用 CertGetCertificateContextProperty 询问私钥信息
  • 对于找到的每个私钥信息,存储提供者名称 pwszProvName 和容器名称 pwszContainerName

然后,当找到密钥时,我的应用程序使用通过 CSP API 找到的私钥执行签名功能:

  • 使用带有 pwszProvNamepwszContainerNameCryptAcquireContext 初始化提供程序操作
  • 使用 CSP 函数计算签名:CryptCreateHashCryptHashDataCryptSignHash

CSP 功能一切正常。

现在我尝试使用 CNG API 进行签名操作:

  • 使用 NCryptOpenStorageProviderpwszProvName 初始化提供程序操作
  • 使用 CNG 函数 BCryptOpenAlgorithmProvider 的打开算法提供程序失败并显示 STATUS_NOT_FOUND

当私钥存储在 Microsoft Software Key Storage Provider 中时会发生此错误。 阅读 Microsoft 文档,我了解提供程序的类型是 KSP 提供程序,并且仅对密钥管理起作用。这就是为什么当我尝试原始函数时它失败的原因,我需要使用“原始提供者”。

我找到了按照这些设置使用 CNG 提供程序的方法:

  • Windows Server 2008:创建具有提供程序要求的证书模板(在“加密”选项卡上)。唯一可用的提供商是“Microsoft Software Key Storage Provider
  • Windows 7:用户要求生成密钥,密钥存储在 Microsoft KSP 中。

所以这是我的问题:

  • 我无法使用“Microsoft Software Key Storage Provider”执行原始功能正常吗?

  • 如果我无法使用 Microsoft KSP(它是 KSP 提供程序)执行原始功能(签名、加密、解密、散列),我如何使我的私钥在 Microsoft Primitive Provider 中存储和管理?

我的麻烦在于,使用 CSP API,默认的 Microsoft CSP 提供程序执行签名(以及解密、加密等)功能。但是使用 CNG API,默认提供程序只执行密钥存储管理。

【问题讨论】:

    标签: c++ certificate key cng


    【解决方案1】:

    对于非对称密钥,CNG 密钥存储提供程序支持的功能与原始提供程序相当,当然 KSP(密钥存储提供程序)允许您持久化和加载密钥这一事实除外。

    事实上,用于执行加密操作的 KSP API 调用看起来与原始的很相似,除了 KSP 的以N 开头,而原始的以B 开头。

    例如:

    KSP 中缺少的 是对称功能(包括散列),这可能是引起混淆的地方。与 CAPI (CSP/Crypto API) 相比,CNG 签名函数更底层一些 - 你首先单独散列数据,然后将该散列字节块传递给NCryptSignHash(没有像 CAPI 中那样的散列对象句柄)。

    重申一下,因为这会使来自 CAPI 的人感到困惑,您可以使用任何原始提供者 MS_PRIMITIVE_PROVIDER 或第三方提供者进行哈希处理,然后将结果传递给任何密钥存储提供者的 @ 987654328@,因为它只是字节数据,谁做散列并不重要。传递给NCryptSignHashNCRYPT_KEY_HANDLE 决定了使用什么KSP 进行签名;没有 CNG 等效于 HCRYPTHASH 传递给 NCryptSignHash

    因此,如果您想使用 KSP 签名,您应该首先使用原始提供者(使用 BCryptCreateHash/BCryptHashData/BCryptFinishHash)对要签名的消息进行哈希处理,并将结果传递给 NCryptSignHash .

    【讨论】:

    • 感谢您的回答@softwariness 我了解在使用 NCryptSignHash 签署数据之前,我需要使用 BCryptCreateHash / BCryptHashData 对数据进行哈希处理 / BCryptFinishHash。但要执行这些 BCryptXXX 功能,我需要使用 BCryptOpenAlgorithmProvider 和存储我的密钥的提供程序名称开始获取提供程序(此处为 Microsoft KSP)。这会因 STATUS_NOT_FOUND 而失败。那么,我应该为提供者名称获取带有 NULL 的默认提供者并执行散列函数吗?因为,有了 CSP Microsoft 提供程序,我可以要求它对数据进行哈希处理,无需使用其他提供程序。
    • 是的,提供 NULL 以使用默认提供程序,或者您可以在使用 BCryptXXX 函数时显式指定 MS_PRIMITIVE_PROVIDER。例如,如果您查看 NCryptSignHash 的文档,您会注意到它需要一个缓冲区来存储哈希数据,而不是像等效的 CSP 函数那样的句柄,因此您没有使用相同的哈希值并不重要提供者。
    • 好的,我明白了。与我们向存储密钥的提供者询问哈希函数的 CSP API 相比,她使用 CNG API,我们要求默认提供者执行此操作。这是一个很大的实施变化。我没有注意到 Microsoft 文档中的详细信息。
    • 我已经更新了我的答案,以重申并澄清这一点。这是否涵盖了您在问题中需要的所有内容?
    猜你喜欢
    • 1970-01-01
    • 2011-01-13
    • 2018-02-22
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多