Share via


Tutorial: Creación de una aplicación criptográfica

Nota

Este artículo se aplica a Windows.

Para más información sobre ASP.NET Core, consulte Protección de datos de ASP.NET Core.

En este tutorial se muestra cómo cifrar y descifrar el contenido de un archivo. Los ejemplos de código están diseñados para una aplicación de Windows Forms. Esta aplicación no muestra escenarios del mundo real, como el uso de tarjetas inteligentes. En su lugar, muestra los aspectos básicos del cifrado y el descifrado.

En este tutorial se usan las siguientes directrices para el cifrado:

  • Use la clase Aes, un algoritmo simétrico, para cifrar y descifrar datos mediante su Key y IV generados automáticamente.

  • Use el algoritmo asimétrico RSA para cifrar y descifrar la clave en los datos cifrados mediante Aes. Los algoritmos asimétricos son útiles para pequeñas cantidades de datos, como las claves.

    Nota

    Si desea proteger los datos en el equipo en lugar de intercambiar contenido cifrado con otras personas, considere la posibilidad de usar la clase ProtectedData.

En la tabla siguiente se resumen las tareas criptográficas de este tema.

Tarea Descripción
Crear una aplicación de Windows Forms Enumera los controles necesarios para ejecutar la aplicación.
Declaración de objetos globales Declara variables de ruta de acceso de cadena, los CspParameters y el RSACryptoServiceProvider para disponer del contexto global de la clase Form.
Creación de una clave asimétrica Crea un par clave-valor público y privado asimétricos y le asigna un nombre de contenedor de claves.
Cifrado de un archivo Muestra un cuadro de diálogo para seleccionar un archivo para el cifrado y lo cifra.
Descifrado de un archivo Muestra un cuadro de diálogo para seleccionar un archivo cifrado para el descifrado y lo descifra.
Obtención de una clave privada Obtiene el par de claves completo con el nombre del contenedor de claves.
Exportación de una clave pública Guarda la clave en un archivo XML únicamente con parámetros públicos.
Importación de una clave pública Carga la clave desde un archivo XML en el contenedor de claves.
Prueba de la aplicación Enumera los procedimientos para probar esta aplicación.

Requisitos previos

Necesitará los componentes siguientes para completar este tutorial:

Crear una aplicación de Windows Forms

La mayoría de los ejemplos de código de este tutorial están diseñados para actuar como controladores de eventos de los controles de botón. En la tabla siguiente se enumeran los controles necesarios para que la aplicación de ejemplo y los nombres necesarios coincidan con los ejemplos de código.

Control Nombre Propiedad de texto (según sea necesario)
Button buttonEncryptFile Cifrar archivo
Button buttonDecryptFile Descifrar archivo
Button buttonCreateAsmKeys Crear claves
Button buttonExportPublicKey Exportar la clave pública
Button buttonImportPublicKey Importar la clave pública
Button buttonGetPrivateKey Obtener la clave privada
Label label1 Clave no establecida
OpenFileDialog _encryptOpenFileDialog
OpenFileDialog _decryptOpenFileDialog

Haga doble clic en los botones del diseñador de Visual Studio para crear los controladores de eventos.

Declaración de objetos globales

Agregue el código siguiente como parte de la declaración de la clase Form1. Edite las variables de cadena para el entorno y las preferencias.

// Declare CspParameters and RsaCryptoServiceProvider
// objects with global scope of your Form class.
readonly CspParameters _cspp = new CspParameters();
RSACryptoServiceProvider _rsa;

// Path variables for source, encryption, and
// decryption folders. Must end with a backslash.
const string EncrFolder = @"c:\Encrypt\";
const string DecrFolder = @"c:\Decrypt\";
const string SrcFolder = @"c:\docs\";

// Public key file
const string PubKeyFile = @"c:\encrypt\rsaPublicKey.txt";

// Key container name for
// private/public key value pair.
const string KeyName = "Key01";
' Declare CspParameters and RsaCryptoServiceProvider
' objects with global scope of your Form class.
ReadOnly _cspp As New CspParameters
Dim _rsa As RSACryptoServiceProvider

