Толик Панков
hex_laden
............ .................. ................
October 2025
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Толик Панков [userpic]
C#, получение хэша (fingerprint) сертификата X509.

Преамбула


Понадобилось проверить сертификат X509 на целостность и подлинность. Поставщик сертификата отдельно передает его fingerprint и алгоритм хэширования по которому тот вычисляется.

Судя по документации от MS, получить fingerprint, он же хэш, можно функцией GetCertHashString() (или GetCertHash() в виде массива байт) класса X509Certificate2, однако, в .NET 2.0 отсутствует перегрузка функции GetCertHashString(HashAlgorithmName), которая позволяет выбрать алгоритм хеширования (GetCertHashString() возвращает хэш SHA1). Потому сделаем руками, благо ничего сложного в этом нет.

Получение fingerprint


1. Подключаем в References System.Security.Cryptography
2. Подключаем необходимые пространства имен в классе:

using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;


3. Загружать сертификат будем из файла, потому проверяем его наличие:

if (!File.Exists(CertFile))
{
    Console.WriteLine("File not found.");
    return null;
}


4. Загружаем сертификат (создаем экземпляр класса X509Certificate2). Если вдруг файл сертификата поврежден, то конструктор X509Certificate2 вызовет Exception Требуемый объект не найден. Поэтому конструктор надо обернуть в try...catch:

try
{
    X509 = new X509Certificate2(CertFile);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
    return null;
}


5. Получаем загруженный сертификат в виде массива байт:

byte[] cert = X509.GetRawCertData();

6. Создаем объект HashAlgorithm, который и займется вычислением хэша/fingerprint'а. Я завел в функции входную переменную AlgName, куда записывается строка с названием алгоритма, что бы иметь возможность выбора алгоритма хэширования если что:

HashAlgorithm alg = null;
switch (AlgName.ToUpperInvariant())
{
    case "MD5": alg = MD5.Create(); break;
    case "SHA1": alg = SHA1.Create(); break;
    case "SHA256": alg = SHA256.Create(); break;
    case "SHA384": alg = SHA384.Create(); break;
    case "SHA512": alg = SHA512.Create(); break;
    default:
        {
            Console.WriteLine("Unknow algorithm.");
            return null;
        }
}


7. Получаем хэш в виде массива байт:

byte[] hash = alg.ComputeHash(cert);

8. Преобразуем массив байт в строку шестнадцатеричных чисел:

string hex = BitConverter.ToString(hash).ToLowerInvariant().
    Replace("-", "");


ToLowerInvariant() преобразует буквы в строке, полученной BitConverter в строчные, а Replace("-", "") удаляет разделители (-) между значениями байтов, которые BitConverter вставляет в строку.

Код функции целиком
Тестовый пример на GitHub

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/01/09/c-poluchenie-hesha-fingerprint-sertifikata-x509/

Tags: ,