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