Reputation: 215
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.
I'd prefer to see this with RSA encryption, unless there is a safer way to do this.
I am almost certain that this is more or less a duplicate question, but if so, then I haven't found the original yet.
Upvotes: 2
Views: 1982
Reputation: 33098
Borrowed from a corefx test (and other code in the same file):
// 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:
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):
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.
}
Upvotes: 1