' Path variables for source, encryption, and
' decryption folders. Must end with a backslash.
Const EncrFolder As String = "c:\Encrypt\"
Const DecrFolder As String = "c:\Decrypt\"
Const SrcFolder As String = "c:\docs\"

' Public key file
Const PubKeyFile As String = "c:\encrypt\rsaPublicKey.txt"

' Key container name for
' private/public key value pair.
Const KeyName As String = "Key01"

Creación de una clave asimétrica

Esta tarea crea una clave asimétrica que cifra y descifra la clave Aes. Esta clave se usó para cifrar el contenido y muestra el nombre del contenedor de claves en el control de etiqueta.

Agregue el siguiente código como controlador de eventos Click del botón Create Keys (buttonCreateAsmKeys_Click).

private void buttonCreateAsmKeys_Click(object sender, EventArgs e)
{
    // Stores a key pair in the key container.
    _cspp.KeyContainerName = KeyName;
    _rsa = new RSACryptoServiceProvider(_cspp)
    {
        PersistKeyInCsp = true
    };

    label1.Text = _rsa.PublicOnly
        ? $"Key: {_cspp.KeyContainerName} - Public Only"
        : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
}
Private Sub buttonCreateAsmKeys_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonCreateAsmKeys.Click
    ' Stores a key pair in the key container.
    _cspp.KeyContainerName = KeyName
    _rsa = New RSACryptoServiceProvider(_cspp) With {
        .PersistKeyInCsp = True
    }

    If _rsa.PublicOnly Then
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
    Else
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
    End If

End Sub

Cifrado de un archivo

Esta tarea implica dos métodos: el método del controlador de eventos del botón Encrypt File (buttonEncryptFile_Click) y el método EncryptFile. El primer método muestra un cuadro de diálogo para seleccionar un archivo y pasa el nombre del archivo al segundo método, que lleva a cabo el cifrado.

El contenido cifrado, la clave y el vector de inicialización (IV) se guardan en un FileStream, conocido como paquete de cifrado.

El método EncryptFile hace lo siguiente:

  1. Crea un algoritmo simétrico Aes para cifrar el contenido.
  2. Crea un objeto RSACryptoServiceProvider para cifrar la clave Aes.
  3. Usa un objeto CryptoStream para leer y cifrar el FileStream del archivo de código fuente, en bloques de bytes, en un objeto FileStream de destino para el archivo cifrado.
  4. Determina la longitud de la clave cifrada y del IV y crea matrices de bytes de sus valores de longitud.
  5. Escribe la clave, el IV y sus valores de longitud en el paquete cifrado.

El paquete de cifrado usa el siguiente formato:

  • Longitud de clave, bytes 0 - 3
  • Longitud del IV, bytes 4 - 7
  • Clave cifrada
  • IV
  • Texto cifrado

Puede usar la longitud de la clave y del IV para determinar los puntos iniciales y la longitud de todas las partes del paquete de cifrado, que posteriormente se puede usar para descifrar el archivo.

Agregue el siguiente código como controlador de eventos Click del botón Encrypt File (buttonEncryptFile_Click).

private void buttonEncryptFile_Click(object sender, EventArgs e)
{
    if (_rsa is null)
    {
        MessageBox.Show("Key not set.");
    }
    else
    {
        // Display a dialog box to select a file to encrypt.
        _encryptOpenFileDialog.InitialDirectory = SrcFolder;
        if (_encryptOpenFileDialog.ShowDialog() == DialogResult.OK)
        {
            string fName = _encryptOpenFileDialog.FileName;
            if (fName != null)
            {
                // Pass the file name without the path.
                EncryptFile(new FileInfo(fName));
            }
        }
    }
}
Private Sub buttonEncryptFile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonEncryptFile.Click
    If _rsa Is Nothing Then
        MsgBox("Key not set.")
    Else
        ' Display a dialog box to select a file to encrypt.
        _encryptOpenFileDialog.InitialDirectory = SrcFolder
        If _encryptOpenFileDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
            Try
                Dim fName As String = _encryptOpenFileDialog.FileName
                If (Not (fName) Is Nothing) Then
                    Dim fInfo As New FileInfo(fName)
                    ' Use just the file name without path.
                    Dim name As String = fInfo.FullName
                    EncryptFile(name)
                End If
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End If
    End If
