添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
彷徨的机器人  ·  stringvar转变成str ...·  5 天前    · 
高大的卤蛋  ·  Prevent Cross-Site ...·  2 天前    · 
有腹肌的啄木鸟  ·  使用 JdbcTemplate ...·  昨天    · 
咆哮的馒头  ·  Get Nth Entry from ...·  17 小时前    · 
高兴的红酒  ·  Pro X20 - Westone Audio·  4 月前    · 
打酱油的香蕉  ·  Excel ...·  8 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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.

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() 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);

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

UPDATE

I found a way to get a byte[] using

 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);

...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?

What exceptions were you getting exactly? Not only would that help people help you, it would make your question (and more importantly your solution!) more discoverable by people facing the same issue. – Ohad Schneider Sep 7, 2017 at 15:28

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);
            throw new CryptographicException($"The key with the name '{keyName}' already exists!");
                For reference, I believe this was the inspiration for this answer: social.msdn.microsoft.com/Forums/vstudio/en-US/…
– Ohad Schneider
                Sep 6, 2017 at 23:43
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.