Cómo cifrar y descifrar un archivo mediante Visual C#

Para una versión de Microsoft Visual Basic .NET de este artículo, vea 301070 .

En este artículo se refiere a los siguientes espacios de nombres de biblioteca de clases de Microsoft.NET Framework:
  • System.IO
  • System.Security
  • System.Security.Cryptography
Nota: En este artículo no se aplica a la de Microsoft.NET Framework 2.0.

Resumen

En este artículo describiremos cómo utilizar las clases de cifrado proporcionadas por el de Microsoft.NET Framework para cifrar un archivo de texto en un estado ilegible y para descifrar ese archivo de texto vuelva a su formato original.

Requisitos

La lista siguiente describe el hardware recomendado, software, infraestructura de red y los service packs que debe tener:
  • Microsoft Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server, Windows NT 4.0 Server o Microsoft Windows XP Professional
  • Microsoft Visual Studio 2005 o Microsoft Visual Studio .NET

Cifrado y descifrado

El espacio de nombres System.Security.Cryptographic en el Microsoft.NET Framework proporciona diversas herramientas para ayudarle con el cifrado y el descifrado. La clase CryptoStream es una de las numerosas clases que se proporciona. La clase CryptoStream está diseñada para cifrar o descifrar el contenido a medida que se transmite en secuencias a un archivo.

Cifrar un archivo

Para cifrar un archivo, siga estos pasos:
  1. Inicie Visual Studio .NET o Visual Studio 2005.
  2. Haga clic en Visual C# en
    Proyectosy, a continuación, haga clic en Aplicación de consolaen plantillas. Visual C# .NET crea una clase Static junto con un procedimiento Main() vacío.
  3. Utilice la instrucción using (como se indica en el siguiente código de ejemplo) en los espacios de nombres siguientes:
    • Sistema
    • System.Security
    • System.Security.Cryptography
    • System.Text
    • System.IO
    para que no tenga que suministrar declaraciones de estos espacios de nombres más adelante en el código. Debe utilizar estas instrucciones antes que cualquier otra declaración.
    using System;using System.IO;
    using System.Security;
    using System.Security.Cryptography;
    using System.Runtime.InteropServices;
    using System.Text;

  4. Genere una clave secreta para cifrar y descifrar los datos. DESCryptoServiceProvider se basa en un algoritmo de cifrado simétrico. El cifrado simétrico requiere una clave y un vector de inicialización (IV) para cifrar los datos. Para descifrar los datos, debe tener la misma clave y el mismo IV. También debe utilizar el mismo algoritmo de cifrado. Puede generar las claves mediante cualquiera de los métodos siguientes:
    • Método 1 Puede solicitar al usuario una contraseña. A continuación, utilice la contraseña como la clave y el IV.
    • Método 2 Cuando se crea una nueva instancia de las clases de cifrado simétricas, se crean automáticamente una nueva clave y un IV para la sesión. Utilice la clave y el IV generados por las clases cifradas simétricas administradas para cifrar y descifrar el archivo.

      Para obtener más información acerca de cómo generar y distribuir claves, consulte la documentación del SDK de.NET Framework de Microsoft o consulte el siguiente sitio Web de Microsoft Developer Network (MSDN):
  5. Agregue la siguiente función para generar una nueva clave para una sesión (como se indica en el método 2 del paso 4):
    //  Call this function to remove the key from memory after use for security.[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")]
    public static extern bool ZeroMemory(ref string Destination, int Length);

    // Function to Generate a 64 bits Key.
    static string GenerateKey()
    {
    // Create an instance of Symetric Algorithm. Key and IV is generated automatically.
    DESCryptoServiceProvider desCrypto =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();

    // Use the Automatically generated key for Encryption.
    return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
    }
  6. Cree un método en la clase que se denomina EncryptFile. La clase EncryptFile debe tener los tres parámetros siguientes:
    • sInputFilename
    • sOutputFilename
    • sKey (La clave secreta que se utiliza para cifrar y descifrar el archivo.)
    static void EncryptFile(string sInputFilename,string sOutputFilename,
    string sKey)

  7. En el procedimiento EncryptFile , cree un objeto FileStream de entrada y salida de un objeto FileStream . Estos objetos pueden ser leídos desde y escritos a los archivos de destino.
    FileStream fsInput = new FileStream(sInputFilename, FileMode.Open, 
    FileAccess.Read);

    FileStream fsEncrypted = new FileStream(sOutputFilename,
    FileMode.Create,
    FileAccess.Write);

  8. Declare una instancia de la clase DESCryptoServiceProvider . Esto representa el cifrado real y la tecnología de descifrado real que se utiliza en los archivos. En este punto, puede crear un proveedor diferente si prefiere utilizar RSAsecutiry u otra técnica de cifrado.
    DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
  9. El proveedor de servicios criptográfico deberá estar provisto de la clave secreta como una matriz de bytes. El espacio de nombres System.Text proporciona una función denominada GetBytes(). Como parte de sus características de codificación, el método GetBytes() toma una cadena y, a continuación, devuelve una matriz de bytes. El tamaño de la clave es diferente para cada técnica de cifrado. Por ejemplo, estándar de cifrado de datos (DES) toma una clave de 64 bits que es igual a 8 bytes o a 8 caracteres.

    Si no proporciona ninguna clave, el proveedor genera una aleatoriamente. Esto cifra correctamente el archivo, pero no existe forma de descifrar el archivo. Tenga en cuenta que también debe proporcionar el vector de inicialización (IV). Este valor se utiliza como parte del cifrado. Al igual que la clave, el IV se genera aleatoriamente si no proporciona el valor. Dado que los valores deben ser los mismos para el cifrado y el descifrado, no debe permitir la generación aleatoria de estos valores.
    DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);

  10. Cree una instancia de la clase CryptoStream utilizando el proveedor de servicios criptográfico para obtener un objeto de cifrado (CreateEncryptor) y el objeto de salida existente FileStream como parte del constructor.
    ICryptoTransform desencrypt = DES.CreateEncryptor();CryptoStream cryptostream = new CryptoStream(fsEncrypted, 
    desencrypt,
    CryptoStreamMode.Write);

  11. Leer en el archivo de entrada y, a continuación, escribir en el archivo de salida. Pasar a través del objeto CryptoStream donde el archivo se cifra mediante la clave que proporcionó.
    byte[] bytearrayinput = new byte[fsInput.Length - 1];fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
    cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);

