导入 RSA CngKey 并存储在 MicrosoftSoftwareKeyStoragePro

Import RSA CngKey and store in MicrosoftSoftwareKeyStorageProvider(导入 RSA CngKey 并存储在 MicrosoftSoftwareKeyStorageProvider 中)
本文介绍了导入 RSA CngKey 并存储在 MicrosoftSoftwareKeyStorageProvider 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个导出的 RSAParameters 私钥,我想将它导入另一台机器.我可以将 new 密钥保存到本地计算机或用户容器中,但我无法尝试导入 现有 密钥.

I have an exported RSAParameters private key that I'd like to import into another machine. I can save new keys into the local machine or user containers, but I'm stuck trying to import an existing key.

下面的代码将生成一个新的密钥对,我知道我可以直接在容器中生成一个新密钥 - 但我希望能够生成一个密钥并将同一个密钥导入到少数不同的计算机中.

The code below will generate a new key pair, and I know I could just generate a new key directly into the container - but I want to be able to generate a single key and import that same key into a handful of different computers.

如何获取 RSAParameters 或 XML 字符串(任一)并将其导入本地用户(或机器)容器?

How can I take either an RSAParameters or a string of XML (either one) and import that into a local user (or machine) container?

    public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize)
    {
        var csp = new RSACng(keySize);

        var privKey = await Task.Run(() => csp.ExportParameters(includePrivateParameters: true));
        var pubKey = csp.ExportParameters(includePrivateParameters: false);

        var pubKeyString = exportKeyToString(pubKey);
        var privKeyString = exportKeyToString(privKey);

        return new KeyGenerationResult
        {
            PrivateKey = privKey,
            PublicKey = pubKey,
            PrivateKeyCleartext = privKeyString,
            PublicKeyCleartext = pubKeyString
        };
    }

    private static string exportKeyToString(RSAParameters key)
    {
        string keyString;
        var sw = new StringWriter();
        var xs = new XmlSerializer(typeof(RSAParameters));
        xs.Serialize(sw, key);
        keyString = sw.ToString();
        return keyString;
    }

    public void SavePrivateKeyToLocalMachine(RSAParameters privateKey, string keyName)
    {
       //Stuck here. :(
    }

CngKey.Import() 需要一个字节[],这看起来很有希望,但我无法找到任何方法来创建 CngKey.Import() 所需的字节[].

CngKey.Import() takes a byte[] and that looks promising, but I haven't been able to find any method to create the byte[] that CngKey.Import() requires.

        var d = new RSACryptoServiceProvider();
        d.ImportParameters(privateKey);
        var keyBlob = d.ExportCspBlob(true);
        var key = CngKey.Import(keyBlob, CngKeyBlobFormat.Pkcs8PrivateBlob);

这给了我一个字节[],但无论我使用什么 CngKeyBlobFormat,我都会遇到异常.我被卡住了.

That gets me a byte[] but regardless of what CngKeyBlobFormat I use, I get an exception. I'm stuck.

更新

我找到了一种使用

 var cp = new CngKeyCreationParameters();
 cp.KeyUsage = CngKeyUsages.AllUsages;
 cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving;
 cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
 var key = CngKey.Create(CngAlgorithm.Rsa, null, cp);
 var bytes = key.Export(CngKeyBlobFormat.{I have tried them all});

这段代码看起来像它应该让我导入字节[]

And this code looks like it should let me import the byte[]

 /* try to save this key to the local user container */
 var keyParameters = new CngKeyCreationParameters()
 {
     KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey,
     Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
     KeyUsage = CngKeyUsages.AllUsages,
     ExportPolicy = CngExportPolicies.AllowPlaintextExport
 };
 keyParameters.KeyCreationOptions = CngKeyCreationOptions.None;
 keyParameters.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
 keyParameters.Parameters.Add(new CngProperty(blobType.Format, bytes, CngPropertyOptions.None));

 var newKey = CngKey.Create(CngAlgorithm.Rsa, "MyTestName", keyParameters);

...但再一次,没有骰子.我尝试什么 CngKeyBlobFormat 都没关系,它们都给了我例外,我无法将密钥导入本地密钥存储提供程序.

...but once again, no dice. It doesn't matter what CngKeyBlobFormat I try, they all give me exceptions and I'm unable to import the key into a local key storage provider.

我需要什么神奇的设置和参数组合才能完成这项工作?

What magic mix of settings and parameters do I need to make this work?

推荐答案

好吧,我终于搞定了.这是最终稳定下来的代码.

Well, I finally got it working. Here's the code as it finally settled down.

public class KeyGenerationResult
{
    public RSAParameters PublicKey { get; set; }
    public string PublicKeyCleartext { get; set; }
    public string PrivateKeyCleartext { get; set; }
    public byte[] PrivateBytes { get; set; }
    public int KeySize { get; set; }
    public CngKeyBlobFormat BlobFormat { get; set; }
}

    public async Task<KeyGenerationResult> GenerateNewKeyAsync(int keySize)
    {
        var cp = new CngKeyCreationParameters();
        cp.KeyUsage = CngKeyUsages.AllUsages;
        cp.ExportPolicy = CngExportPolicies.AllowPlaintextExport | CngExportPolicies.AllowExport | CngExportPolicies.AllowArchiving | CngExportPolicies.AllowPlaintextArchiving;
        cp.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keySize), CngPropertyOptions.None));
        var key = await Task.Run(() => CngKey.Create(CngAlgorithm.Rsa, null, cp)).ConfigureAwait(false);
        var blobType = CngKeyBlobFormat.GenericPrivateBlob;
        var bytes = await Task.Run(() => key.Export(blobType)).ConfigureAwait(false);

        var rsa = new RSACng(key);
        var pubKey = rsa.ExportParameters(includePrivateParameters: false);
        var pubKeyString = exportKeyToString(pubKey);

        return new KeyGenerationResult
        {
            PublicKey = pubKey,
            PrivateKeyCleartext = Convert.ToBase64String(bytes),
            PublicKeyCleartext = pubKeyString,
            PrivateBytes = bytes,
            BlobFormat = blobType,
            KeySize = keySize
        };
    }

    private static string exportKeyToString(RSAParameters key)
    {
        string keyString;
        var sw = new StringWriter();
        var xs = new XmlSerializer(typeof(RSAParameters));
        xs.Serialize(sw, key);
        keyString = sw.ToString();
        return keyString;
    }

    public void SavePrivateKeyToLocalMachine(KeyGenerationResult keyData, string keyName)
    {
        var myKSP = CngProvider.MicrosoftSoftwareKeyStorageProvider;
        const bool MachineKey = false;

        if (!CngKey.Exists(keyName, myKSP))
        {
            var keyParams = new CngKeyCreationParameters
            {
                ExportPolicy = CngExportPolicies.AllowPlaintextExport,
                KeyCreationOptions = (MachineKey) ? CngKeyCreationOptions.MachineKey : CngKeyCreationOptions.None,
                Provider = myKSP
            };
            keyParams.Parameters.Add(new CngProperty("Length", BitConverter.GetBytes(keyData.KeySize), CngPropertyOptions.None));
            keyParams.Parameters.Add(new CngProperty(keyData.BlobFormat.Format, keyData.PrivateBytes, CngPropertyOptions.None));

            CngKey.Create(CngAlgorithm.Rsa, keyName, keyParams);
        }
        else
        {
            throw new CryptographicException($"The key with the name '{keyName}' already exists!");
        }
    }

这篇关于导入 RSA CngKey 并存储在 MicrosoftSoftwareKeyStorageProvider 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)