Tutorial: Cifrado y descifrado de cadenas en Visual Basic

En este tutorial se muestra cómo usar la TripleDES clase para cifrar y descifrar cadenas mediante el algoritmo Triple Data Encryption Standard (3DES). El primer paso es crear una clase contenedora sencilla que encapsula el algoritmo 3DES y almacena los datos cifrados como una cadena codificada en base 64. A continuación, ese contenedor se usa para almacenar de forma segura los datos de usuario privados en un archivo de texto accesible públicamente.

Puede usar el cifrado para proteger los secretos de usuario (por ejemplo, contraseñas) y para que los usuarios no autorizados puedan leer las credenciales. El cifrado puede evitar el robo de la identidad de un usuario autorizado, lo que protege los recursos de ese usuario y evita el repudio. El cifrado también puede proteger los datos de un usuario del acceso a los usuarios no autorizados.

Para más información, vea Servicios criptográficos.

Importante

Los algoritmos Rijndael (ahora denominados Advanced Encryption Standard [AES]) y Triple Data Encryption Standard (3DES) proporcionan una mayor seguridad que DES porque son más intensivos de cálculo. Para obtener más información, vea DES y Rijndael.

Para crear la envoltura de cifrado

  1. Cree la Simple3Des clase para encapsular los métodos de cifrado y descifrado.

    Public NotInheritable Class Simple3Des
    End Class
    
  2. Agregue una importación del espacio de nombres de criptografía al inicio del archivo que contiene la Simple3Des clase .

    Imports System.Security.Cryptography
    
  3. En la Simple3Des clase , agregue campos privados para almacenar el proveedor de servicios criptográficos 3DES, la clave especificada y la versión de formato, el tamaño de sal y el recuento de iteraciones.

    Private TripleDes As TripleDES = TripleDES.Create()
    
    Private Const FormatVersion As Byte = 1
    Private Const SaltSize As Integer = 16
    Private Const Iterations As Integer = 600000
    Private ReadOnly Key As String
    
  4. Agregue un método privado que cree una matriz de bytes a partir de la clave especificada y una sal.

    Private Function DeriveKey(ByVal salt() As Byte) As Byte()
        ' Derive a key from the specified key and the salt.
        Using kdf As New Rfc2898DeriveBytes(
            Key, salt, Iterations, HashAlgorithmName.SHA256)
    
            Return kdf.GetBytes(TripleDes.KeySize \ 8)
        End Using
    End Function
    
  5. Agregue un constructor que almacene la clave especificada.

    El key parámetro controla los EncryptData métodos y DecryptData .

    Sub New(ByVal key As String)
        ' Store the key. The encryption key and IV are created per message.
        Me.Key = key
    End Sub
    
  6. Agregue un método público que cifre una cadena.

    Public Function EncryptData( 
        ByVal plaintext As String) As String
    
        ' Create a new salt and initialization vector for this message.
        Dim salt(SaltSize - 1) As Byte
        Using rng As RandomNumberGenerator = RandomNumberGenerator.Create()
            rng.GetBytes(salt)
        End Using
    
        TripleDes.Key = DeriveKey(salt)
        TripleDes.GenerateIV()
    
        ' Convert the plaintext string to a byte array.
        Dim plaintextBytes() As Byte = 
            System.Text.Encoding.Unicode.GetBytes(plaintext)
    
        ' Create the stream.
        Dim ms As New System.IO.MemoryStream
        ' Write the format version, salt, and initialization vector in front of
        ' the cipher text. The version identifies the salt length and iteration count.
        ms.WriteByte(FormatVersion)
        ms.Write(salt, 0, salt.Length)
        ms.Write(TripleDes.IV, 0, TripleDes.IV.Length)
    
        ' Create the encoder to write to the stream.
        Dim encStream As New CryptoStream(ms, 
            TripleDes.CreateEncryptor(), 
            System.Security.Cryptography.CryptoStreamMode.Write)
    
        ' Use the crypto stream to write the byte array to the stream.
        encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
        encStream.FlushFinalBlock()
    
        ' Convert the encrypted stream to a printable string.
        Return Convert.ToBase64String(ms.ToArray)
    End Function
    
  7. Agregue un método público que descifre una cadena.

    Public Function DecryptData( 
        ByVal encryptedtext As String) As String
    
        ' Convert the encrypted text string to a byte array.
        Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedtext)
    
        ' Read the header that precedes the cipher text. Only one format
        ' version exists, so reject anything else.
        Dim ivSize As Integer = TripleDes.BlockSize \ 8
        Dim headerSize As Integer = 1 + SaltSize + ivSize
        If encryptedBytes.Length < headerSize OrElse
            encryptedBytes(0) <> FormatVersion Then
    
            Throw New CryptographicException(
                "The encrypted data is not in the expected format.")
        End If
    
        Dim salt(SaltSize - 1) As Byte
        Dim iv(ivSize - 1) As Byte
        Array.Copy(encryptedBytes, 1, salt, 0, SaltSize)
        Array.Copy(encryptedBytes, 1 + SaltSize, iv, 0, ivSize)
    
        TripleDes.Key = DeriveKey(salt)
        TripleDes.IV = iv
    
        ' Create the stream.
        Dim ms As New System.IO.MemoryStream
        ' Create the decoder to write to the stream.
        Dim decStream As New CryptoStream(ms, 
            TripleDes.CreateDecryptor(), 
            System.Security.Cryptography.CryptoStreamMode.Write)
    
        ' Use the crypto stream to write the byte array to the stream.
        decStream.Write(encryptedBytes, headerSize, 
            encryptedBytes.Length - headerSize)
        decStream.FlushFinalBlock()
    
        ' Convert the plaintext stream to a string.
        Return System.Text.Encoding.Unicode.GetString(ms.ToArray)
    End Function
    

    La clase de envoltura ahora puede utilizarse para proteger los activos de los usuarios. En este ejemplo, se usa para almacenar de forma segura datos de usuario privados en un archivo de texto accesible públicamente.