Descifrar un archivo

Para descifrar un archivo, siga estos pasos:
  1. Cree un método y, a continuación, asígnele el nombre
    DecryptFile. El proceso de descifrado es similar al proceso de cifrado, sin embargo, el procedimiento DecryptFile tiene dos diferencias respecto al procedimiento EncryptFile .
    • CreateDecryptor se utiliza en lugar de CreateEncryptor para crear el objeto CryptoStream , que especifica cómo se puede utilizar el objeto.
    • Cuando el texto descifrado se escribe en el archivo de destino, el objeto CryptoStream es ahora el origen en lugar de la secuencia de destino.
    static void DecryptFile(string sInputFilename,                 string sOutputFilename,
    string sKey)
    {
    DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
    //A 64 bit key and IV is required for this provider.
    //Set secret key For DES algorithm.
    DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
    //Set initialization vector.
    DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);

    //Create a file stream to read the encrypted file back.
    FileStream fsread = new FileStream(sInputFilename,
    FileMode.Open,
    FileAccess.Read);
    //Create a DES decryptor from the DES instance.
    ICryptoTransform desdecrypt = DES.CreateDecryptor();
    //Create crypto stream set to read and do a
    //DES decryption transform on incoming bytes.
    CryptoStream cryptostreamDecr = new CryptoStream(fsread,
    desdecrypt,
    CryptoStreamMode.Read);
    //Print the contents of the decrypted file.
    StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
    fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
    fsDecrypted.Flush();
    fsDecrypted.Close();
    }

  2. Agregue las líneas siguientes al procedimiento Main() para llamar a EncryptFile y DecryptFile:
    static void Main(){
    // Must be 64 bits, 8 bytes.
    // Distribute this key to the user who will decrypt this file.
    string sSecretKey;

    // Get the key for the file to encrypt.
    sSecretKey = GenerateKey();

    // For additional security pin the key.
    GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );

    // Encrypt the file.
    EncryptFile(@"C:\MyData.txt",
    @"C:\Encrypted.txt",
    sSecretKey);

    // Decrypt the file.
    DecryptFile(@"C:\Encrypted.txt",
    @"C:\Decrypted.txt",
    sSecretKey);

    // Remove the key from memory.
    ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
    gch.Free();
    }
  3. Guarde el archivo. Ejecutar la aplicación. Asegúrese de que la ruta de acceso que se utiliza para el nombre de archivo de entrada señala a un archivo existente.

