Uso de Visual C# para calcular y comparar valores hash

En este artículo paso a paso se muestra cómo obtener un valor hash y cómo comparar dos valores hash para comprobar si son idénticos mediante Visual C#. También proporciona un ejemplo de código para mostrar cómo realizar esta tarea.

Versión original del producto: Visual C#
Número de KB original: 307020

Resumen

En este artículo se hace referencia a los siguientes espacios de nombres de la biblioteca de clases de Microsoft .NET Framework:

  • System.Security.Cryptography
  • System.Text

La System.Security.Cryptography clase de .NET Framework facilita el proceso de un valor hash para los datos de origen.

Calcular un valor hash

Es fácil generar y comparar valores hash mediante los recursos criptográficos contenidos en el System.Security.Cryptography espacio de nombres. Dado que todas las funciones hash toman la entrada de tipo Byte[], es posible que sea necesario convertir el origen en una matriz de bytes antes de que se realice el hash. Para crear un hash para un valor de cadena, siga estos pasos:

  1. Abra Visual Studio .NET o Visual Studio.

  2. Crear una nueva aplicación de consola en Visual C# .NET o en Visual C# crea una clase pública junto con un método vacío Main() .

    Nota:

    En Visual C#. NET, Class1.cs se crea de forma predeterminada. En Visual C#, Program.cs se crea de forma predeterminada.

  3. Use la using directiva en los Systemespacios de nombres , System.Security.Cryptographyy System.Text para que no sea necesario calificar las declaraciones de estos espacios de nombres más adelante en el código. Estas instrucciones deben usarse antes que cualquier otra declaración.

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
  4. Declare una variable de cadena para contener los datos de origen y dos matrices de bytes (de tamaño no definido) para contener los bytes de origen y el valor hash resultante.

    string sSourceData;
    byte[] tmpSource;
    byte[] tmpHash;
    
  5. Use el GetBytes() método de la clase para convertir la System.Text.ASCIIEncoding cadena de origen en una matriz de bytes (necesaria como entrada para la función de hash).

    sSourceData = "MySourceData";
    //Create a byte array from source data.
    tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
    
  6. Calcule el hash MD5 para los datos de origen llamando a ComputeHash en una instancia de la MD5CryptoServiceProvider clase .

    Nota:

    Para calcular otro valor hash, deberá crear otra instancia de la clase .

    //Compute hash based on source data.
    tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
    
  7. La tmpHash matriz de bytes ahora contiene el valor hash calculado (valor de 128 bits=16 bytes) para los datos de origen. A menudo resulta útil mostrar o almacenar un valor como este como una cadena hexadecimal, que el código siguiente realiza:

    Console.WriteLine(ByteArrayToString(tmpHash));
    static string ByteArrayToString(byte[] arrInput)
    {
        int i;
        StringBuilder sOutput = new StringBuilder(arrInput.Length);
        for (i=0;i < arrInput.Length; i++)
        {
            sOutput.Append(arrInput[i].ToString("X2"));
        }
        return sOutput.ToString();
    }
    
  8. Guarde y ejecute el código para ver la cadena hexadecimal resultante para el valor de origen.

Comparación de dos valores hash

Los propósitos de crear un hash a partir de datos de origen son:

  • Proporcionar una manera de ver si los datos han cambiado con el tiempo.
  • Comparar dos valores sin trabajar nunca con los valores reales.

En cualquier caso, debe comparar dos hashes calculados. Es fácil si ambos se almacenan como cadenas hexadecimales (como en el último paso de la sección anterior). Pero es posible que ambos estén en forma de matrices de bytes. El código siguiente, que continúa a partir del código creado en la sección anterior, muestra cómo comparar dos matrices de bytes.

  1. Justo debajo de la creación de una cadena hexadecimal, cree un nuevo valor hash basado en nuevos datos de origen.

    sSourceData = "NotMySourceData";
    tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
    byte[] tmpNewHash;
    tmpNewHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
    
  2. La manera más sencilla de comparar dos matrices de bytes es recorrer en bucle las matrices, comparando cada elemento individual con su homólogo del segundo valor. Si algún elemento es diferente o si las dos matrices no tienen el mismo tamaño, los dos valores no son iguales.

    bool bEqual = false;
    if (tmpNewHash.Length == tmpHash.Length)
    {
        int i=0;
        while ((i < tmpNewHash.Length) && (tmpNewHash[i] == tmpHash[i]))
        {
            i += 1;
        }
        if (i == tmpNewHash.Length)
        {
            bEqual = true;
        }
    }
    
    if (bEqual)
        Console.WriteLine("The two hash values are the same");
    else
        Console.WriteLine("The two hash values are not the same");
    Console.ReadLine();
    
  3. Guarde y ejecute el proyecto para ver la cadena hexadecimal creada a partir del primer valor hash. Averigüe si el nuevo hash es igual al original.

Lista de código completa

using System;
using System.Security.Cryptography;
using System.Text;

namespace ComputeAHash_csharp
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
        static void Main(string[] args)
        {
            string sSourceData;
            byte[] tmpSource;
            byte[] tmpHash;
            sSourceData = "MySourceData";
            //Create a byte array from source data
            tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);

            //Compute hash based on source data
            tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
            Console.WriteLine(ByteArrayToString(tmpHash));

            sSourceData = "NotMySourceData";
            tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);

            byte[] tmpNewHash;

            tmpNewHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);

            bool bEqual = false;
            if (tmpNewHash.Length == tmpHash.Length)
            {
                int i=0;
                while ((i < tmpNewHash.Length) && (tmpNewHash[i] == tmpHash[i]))
                {
                    i += 1;
                }
                if (i == tmpNewHash.Length)
                {
                    bEqual = true;
                }
            }

            if (bEqual)
                Console.WriteLine("The two hash values are the same");
            else
                Console.WriteLine("The two hash values are not the same");
            Console.ReadLine();
        }

        static string ByteArrayToString(byte[] arrInput)
        {
            int i;
            StringBuilder sOutput = new StringBuilder(arrInput.Length);
            for (i=0;i < arrInput.Length -1; i++)
            {
                sOutput.Append(arrInput[i].ToString("X2"));
            }
            return sOutput.ToString();
        }
    }
}

Referencias

Para obtener más información sobre cómo usar las características criptográficas de .NET Framework, vea .NET.