Almacenamiento de claves asimétricas en un contenedor de claves

Las claves privadas asimétricas nunca deben almacenarse literalmente o en texto sin formato en el equipo local. Si tiene que almacenar una clave privada, utilice un contenedor de claves. Para más información sobre contenedores de claves, consulte Descripción de los contenedores de claves RSA en el nivel de equipo y de usuario.

Nota

El código de este artículo se aplica a Windows y usa características que no están disponibles en .NET Core 2.2 y versiones anteriores. Para más información, consulte la incidencia 23391 de dotnet/runtime.

Creación de una clave asimétrica y almacenamiento en un contenedor de claves

  1. Cree una instancia nueva de una clase CspParameters y pase el nombre que quiera darle al contenedor de claves al campo CspParameters.KeyContainerName.

  2. Cree una nueva instancia de una clase que se deriva de la clase AsymmetricAlgorithm (normalmente RSACryptoServiceProvider o DSACryptoServiceProvider) y pase el objeto CspParameters previamente creado a su constructor.

Nota

La creación y recuperación de una clave asimétrica es una operación. Si una clave aún no está en el contenedor, se creará antes de devolverse.

Eliminación de la clave del contenedor de claves

  1. Cree una instancia nueva de una clase CspParameters y pase el nombre que quiera darle al contenedor de claves al campo CspParameters.KeyContainerName.

  2. Cree una nueva instancia de una clase que se deriva de la clase AsymmetricAlgorithm (normalmente RSACryptoServiceProvider o DSACryptoServiceProvider) y pase el objeto CspParameters previamente creado a su constructor.

  3. Establezca la propiedad RSACryptoServiceProvider.PersistKeyInCsp o la propiedad DSACryptoServiceProvider.PersistKeyInCsp de la clase que se deriva de AsymmetricAlgorithm a false (False en Visual Basic).

  4. Llame al método Clear de la clase que se deriva de AsymmetricAlgorithm. Este método libera todos los recursos de la clase y borra el contenedor de claves.

Ejemplo

En el ejemplo siguiente se muestra cómo crear una clave asimétrica, guardarla en un contenedor de claves, recuperarla posteriormente y eliminarla del contenedor.

Observe que el código de los métodos GenKey_SaveInContainer y GetKeyFromContainer es similar. Si especifica el nombre de un contenedor de claves para un objeto CspParameters y lo pasa a un objeto AsymmetricAlgorithm con la propiedad PersistKeyInCsp o la propiedad PersistKeyInCsp establecidas en true, el comportamiento será el siguiente:

  • Si no existe un contenedor de claves con el nombre especificado, se crea uno y la clave se conserva.
  • Si no existe un contenedor de claves con el nombre especificado, la clave del contenedor se carga automáticamente en el objeto AsymmetricAlgorithm actual.

Por lo tanto, el código del método GenKey_SaveInContainer conserva la clave porque se ejecuta primero, mientras que el código del método GetKeyFromContainer carga la clave porque se ejecuta en segundo lugar.

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 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 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 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
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.
        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.
        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.
        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.");
    }
}

La salida es como sigue:

Key added to container:
<RSAKeyValue> Key Information A</RSAKeyValue>
Key retrieved from container :
<RSAKeyValue> Key Information A</RSAKeyValue>
Key deleted.
Key added to container:
<RSAKeyValue> Key Information B</RSAKeyValue>
Key deleted.

Consulte también