简体   繁体   English

如何创建公钥/私钥对并将其安全地存储到密钥容器中?

[英]How do I create a public-key/private-key pair and safely store them into a key container?

I have been trying to do some simple cryptography practice, but I am stumped. 我一直在尝试做一些简单的加密练习,但我很难过。 I have thus far been able to generate a pair of public and private keys, but I haven't figured out how to safely store them or make them persist beyond a single session. 到目前为止,我已经能够生成一对公钥和私钥,但我还没有弄清楚如何安全地存储它们或使它们在单个会话之后持续存在。 In my research, I've heard of this thing called a "key container" that allows these keys to (safely) persist beyond a single session and be retrieved at a later time. 在我的研究中,我听说过这个称为“密钥容器”的东西,它允许这些密钥(安全地)持续超过单个会话并在以后检索。

Unfortunately, cryptography is complicated, so every time I think I've figured something out, it gives me five more questions that have to be answered before I can understand what I'm doing. 不幸的是,密码学是复杂的,所以每次我想我已经找到了一些东西,它给了我另外五个问题,在我能理解我在做什么之前必须回答。 By this point, my head is swimming with all this information, and I'm having quite a bit of trouble making sense of it all. 在这一点上,我的头脑正在游泳所有这些信息,我在理解这一切时遇到了一些麻烦。 So... 所以...

I would like to see a code example that creates a public-key/private-key pair, saves them in a key container, and then retrieves them. 我想看一个代码示例,它创建一个公钥/私钥对,将它们保存在一个密钥容器中,然后检索它们。 If possible, I would also like to see some code that retrieves a public key and a private key from a key container that is assumed to already exist. 如果可能的话,我还希望看到一些代码从一个假定已经存在的密钥容器中检索公钥和私钥。 For constraints, assume that Visual Studios C# is being used in a .NET framework, on a Windows 10 OS. 对于约束,假设Visual Studio C#正在Windows 10 OS上的.NET框架中使用。

I'd prefer to see this with RSA encryption, unless there is a safer way to do this. 除非有更安全的方法,否则我更愿意看到RSA加密。

I am almost certain that this is more or less a duplicate question, but if so, then I haven't found the original yet. 我几乎可以肯定这或多或少是一个重复的问题,但如果是这样,那么我还没有找到原始问题。

Borrowed from a corefx test (and other code in the same file): 借用corefx测试 (以及同一文件中的其他代码):

// Ideally you use a name that won't ever be used by someone else.
// Certificate import names its keys GUIDs, but then has to remember what they were.
const string KeyName = "SomePersistedKey";
const int Size = 2048; // Or whatever.

CNG: CNG:

CngKey key = null;

try
{
    key = CngKey.Open(KeyName);
}
catch (CryptographicException)
{
    // This is only in the catch block to avoid a scrollbar.
    CngKeyCreationParameters creationParameters = new CngKeyCreationParameters()
    {
        ExportPolicy = CngExportPolicies.None, // Or whatever.
        Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
        KeyCreationOptions = CngKeyCreationOptions.OverwriteExistingKey,
        Parameters =
        {
            new CngProperty("Length", BitConverter.GetBytes(Size), CngPropertyOptions.None),
        }
    };

    cngKey = CngKey.Create(CngAlgorithm.Rsa, KeyName, creationParameters);
}

using (cngKey)
using (RSA rsa = new RSACng(cngKey))
{
    // Tada.
}

Or, if you need to stick with CAPI (hopefully not): 或者,如果你需要坚持使用CAPI(希望不是):

const int PROV_RSA_AES = 24;

CspParameters cspParameters = new CspParameters(PROV_RSA_AES)
{
    KeyNumber = (int)KeyNumber.Exchange,
    KeyContainerName = KeyName,
    Flags = CspProviderFlags.UseNonExportableKey, // Or whatever.
};

// This constructor is open-or-create since flags didn't asset ExistingOnly.
using (RSA rsa = new RSACryptoServiceProvider(Size, cspParameters))
{
    // tada.  Use CNG instead, if you can.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM