From 1b7b3bf6cc015774b5f67ed89cae34d39dd31963 Mon Sep 17 00:00:00 2001 From: David Pine Date: Tue, 26 May 2020 15:18:32 -0500 Subject: [PATCH 1/2] Updates on doc --- ...tore-asymmetric-keys-in-a-key-container.md | 412 +++++++++--------- 1 file changed, 213 insertions(+), 199 deletions(-) diff --git a/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md b/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md index e86fc757e3cec..7e5974ccbaa62 100644 --- a/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md +++ b/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md @@ -1,6 +1,6 @@ --- -title: "How to: Store Asymmetric Keys in a Key Container" -ms.date: "03/30/2017" +title: "How to: store asymmetric keys in a key container" +ms.date: 05/26/2020 ms.technology: dotnet-standard dev_langs: - "csharp" @@ -16,208 +16,222 @@ helpviewer_keywords: - "decryption keys" ms.assetid: 0dbcbd8d-0dcf-40e9-9f0c-e3f162d35ccc --- -# How to: Store Asymmetric Keys in a Key Container -Asymmetric private keys should never be stored verbatim or in plain text on the local computer. If you need to store a private key, you should use a key container. For more information on key containers, see [Understanding Machine-Level and User-Level RSA Key Containers](https://docs.microsoft.com/previous-versions/aspnet/f5cs0acs(v=vs.100)). - -### To create an asymmetric key and save it in a key container - -1. Create a new instance of a class and pass the name that you want to call the key container to the field. - -2. Create a new instance of a class that derives from the class (usually **RSACryptoServiceProvider** or **DSACryptoServiceProvider**) and pass the previously created **CspParameters** object to its constructor. - -### To delete the key from a key container - -1. Create a new instance of a **CspParameters** class and pass the name that you want to call the key container to the **CspParameters.KeyContainerName** field. - -2. Create a new instance of a class that derives from the **AsymmetricAlgorithm** class (usually **RSACryptoServiceProvider** or **DSACryptoServiceProvider**) and pass the previously created **CspParameters** object to its constructor. - -3. Set the **PersistKeyInCSP** property of the class that derives from **AsymmetricAlgorithm** to **false** (**False** in Visual Basic). - -4. Call the **Clear** method of the class that derives from **AsymmetricAlgorithm**. This method releases all resources of the class and clears the key container. - -## Example - The following example demonstrates how to create an asymmetric key, save it in a key container, retrieve the key at a later time, and delete the key from the container. - - Notice that code in the `GenKey_SaveInContainer` method and the `GetKeyFromContainer` method is similar. When you specify a key container name for a object and pass it to an object with the property or property set to true, the following occurs. If a key container with the specified name does not exist, then one is created and the key is persisted. If a key container with the specified name does exist, then the key in the container is automatically loaded into the current object. Therefore, the code in the `GenKey_SaveInContainer` method persists the key because it is run first, while the code in the `GetKeyFromContainer` method loads the key because it is run second. - -```vb -Imports System -Imports System.IO -Imports System.Security.Cryptography - _ - -Public Class StoreKey - - Public Shared Sub Main() - Try - ' Create a key and save it in a container. - GenKey_SaveInContainer("MyKeyContainer") - - ' Retrieve the key from the container. - GetKeyFromContainer("MyKeyContainer") - - ' Delete the key from the container. - DeleteKeyFromContainer("MyKeyContainer") - - ' Create a key and save it in a container. - GenKey_SaveInContainer("MyKeyContainer") - - ' Delete the key from the container. - DeleteKeyFromContainer("MyKeyContainer") - Catch e As CryptographicException - Console.WriteLine(e.Message) - End Try - End Sub - - Public Shared Sub GenKey_SaveInContainer(ByVal ContainerName As String) + +# Store asymmetric keys in a key container + +Asymmetric private keys should never be stored verbatim or in plain text on the local computer. If you need to store a private key, you should use a key container. For more information on key containers, see [understanding machine-level and user-level RSA key containers](https://docs.microsoft.com/previous-versions/aspnet/f5cs0acs(v=vs.100)). + +### To create an asymmetric key and save it in a key container + +1. Create a new instance of a class and pass the name that you want to call the key container to the field. + +1. Create a new instance of a class that derives from the class (usually or ) and pass the previously created `CspParameters` object to its constructor. + +> [!NOTE] +> The creation and retrieval of an asymmetric key is one in the same. If a key is not already in the container is it created before being returned, otherwise just returned. +> +> - +> - + +### To delete the key from a key container + +1. Create a new instance of a `CspParameters` class and pass the name that you want to call the key container to the field. + +1. Create a new instance of a class that derives from the class (usually `RSACryptoServiceProvider` or `DSACryptoServiceProvider`) and pass the previously created `CspParameters` object to its constructor. + +1. Set the or the property of the class that derives from `AsymmetricAlgorithm` to `false` (`False` in Visual Basic). + +1. Call the `Clear` method of the class that derives from `AsymmetricAlgorithm`. This method releases all resources of the class and clears the key container. + +## Example + +The following example demonstrates how to create an asymmetric key, save it in a key container, retrieve the key at a later time, and delete the key from the container. + +Notice that code in the `GenKey_SaveInContainer` method and the `GetKeyFromContainer` method is similar. When you specify a key container name for a object and pass it to an object with the property or property set to true, the following occurs. If a key container with the specified name does not exist, then one is created and the key is persisted. If a key container with the specified name does exist, then the key in the container is automatically loaded into the current object. Therefore, the code in the `GenKey_SaveInContainer` method persists the key because it is run first, while the code in the `GetKeyFromContainer` method loads the key because it is run second. + +```vb +Imports System +Imports System.Security.Cryptography + +Public Class StoreKey + + Public Shared Sub Main() + Try + ' Create a key and save it in a container. + GenKey_SaveInContainer("MyKeyContainer") + + ' Retrieve the key from the container. + GetKeyFromContainer("MyKeyContainer") + + ' Delete the key from the container. + DeleteKeyFromContainer("MyKeyContainer") + + ' Create a key and save it in a container. + GenKey_SaveInContainer("MyKeyContainer") + + ' Delete the key from the container. + DeleteKeyFromContainer("MyKeyContainer") + Catch e As CryptographicException + Console.WriteLine(e.Message) + End Try + End Sub + + Private Shared Sub GenKey_SaveInContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container - ' name used to store the RSA key pair. - Dim cp As New CspParameters() - cp.KeyContainerName = ContainerName - - ' Create a new instance of RSACryptoServiceProvider that accesses - ' the key container MyKeyContainerName. - Dim rsa As New RSACryptoServiceProvider(cp) - - ' Display the key information to the console. - Console.WriteLine("Key added to container: {0}", rsa.ToXmlString(True)) - End Sub - - Public Shared Sub GetKeyFromContainer(ByVal ContainerName As String) + ' name used to store the RSA key pair. + Dim parameters As New CspParameters With { + .KeyContainerName = ContainerName + } + + ' Create a new instance of RSACryptoServiceProvider that accesses + ' the key container MyKeyContainerName. + Using rsa As New RSACryptoServiceProvider(parameters) + ' Display the key information to the console. + Console.WriteLine($"Key added to container: {rsa.ToXmlString(True)}") + End Using + End Sub + + Private Shared Sub GetKeyFromContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container - ' name used to store the RSA key pair. - Dim cp As New CspParameters() - cp.KeyContainerName = ContainerName - - ' Create a new instance of RSACryptoServiceProvider that accesses - ' the key container MyKeyContainerName. - Dim rsa As New RSACryptoServiceProvider(cp) - - ' Display the key information to the console. - Console.WriteLine("Key retrieved from container : {0}", rsa.ToXmlString(True)) - End Sub - - Public Shared Sub DeleteKeyFromContainer(ByVal ContainerName As String) + ' name used to store the RSA key pair. + Dim parameters As New CspParameters With { + .KeyContainerName = ContainerName + } + + ' Create a new instance of RSACryptoServiceProvider that accesses + ' the key container MyKeyContainerName. + Using rsa As New RSACryptoServiceProvider(parameters) + ' Display the key information to the console. + Console.WriteLine($"Key retrieved from container : {rsa.ToXmlString(True)}") + End Using + End Sub + + Private Shared Sub DeleteKeyFromContainer(ByVal ContainerName As String) ' Create the CspParameters object and set the key container - ' name used to store the RSA key pair. - Dim cp As New CspParameters() - cp.KeyContainerName = ContainerName - - ' Create a new instance of RSACryptoServiceProvider that accesses - ' the key container. - Dim rsa As New RSACryptoServiceProvider(cp) - - ' Delete the key entry in the container. - rsa.PersistKeyInCsp = False - - ' Call Clear to release resources and delete the key from the container. - rsa.Clear() - - Console.WriteLine("Key deleted.") - End Sub -End Class -``` - -```csharp -using System; -using System.IO; -using System.Security.Cryptography; - -public class StoreKey - -{ - public static void Main() - { - try - { - // Create a key and save it in a container. - GenKey_SaveInContainer("MyKeyContainer"); - - // Retrieve the key from the container. - GetKeyFromContainer("MyKeyContainer"); - - // Delete the key from the container. - DeleteKeyFromContainer("MyKeyContainer"); - - // Create a key and save it in a container. - GenKey_SaveInContainer("MyKeyContainer"); - - // Delete the key from the container. - DeleteKeyFromContainer("MyKeyContainer"); - } - catch(CryptographicException e) - { - Console.WriteLine(e.Message); - } - - } - - public static void GenKey_SaveInContainer(string ContainerName) - { + ' name used to store the RSA key pair. + Dim parameters As New CspParameters With { + .KeyContainerName = ContainerName + } + + ' Create a new instance of RSACryptoServiceProvider that accesses + ' the key container. + ' Delete the key entry in the container. + Dim rsa As New RSACryptoServiceProvider(parameters) With { + .PersistKeyInCsp = False + } + + ' Call Clear to release resources and delete the key from the container. + rsa.Clear() + + Console.WriteLine("Key deleted.") + End Sub +End Class +``` + +```csharp +using System; +using System.Security.Cryptography; + +public class StoreKey +{ + public static void Main() + { + try + { + // Create a key and save it in a container. + GenKey_SaveInContainer("MyKeyContainer"); + + // Retrieve the key from the container. + GetKeyFromContainer("MyKeyContainer"); + + // Delete the key from the container. + DeleteKeyFromContainer("MyKeyContainer"); + + // Create a key and save it in a container. + GenKey_SaveInContainer("MyKeyContainer"); + + // Delete the key from the container. + DeleteKeyFromContainer("MyKeyContainer"); + } + catch (CryptographicException e) + { + Console.WriteLine(e.Message); + } + } + + private static void GenKey_SaveInContainer(string containerName) + { // Create the CspParameters object and set the key container - // name used to store the RSA key pair. - CspParameters cp = new CspParameters(); - cp.KeyContainerName = ContainerName; - - // Create a new instance of RSACryptoServiceProvider that accesses - // the key container MyKeyContainerName. - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); - - // Display the key information to the console. - Console.WriteLine("Key added to container: \n {0}", rsa.ToXmlString(true)); - } - - public static void GetKeyFromContainer(string ContainerName) - { + // name used to store the RSA key pair. + var parameters = new CspParameters + { + KeyContainerName = containerName + }; + + // Create a new instance of RSACryptoServiceProvider that accesses + // the key container MyKeyContainerName. + using var rsa = new RSACryptoServiceProvider(parameters); + + // Display the key information to the console. + Console.WriteLine($"Key added to container: \n {rsa.ToXmlString(true)}"); + } + + private static void GetKeyFromContainer(string containerName) + { // Create the CspParameters object and set the key container - // name used to store the RSA key pair. - CspParameters cp = new CspParameters(); - cp.KeyContainerName = ContainerName; - - // Create a new instance of RSACryptoServiceProvider that accesses - // the key container MyKeyContainerName. - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); - - // Display the key information to the console. - Console.WriteLine("Key retrieved from container : \n {0}", rsa.ToXmlString(true)); - } - - public static void DeleteKeyFromContainer(string ContainerName) - { + // name used to store the RSA key pair. + var parameters = new CspParameters + { + KeyContainerName = containerName + }; + + // Create a new instance of RSACryptoServiceProvider that accesses + // the key container MyKeyContainerName. + using var rsa = new RSACryptoServiceProvider(parameters); + + // Display the key information to the console. + Console.WriteLine($"Key retrieved from container : \n {rsa.ToXmlString(true)}"); + } + + private static void DeleteKeyFromContainer(string containerName) + { // Create the CspParameters object and set the key container - // name used to store the RSA key pair. - CspParameters cp = new CspParameters(); - cp.KeyContainerName = ContainerName; - - // Create a new instance of RSACryptoServiceProvider that accesses - // the key container. - RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp); - - // Delete the key entry in the container. - rsa.PersistKeyInCsp = false; - - // Call Clear to release resources and delete the key from the container. - rsa.Clear(); - - Console.WriteLine("Key deleted."); - } -} -``` - -```console -Key added to container: - Key Information A -Key retrieved from container : - Key Information A -Key deleted. -Key added to container: - Key Information B -Key deleted. -``` - + // name used to store the RSA key pair. + var parameters = new CspParameters + { + KeyContainerName = containerName + }; + + // Create a new instance of RSACryptoServiceProvider that accesses + // the key container. + using var rsa = new RSACryptoServiceProvider(parameters) + { + // Delete the key entry in the container. + PersistKeyInCsp = false + }; + + // Call Clear to release resources and delete the key from the container. + rsa.Clear(); + + Console.WriteLine("Key deleted."); + } +} +``` + +```console +Key added to container: + Key Information A +Key retrieved from container : + Key Information A +Key deleted. +Key added to container: + Key Information B +Key deleted. +``` + ## See also -- [Generating Keys for Encryption and Decryption](../../../docs/standard/security/generating-keys-for-encryption-and-decryption.md) -- [Encrypting Data](../../../docs/standard/security/encrypting-data.md) -- [Decrypting Data](../../../docs/standard/security/decrypting-data.md) -- [Cryptographic Services](../../../docs/standard/security/cryptographic-services.md) +- [Generating keys for encryption and decryption](generating-keys-for-encryption-and-decryption.md) +- [Encrypting data](encrypting-data.md) +- [Decrypting data](decrypting-data.md) +- [Cryptographic services](cryptographic-services.md) From 410740c1e7dd447d082a748b96a4d7366bc800f3 Mon Sep 17 00:00:00 2001 From: David Pine Date: Wed, 27 May 2020 07:26:17 -0500 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Genevieve Warren --- ...-store-asymmetric-keys-in-a-key-container.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md b/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md index 7e5974ccbaa62..8fde70e8c5277 100644 --- a/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md +++ b/docs/standard/security/how-to-store-asymmetric-keys-in-a-key-container.md @@ -19,21 +19,21 @@ ms.assetid: 0dbcbd8d-0dcf-40e9-9f0c-e3f162d35ccc # Store asymmetric keys in a key container -Asymmetric private keys should never be stored verbatim or in plain text on the local computer. If you need to store a private key, you should use a key container. For more information on key containers, see [understanding machine-level and user-level RSA key containers](https://docs.microsoft.com/previous-versions/aspnet/f5cs0acs(v=vs.100)). +Asymmetric private keys should never be stored verbatim or in plain text on the local computer. If you need to store a private key, use a key container. For more information on key containers, see [Understanding machine-level and user-level RSA key containers](https://docs.microsoft.com/previous-versions/aspnet/f5cs0acs(v=vs.100)). -### To create an asymmetric key and save it in a key container +## Create an asymmetric key and save it in a key container 1. Create a new instance of a class and pass the name that you want to call the key container to the field. 1. Create a new instance of a class that derives from the class (usually or ) and pass the previously created `CspParameters` object to its constructor. > [!NOTE] -> The creation and retrieval of an asymmetric key is one in the same. If a key is not already in the container is it created before being returned, otherwise just returned. +> The creation and retrieval of an asymmetric key is one operation. If a key is not already in the container, it's created before being returned. > > - > - -### To delete the key from a key container +## Delete the key from the key container 1. Create a new instance of a `CspParameters` class and pass the name that you want to call the key container to the field. @@ -47,7 +47,12 @@ Asymmetric private keys should never be stored verbatim or in plain text on the The following example demonstrates how to create an asymmetric key, save it in a key container, retrieve the key at a later time, and delete the key from the container. -Notice that code in the `GenKey_SaveInContainer` method and the `GetKeyFromContainer` method is similar. When you specify a key container name for a object and pass it to an object with the property or property set to true, the following occurs. If a key container with the specified name does not exist, then one is created and the key is persisted. If a key container with the specified name does exist, then the key in the container is automatically loaded into the current object. Therefore, the code in the `GenKey_SaveInContainer` method persists the key because it is run first, while the code in the `GetKeyFromContainer` method loads the key because it is run second. +Notice that code in the `GenKey_SaveInContainer` method and the `GetKeyFromContainer` method is similar. When you specify a key container name for a object and pass it to an object with the property or property set to `true`, the behavior is as follows: + +- If a key container with the specified name does not exist, then one is created and the key is persisted. +- If a key container with the specified name does exist, then the key in the container is automatically loaded into the current object. + +Therefore, the code in the `GenKey_SaveInContainer` method persists the key because it is run first, while the code in the `GetKeyFromContainer` method loads the key because it's run second. ```vb Imports System @@ -218,6 +223,8 @@ public class StoreKey } ``` +The output is as follows: + ```console Key added to container: Key Information A