Использование Visual C# для вычисления и сравнения хэш-значений

В этой пошаговой статье показано, как получить хэш-значение и сравнить два хэш-значения с проверка, совпадают ли они с помощью Visual C#. В нем также представлен пример кода, показывающий, как выполнить эту задачу.

Исходная версия продукта: Visual C#
Оригинальный номер базы знаний: 307020

Сводка

В этой статье рассматриваются следующие пространства имен библиотеки классов Microsoft платформа .NET Framework:

  • System.Security.Cryptography
  • System.Text

Класс System.Security.Cryptography в платформа .NET Framework упрощает вычисление хэш-значения для исходных данных.

Вычисление хэш-значения

С помощью криптографических ресурсов, содержащихся в System.Security.Cryptography пространстве имен, легко создавать и сравнивать хэш-значения. Так как все хэш-функции принимают входные данные типа Byte[], может потребоваться преобразовать источник в массив байтов, прежде чем он будет хэширован. Чтобы создать хэш для строкового значения, выполните следующие действия.

  1. Откройте Visual Studio .NET или Visual Studio.

  2. Создание консольного приложения в Visual C# .NET или Visual C# создает открытый класс вместе с пустым Main() методом.

    Примечание.

    В Visual C#. NET, Class1.cs создается по умолчанию. В Visual C# Program.cs создается по умолчанию.

  3. Используйте директиву usingSystemдля пространств имен , System.Security.Cryptographyи System.Text , чтобы позже в коде не требовалось определять объявления из этих пространств имен. Эти инструкции должны использоваться перед любыми другими объявлениями.

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
  4. Объявите строковую переменную для хранения исходных данных и два массива байтов (неопределенного размера) для хранения исходных байтов и полученного хэш-значения.

    string sSourceData;
    byte[] tmpSource;
    byte[] tmpHash;
    
  5. GetBytes() Используйте метод класса , System.Text.ASCIIEncoding чтобы преобразовать исходную строку в массив байтов (требуется в качестве входных данных для функции хэширования).

    sSourceData = "MySourceData";
    //Create a byte array from source data.
    tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
    
  6. Вычислить хэш MD5 для исходных данных путем вызова ComputeHash для экземпляра MD5CryptoServiceProvider класса .

    Примечание.

    Чтобы вычислить другое хэш-значение, необходимо создать другой экземпляр класса .

    //Compute hash based on source data.
    tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
    
  7. Массив tmpHash байтов теперь содержит вычисляемое хэш-значение (128-битовое значение=16 байт) для исходных данных. Часто полезно отобразить или сохранить подобное значение в виде шестнадцатеричной строки, которую выполняет следующий код:

    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. Сохраните и запустите код, чтобы просмотреть полученную шестнадцатеричную строку для исходного значения.

Сравнение двух хэш-значений

Цели создания хэша на основе исходных данных:

  • Предоставление способа узнать, изменялись ли данные с течением времени.
  • Сравнение двух значений без работы с фактическими значениями.

В любом случае необходимо сравнить два вычисляемых хэша. Это легко сделать, если они хранятся в виде шестнадцатеричных строк (как на последнем шаге выше). Но вполне возможно, что они оба будут в виде массивов байтов. В следующем коде, который продолжается из кода, созданного в предыдущем разделе, показано, как сравнить два массива байтов.

  1. Сразу под созданием шестнадцатеричной строки создайте новое хэш-значение на основе новых исходных данных.

    sSourceData = "NotMySourceData";
    tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
    byte[] tmpNewHash;
    tmpNewHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
    
  2. Самый простой способ сравнить два массива байтов — циклически просматривать массивы, сравнивая каждый отдельный элемент со своим аналогом из второго значения. Если какие-либо элементы отличаются или два массива имеют разный размер, эти два значения не равны.

    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. Сохраните и запустите проект, чтобы просмотреть шестнадцатеричную строку, созданную из первого хэш-значения. Узнайте, равен ли новый хэш исходному.

Полный список кода

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();
        }
    }
}

Ссылки

Дополнительные сведения об использовании криптографических функций платформа .NET Framework см. в разделе .NET.