End Sub

Agregue el siguiente método EncryptFile al formulario.

private void EncryptFile(FileInfo file)
{
    // Create instance of Aes for
    // symmetric encryption of the data.
    Aes aes = Aes.Create();
    ICryptoTransform transform = aes.CreateEncryptor();

    // Use RSACryptoServiceProvider to
    // encrypt the AES key.
    // rsa is previously instantiated:
    //    rsa = new RSACryptoServiceProvider(cspp);
    byte[] keyEncrypted = _rsa.Encrypt(aes.Key, false);

    // Create byte arrays to contain
    // the length values of the key and IV.
    int lKey = keyEncrypted.Length;
    byte[] LenK = BitConverter.GetBytes(lKey);
    int lIV = aes.IV.Length;
    byte[] LenIV = BitConverter.GetBytes(lIV);

    // Write the following to the FileStream
    // for the encrypted file (outFs):
    // - length of the key
    // - length of the IV
    // - encrypted key
    // - the IV
    // - the encrypted cipher content

    // Change the file's extension to ".enc"
    string outFile =
        Path.Combine(EncrFolder, Path.ChangeExtension(file.Name, ".enc"));

    using (var outFs = new FileStream(outFile, FileMode.Create))
    {
        outFs.Write(LenK, 0, 4);
        outFs.Write(LenIV, 0, 4);
        outFs.Write(keyEncrypted, 0, lKey);
        outFs.Write(aes.IV, 0, lIV);

        // Now write the cipher text using
        // a CryptoStream for encrypting.
        using (var outStreamEncrypted =
            new CryptoStream(outFs, transform, CryptoStreamMode.Write))
        {
            // By encrypting a chunk at
            // a time, you can save memory
            // and accommodate large files.
            int count = 0;
            int offset = 0;

            // blockSizeBytes can be any arbitrary size.
            int blockSizeBytes = aes.BlockSize / 8;
            byte[] data = new byte[blockSizeBytes];
            int bytesRead = 0;

            using (var inFs = new FileStream(file.FullName, FileMode.Open))
            {
                do
                {
                    count = inFs.Read(data, 0, blockSizeBytes);
                    offset += count;
                    outStreamEncrypted.Write(data, 0, count);
                    bytesRead += blockSizeBytes;
                } while (count > 0);
            }
            outStreamEncrypted.FlushFinalBlock();
        }
    }
}
Private Sub EncryptFile(ByVal inFile As String)
    ' Create instance of Aes for
    ' symmetric encryption of the data.
    Dim aes As Aes = Aes.Create()
    Dim transform As ICryptoTransform = aes.CreateEncryptor

    ' Use RSACryptoServiceProvider to
    ' encrypt the AES key.
    Dim keyEncrypted() As Byte = _rsa.Encrypt(aes.Key, False)

    ' Create byte arrays to contain
    ' the length values of the key and IV.
    Dim LenK() As Byte = New Byte((4) - 1) {}
    Dim LenIV() As Byte = New Byte((4) - 1) {}
    Dim lKey As Integer = keyEncrypted.Length
    LenK = BitConverter.GetBytes(lKey)
    Dim lIV As Integer = aes.IV.Length
    LenIV = BitConverter.GetBytes(lIV)

    ' Write the following to the FileStream
    ' for the encrypted file (outFs):
    ' - length of the key
    ' - length of the IV
    ' - encrypted key
    ' - the IV
    ' - the encrypted cipher content
    ' Change the file's extension to ".enc"
    Dim startFileName As Integer = inFile.LastIndexOf("\") + 1
    Dim outFile As String = (EncrFolder _
                + (inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc"))

    Using outFs As New FileStream(outFile, FileMode.Create)
        outFs.Write(LenK, 0, 4)
        outFs.Write(LenIV, 0, 4)
        outFs.Write(keyEncrypted, 0, lKey)
        outFs.Write(aes.IV, 0, lIV)

        ' Now write the cipher text using
        ' a CryptoStream for encrypting.
        Using outStreamEncrypted As New CryptoStream(outFs, transform, CryptoStreamMode.Write)
            ' By encrypting a chunk at
            ' a time, you can save memory
            ' and accommodate large files.
            Dim count As Integer = 0
            Dim offset As Integer = 0

            ' blockSizeBytes can be any arbitrary size.
            Dim blockSizeBytes As Integer = (aes.BlockSize / 8)
            Dim data() As Byte = New Byte((blockSizeBytes) - 1) {}
            Dim bytesRead As Integer = 0
            Using inFs As New FileStream(inFile, FileMode.Open)
                Do
                    count = inFs.Read(data, 0, blockSizeBytes)
                    offset = (offset + count)
                    outStreamEncrypted.Write(data, 0, count)
                    bytesRead = (bytesRead + blockSizeBytes)
                Loop Until (count = 0)

                outStreamEncrypted.FlushFinalBlock()
                inFs.Close()
            End Using
            outStreamEncrypted.Close()
        End Using
        outFs.Close()
    End Using
End Sub

Descifrado de un archivo

Esta tarea implica dos métodos: el método del controlador de eventos del botón Decrypt File (buttonDecryptFile_Click) y el método DecryptFile. El primer método muestra un cuadro de diálogo para seleccionar un archivo y pasa su nombre al segundo método, que lleva a cabo el descifrado.

El método Decrypt hace lo siguiente:

  1. Crea un algoritmo simétrico Aes para descifrar el contenido.
  2. Lee los primeros ocho bytes del FileStream del paquete de cifrado en matrices de bytes para obtener la longitud de la clave cifrada y del IV.
  3. Extrae la clave y el IV del paquete de cifrado en matrices de bytes.
  4. Crea un objeto RSACryptoServiceProvider para descifrar la clave Aes.
  5. Usa un objeto CryptoStream para leer y descifrar la sección de texto cifrado del paquete de cifrado FileStream, en bloques de bytes, en el objeto FileStream del archivo descifrado. Al finalizar, se habrá completado el descifrado.

Agregue el siguiente código como controlador de eventos Click del botón Decrypt File.

private void buttonDecryptFile_Click(object sender, EventArgs e)
{
    if (_rsa is null)
    {
        MessageBox.Show("Key not set.");
    }
    else
    {
        // Display a dialog box to select the encrypted file.
        _decryptOpenFileDialog.InitialDirectory = EncrFolder;
        if (_decryptOpenFileDialog.ShowDialog() == DialogResult.OK)
        {
            string fName = _decryptOpenFileDialog.FileName;
            if (fName != null)
            {
                DecryptFile(new FileInfo(fName));
            }
        }
    }
}
Private Sub buttonDecryptFile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonDecryptFile.Click
    If _rsa Is Nothing Then
        MsgBox("Key not set.")
    Else
        ' Display a dialog box to select the encrypted file.
        _decryptOpenFileDialog.InitialDirectory = EncrFolder
        If (_decryptOpenFileDialog.ShowDialog = Windows.Forms.DialogResult.OK) Then
            Try
                Dim fName As String = _decryptOpenFileDialog.FileName
                If ((fName) IsNot Nothing) Then
                    Dim fi As New FileInfo(fName)
                    Dim name As String = fi.Name
                    DecryptFile(name)
                End If
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End If
End Sub

Agregue el siguiente método DecryptFile al formulario.

private void DecryptFile(FileInfo file)
{
    // Create instance of Aes for
    // symmetric decryption of the data.
    Aes aes = Aes.Create();

    // Create byte arrays to get the length of
    // the encrypted key and IV.
    // These values were stored as 4 bytes each
    // at the beginning of the encrypted package.
    byte[] LenK = new byte[4];
    byte[] LenIV = new byte[4];

    // Construct the file name for the decrypted file.
    string outFile =
        Path.ChangeExtension(file.FullName.Replace("Encrypt", "Decrypt"), ".txt");

    // Use FileStream objects to read the encrypted
    // file (inFs) and save the decrypted file (outFs).
    using (var inFs = new FileStream(file.FullName, FileMode.Open))
    {
        inFs.Seek(0, SeekOrigin.Begin);
        inFs.Read(LenK, 0, 3);
        inFs.Seek(4, SeekOrigin.Begin);
        inFs.Read(LenIV, 0, 3);

        // Convert the lengths to integer values.
        int lenK = BitConverter.ToInt32(LenK, 0);
        int lenIV = BitConverter.ToInt32(LenIV, 0);

        // Determine the start position of
        // the cipher text (startC)
        // and its length(lenC).
        int startC = lenK + lenIV + 8;
        int lenC = (int)inFs.Length - startC;

        // Create the byte arrays for
        // the encrypted Aes key,
        // the IV, and the cipher text.
        byte[] KeyEncrypted = new byte[lenK];
        byte[] IV = new byte[lenIV];

        // Extract the key and IV
        // starting from index 8
        // after the length values.
        inFs.Seek(8, SeekOrigin.Begin);
        inFs.Read(KeyEncrypted, 0, lenK);
        inFs.Seek(8 + lenK, SeekOrigin.Begin);
        inFs.Read(IV, 0, lenIV);

        Directory.CreateDirectory(DecrFolder);
        // Use RSACryptoServiceProvider
        // to decrypt the AES key.
        byte[] KeyDecrypted = _rsa.Decrypt(KeyEncrypted, false);

        // Decrypt the key.
        ICryptoTransform transform = aes.CreateDecryptor(KeyDecrypted, IV);

        // Decrypt the cipher text from
        // from the FileSteam of the encrypted
        // file (inFs) into the FileStream
        // for the decrypted file (outFs).
        using (var outFs = new FileStream(outFile, FileMode.Create))
        {
            int count = 0;
            int offset = 0;

            // blockSizeBytes can be any arbitrary size.
            int blockSizeBytes = aes.BlockSize / 8;
            byte[] data = new byte[blockSizeBytes];

            // By decrypting a chunk a time,
            // you can save memory and
            // accommodate large files.

            // Start at the beginning
            // of the cipher text.
            inFs.Seek(startC, SeekOrigin.Begin);
            using (var outStreamDecrypted =
                new CryptoStream(outFs, transform, CryptoStreamMode.Write))
            {
                do
                {
                    count = inFs.Read(data, 0, blockSizeBytes);
                    offset += count;
                    outStreamDecrypted.Write(data, 0, count);
                } while (count > 0);

                outStreamDecrypted.FlushFinalBlock();
            }
        }
    }
}
Private Sub DecryptFile(ByVal inFile As String)
    ' Create instance of Aes for
    ' symmetric decryption of the data.
    Dim aes As Aes = Aes.Create()

    ' Create byte arrays to get the length of
    ' the encrypted key and IV.
    ' These values were stored as 4 bytes each
    ' at the beginning of the encrypted package.
    Dim LenK() As Byte = New Byte(4 - 1) {}
    Dim LenIV() As Byte = New Byte(4 - 1) {}

    ' Construct the file name for the decrypted file.
    Dim outFile As String = (DecrFolder _
                + (inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt"))

    ' Use FileStream objects to read the encrypted
    ' file (inFs) and save the decrypted file (outFs).
    Using inFs As New FileStream((EncrFolder + inFile), FileMode.Open)

        inFs.Seek(0, SeekOrigin.Begin)
        inFs.Read(LenK, 0, 3)
        inFs.Seek(4, SeekOrigin.Begin)
        inFs.Read(LenIV, 0, 3)

        Dim lengthK As Integer = BitConverter.ToInt32(LenK, 0)
        Dim lengthIV As Integer = BitConverter.ToInt32(LenIV, 0)
        Dim startC As Integer = (lengthK + lengthIV + 8)
        Dim lenC As Integer = (CType(inFs.Length, Integer) - startC)
        Dim KeyEncrypted() As Byte = New Byte(lengthK - 1) {}
        Dim IV() As Byte = New Byte(lengthIV - 1) {}

        ' Extract the key and IV
        ' starting from index 8
        ' after the length values.
        inFs.Seek(8, SeekOrigin.Begin)
        inFs.Read(KeyEncrypted, 0, lengthK)
        inFs.Seek(8 + lengthK, SeekOrigin.Begin)
        inFs.Read(IV, 0, lengthIV)
        Directory.CreateDirectory(DecrFolder)
        ' User RSACryptoServiceProvider
        ' to decrypt the AES key
        Dim KeyDecrypted() As Byte = _rsa.Decrypt(KeyEncrypted, False)

        ' Decrypt the key.
        Dim transform As ICryptoTransform = aes.CreateDecryptor(KeyDecrypted, IV)
        ' Decrypt the cipher text from
        ' from the FileSteam of the encrypted
        ' file (inFs) into the FileStream
        ' for the decrypted file (outFs).
        Using outFs As New FileStream(outFile, FileMode.Create)
            Dim count As Integer = 0
            Dim offset As Integer = 0

            ' blockSizeBytes can be any arbitrary size.
            Dim blockSizeBytes As Integer = (aes.BlockSize / 8)
            Dim data() As Byte = New Byte(blockSizeBytes - 1) {}
            ' By decrypting a chunk a time,
            ' you can save memory and
            ' accommodate large files.
            ' Start at the beginning
            ' of the cipher text.
            inFs.Seek(startC, SeekOrigin.Begin)
            Using outStreamDecrypted As New CryptoStream(outFs, transform, CryptoStreamMode.Write)
                Do
                    count = inFs.Read(data, 0, blockSizeBytes)
                    offset += count
                    outStreamDecrypted.Write(data, 0, count)
                Loop Until (count = 0)

                outStreamDecrypted.FlushFinalBlock()
            End Using
        End Using
    End Using
End Sub

Exportación de una clave pública

Esta tarea guarda en un archivo la clave creada por el botón Create Keys. Solo exporta los parámetros públicos.

Esta tarea simula un escenario en que Alicia da a Roberto su clave pública para que pueda cifrar archivos por ella. Roberto y otras personas que tengan esa clave pública no podrán descifrarlos porque no tienen el par de claves completo con los parámetros privados.

Agregue el siguiente código como controlador de eventos Click del botón Export Public Key (buttonExportPublicKey_Click).

void buttonExportPublicKey_Click(object sender, EventArgs e)
{
    // Save the public key created by the RSA
    // to a file. Caution, persisting the
    // key to a file is a security risk.
    Directory.CreateDirectory(EncrFolder);
    using (var sw = new StreamWriter(PubKeyFile, false))
    {
        sw.Write(_rsa.ToXmlString(false));
    }
}
Private Sub buttonExportPublicKey_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonExportPublicKey.Click
    ' Save the public key created by the RSA
    ' to a file. Caution, persisting the
    ' key to a file is a security risk.
    Directory.CreateDirectory(EncrFolder)
    Using sw As New StreamWriter(PubKeyFile)
        sw.Write(_rsa.ToXmlString(False))
    End Using
End Sub

Importación de una clave pública

Esta tarea carga la clave únicamente con parámetros públicos, tal como se creó con el botón Export Public Key, y la establece con el nombre del contenedor de claves.

Esta tarea simula un escenario en que Roberto carga la clave de Alicia que solo tiene parámetros públicos, de manera que pueda cifrar archivos por ella.

Agregue el siguiente código como controlador de eventos Click del botón Import Public Key (buttonImportPublicKey_Click).

void buttonImportPublicKey_Click(object sender, EventArgs e)
{
    using (var sr = new StreamReader(PubKeyFile))
    {
        _cspp.KeyContainerName = KeyName;
        _rsa = new RSACryptoServiceProvider(_cspp);

        string keytxt = sr.ReadToEnd();
        _rsa.FromXmlString(keytxt);
        _rsa.PersistKeyInCsp = true;

        label1.Text = _rsa.PublicOnly
            ? $"Key: {_cspp.KeyContainerName} - Public Only"
            : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
    }
}
Private Sub buttonImportPublicKey_Click(ByVal sender As Object, ByVal e As EventArgs) Handles buttonImportPublicKey.Click
    Using sr As New StreamReader(PubKeyFile)
        _cspp.KeyContainerName = KeyName
        _rsa = New RSACryptoServiceProvider(_cspp)
        Dim keytxt As String = sr.ReadToEnd
        _rsa.FromXmlString(keytxt)
        _rsa.PersistKeyInCsp = True

        If _rsa.PublicOnly Then
            Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
        Else
            Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
        End If
    End Using
End Sub

Obtención de una clave privada

Esta tarea establece el nombre del contenedor de claves con el nombre de la clave creada mediante el botón Create Keys. El contenedor de claves contendrá el par de claves completo con los parámetros privados.

Esta tarea simula un escenario en que Alicia usa su clave privada para descifrar archivos cifrados por Roberto.

Agregue el siguiente código como controlador de eventos Click del botón Get Private Key (buttonGetPrivateKey_Click).

private void buttonGetPrivateKey_Click(object sender, EventArgs e)
{
    _cspp.KeyContainerName = KeyName;
    _rsa = new RSACryptoServiceProvider(_cspp)
    {
        PersistKeyInCsp = true
    };

    label1.Text = _rsa.PublicOnly
        ? $"Key: {_cspp.KeyContainerName} - Public Only"
        : $"Key: {_cspp.KeyContainerName} - Full Key Pair";
}
Private Sub buttonGetPrivateKey_Click(ByVal sender As Object,
    ByVal e As EventArgs) Handles buttonGetPrivateKey.Click
    _cspp.KeyContainerName = KeyName
    _rsa = New RSACryptoServiceProvider(_cspp) With {
        .PersistKeyInCsp = True
    }
    If _rsa.PublicOnly Then
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Public Only"
    Else
        Label1.Text = $"Key: {_cspp.KeyContainerName} - Full Key Pair"
    End If
End Sub

Prueba de la aplicación

Después de haber compilado la aplicación, ejecute los siguientes escenarios de prueba.

Para crear claves, cifrar y descifrar

  1. Haga clic en el botón Create Keys. La etiqueta muestra el nombre de la clave e indica que se trata de un par de claves completo.
  2. Haga clic en el botón Export Public Key. Tenga en cuenta que al exportar los parámetros de la clave pública no se cambia la clave actual.
  3. Haga clic en el botón Encrypt File y seleccione un archivo.
  4. Haga clic en el botón Decrypt File y seleccione el archivo que acaba de cifrar.
  5. Examine el archivo que acaba de descifrar.
  6. Cierre la aplicación y reiníciela para intentar recuperar los contenedores de claves persistentes en el siguiente escenario.

Para cifrar con la clave pública

  1. Haga clic en el botón Import Public Key. La etiqueta muestra el nombre de la clave e indica que solo es pública.
  2. Haga clic en el botón Encrypt File y seleccione un archivo.
  3. Haga clic en el botón Decrypt File y seleccione el archivo que acaba de cifrar. Esto generará un error porque debe disponer de la clave privada para efectuar el descifrado.

En este escenario se muestra una situación en la que solo se dispone de la clave pública para cifrar un archivo para otra persona. Normalmente, esa persona debe proporcionarle únicamente la clave pública y conservar la clave privada para el descifrado.

Para descifrar con la clave privada

  1. Haga clic en el botón Get Private Key. La etiqueta muestra el nombre de la clave e indica si se trata del par de claves completo.
  2. Haga clic en el botón Decrypt File y seleccione el archivo que acaba de cifrar. Esta acción se llevará a cabo correctamente porque dispone del par de claves completo para efectuar el descifrado.

Consulte también