首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RSACryptoServiceProvider vs RSACng

RSACryptoServiceProvider vs RSACng
EN

Stack Overflow用户
提问于 2020-04-17 23:59:18
回答 2查看 1.2K关注 0票数 1

我有使用RSACryptoServiceProvider创建的(不可导出的)密钥。我想使用RSA-PSS (不是RSACryptoServiceProvider)来签署数据。因此,我希望获得与RSACng实例相同的私钥。

我尝试了以下几种方法:

代码语言:javascript
复制
// Create key with RSACryptoServiceProvider
var keyId = Guid.NewGuid().ToString();
var providerName = "Microsoft Enhanced RSA and AES Cryptographic Provider";
var key = new RSACryptoServiceProvider(2048, new CspParameters(24) {
  ProviderName = providerName,
  KeyContainerName = keyId,
  KeyNumber = (int) KeyNumber.Signature,
  Flags = CspProviderFlags.UseNonExportableKey
});

// Obtain an RSACng reference:
var cngKey = CngKey.Open(keyId, new CngProvider(providerName));
var cngRsaKey = new RSACng(cngKey);

// Sign something using cngRsaKey
[...]

不幸的是,当使用WindowsCryptographicException: Keyset does not exist执行CngKey.Open时,它总是失败。

如何使用RSACng打开之前创建的密钥?

请注意,我不能使用https://stackoverflow.com/a/50703729/1400869提供的答案,因为我不能使用可导出的私钥。最后,密钥应该驻留在HSM (硬件安全模块)上。

有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-21 00:36:18

显然,CngKey.Open不适用于Signature插槽中的CAPI RSA密钥(因为它将dwLegacyKeySpec值硬编码为0)。最简单的解决方法是使用Exchange插槽;但如果您需要使用签名插槽密钥,您可以:

代码语言:javascript
复制
[DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
private static extern int NCryptOpenStorageProvider(
    out SafeNCryptProviderHandle phProvider,
    string pszProviderName,
    int dwFlags);

[DllImport("ncrypt.dll", CharSet = CharSet.Unicode)]
private static extern int NCryptOpenKey(
    SafeNCryptProviderHandle hProvider,
    out SafeNCryptKeyHandle phKey,
    string pszKeyName,
    int dwLegacyKeySpec,
    CngKeyOpenOptions dwFlags);

private static void Test61275795()
{
    const string KeyId = "test-982375";

    CspParameters cspParams = new CspParameters(24)
    {
        ProviderName = "Microsoft Enhanced RSA and AES Cryptographic Provider",
        KeyContainerName = KeyId,
        KeyNumber = (int)KeyNumber.Signature,
        Flags = CspProviderFlags.UseNonExportableKey,
    };

    using (RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(2048, cspParams))
    {
        // Because this is a test, delete the key on Dispose.
        rsaCsp.PersistKeyInCsp = false;

        SafeNCryptKeyHandle hKey;

        int dwError = NCryptOpenStorageProvider(out var hProv, cspParams.ProviderName, 0);

        using (hProv)
        {
            if (dwError != 0)
            {
                throw new CryptographicException(
                    $"{nameof(NCryptOpenStorageProvider)}: 0x{dwError:X8}");
            }

            dwError = NCryptOpenKey(hProv, out hKey, KeyId, cspParams.KeyNumber, 0);

            if (dwError != 0)
            {
                hKey.Dispose();
                throw new CryptographicException($"{nameof(NCryptOpenKey)}: 0x{dwError:X8}");
            }
        }

        using (hKey)
        using (CngKey cngKey = CngKey.Open(hKey, 0))
        using (RSACng rsaCng = new RSACng(cngKey))
        {
            byte[] sig = rsaCng.SignData(
                Array.Empty<byte>(),
                HashAlgorithmName.SHA256,
                RSASignaturePadding.Pss);

            Console.WriteLine(BitConverter.ToString(sig));
        }
    }
}
票数 3
EN

Stack Overflow用户

发布于 2020-04-19 20:19:05

有一个名为"CngLightup“的过程,它允许用户获取对使用RSACryptoServiceProvider创建的密钥的RSACng引用。它被微软使用,例如,在他们的清单签名的实现中:https://github.com/microsoft/referencesource/blob/master/inc/mansign2.cs#L1426

这要求您手中有一个证书,而不仅仅是一个密钥引用。但是使用手边的密钥创建一个虚拟的自签名证书是很容易的,然后调用CngLightup.GetRSAPrivateKey(),瞧,如果您检查GetType(),您手中就有一个RSACng引用。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61275795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档