El procedimiento de prueba

Pruebe este código con un archivo de texto (.txt) para confirmar que el código cifró y descifró el archivo correctamente. Asegúrese de que descifra el archivo en un archivo nuevo (como en el procedimiento Main() en este artículo) en lugar de en el archivo original. Examine el archivo descifrado y compárelo con el archivo original.

Lista de código completa

using System;using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using System.Text;

namespace CSEncryptDecrypt
{
class Class1
{
// Call this function to remove the key from memory after use for security
[System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")]
public static extern bool ZeroMemory(IntPtr Destination, int Length);

// Function to Generate a 64 bits Key.
static string GenerateKey()
{
// Create an instance of Symetric Algorithm. Key and IV is generated automatically.
DESCryptoServiceProvider desCrypto =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();

// Use the Automatically generated key for Encryption.
return ASCIIEncoding.ASCII.GetString(desCrypto.Key);
}

static void EncryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
FileStream fsInput = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);

FileStream fsEncrypted = new FileStream(sOutputFilename,
FileMode.Create,
FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream = new CryptoStream(fsEncrypted,
desencrypt,
CryptoStreamMode.Write);

byte[] bytearrayinput = new byte[fsInput.Length];
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}

static void DecryptFile(string sInputFilename,
string sOutputFilename,
string sKey)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
//A 64 bit key and IV is required for this provider.
//Set secret key For DES algorithm.
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
//Set initialization vector.
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);

//Create a file stream to read the encrypted file back.
FileStream fsread = new FileStream(sInputFilename,
FileMode.Open,
FileAccess.Read);
//Create a DES decryptor from the DES instance.
ICryptoTransform desdecrypt = DES.CreateDecryptor();
//Create crypto stream set to read and do a
//DES decryption transform on incoming bytes.
CryptoStream cryptostreamDecr = new CryptoStream(fsread,
desdecrypt,
CryptoStreamMode.Read);
//Print the contents of the decrypted file.
StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
fsDecrypted.Flush();
fsDecrypted.Close();
}

static void Main()
{
// Must be 64 bits, 8 bytes.
// Distribute this key to the user who will decrypt this file.
string sSecretKey;

// Get the Key for the file to Encrypt.
sSecretKey = GenerateKey();

// For additional security Pin the key.
GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );

// Encrypt the file.
EncryptFile(@"C:\MyData.txt",
@"C:\Encrypted.txt",
sSecretKey);

// Decrypt the file.
DecryptFile(@"C:\Encrypted.txt",
@"C:\Decrypted.txt",
sSecretKey);

// Remove the Key from memory.
ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
gch.Free();
}
}
}

Referencias

Para obtener más información acerca de la criptografía y sobre el uso de las características de cifrado de. NET, consulte los siguientes sitios Web de MSDN:
Propiedades

Id. de artículo: 307010 - Última revisión: 22 ene. 2017 - Revisión: 1

Microsoft Visual C# 2005, Microsoft Visual C# .NET 2003 Standard Edition, Microsoft Visual C# .NET 2002 Standard Edition

Comentarios