Para probar el contenedor de cifrado

  1. En una clase independiente, agregue un método que use el método del EncryptData contenedor para cifrar una cadena y escribirla en la carpeta Mis Documentos del usuario.

    Sub TestEncoding()
        Dim plainText As String = InputBox("Enter the plain text:")
        Dim password As String = InputBox("Enter the password:")
    
        Dim wrapper As New Simple3Des(password)
        Dim cipherText As String = wrapper.EncryptData(plainText)
    
        MsgBox("The cipher text is: " & cipherText)
        My.Computer.FileSystem.WriteAllText( 
            My.Computer.FileSystem.SpecialDirectories.MyDocuments & 
            "\cipherText.txt", cipherText, False)
    End Sub
    
  2. Añada un método que lea la cadena encriptada de la carpeta de Documentos del usuario y descifre la cadena usando el método del wrapper DecryptData.

    Sub TestDecoding()
        Dim cipherText As String = My.Computer.FileSystem.ReadAllText( 
            My.Computer.FileSystem.SpecialDirectories.MyDocuments & 
                "\cipherText.txt")
        Dim password As String = InputBox("Enter the password:")
        Dim wrapper As New Simple3Des(password)
    
        ' DecryptData throws if the wrong password is used.
        Try
            Dim plainText As String = wrapper.DecryptData(cipherText)
            MsgBox("The plain text is: " & plainText)
        Catch ex As System.Security.Cryptography.CryptographicException
            MsgBox("The data could not be decrypted with the password.")
        End Try
    End Sub
    
  3. Agregue código de interfaz de usuario para llamar a los métodos TestEncoding y TestDecoding.

  4. Ejecute la aplicación.

    Al probar la aplicación, observe que no descifrará los datos si proporciona la contraseña incorrecta.

Consulte también