807 lines
37 KiB
C#
807 lines
37 KiB
C#
using System.Security.Cryptography.X509Certificates;
|
||
using System.Text;
|
||
|
||
namespace CertificateChecker;
|
||
|
||
class Program
|
||
{
|
||
static async Task Main(string[] args)
|
||
{
|
||
Console.OutputEncoding = Encoding.UTF8;
|
||
Console.Title = "Certificate Manager";
|
||
|
||
while (true)
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗");
|
||
Console.WriteLine("║ УПРАВЛЕНИЕ СЕРТИФИКАТАМИ ║");
|
||
Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n");
|
||
|
||
Console.WriteLine(" 📋 ГЛАВНОЕ МЕНЮ:");
|
||
Console.WriteLine(new string('─', 80));
|
||
Console.WriteLine(" 1. 🔍 Проверить сертификаты");
|
||
Console.WriteLine(" 2. 📥 Установить сертификаты");
|
||
Console.WriteLine(" 3. 🗑️ Удалить сертификаты");
|
||
Console.WriteLine(" 4. 📊 Показать все установленные сертификаты");
|
||
Console.WriteLine(" 5. 🚪 Выход");
|
||
Console.WriteLine(new string('─', 80));
|
||
Console.Write("\n Ваш выбор: ");
|
||
|
||
var choice = Console.ReadLine();
|
||
|
||
switch (choice)
|
||
{
|
||
case "1":
|
||
await CheckCertificatesAsync();
|
||
break;
|
||
case "2":
|
||
await InstallCertificatesAsync();
|
||
break;
|
||
case "3":
|
||
await DeleteCertificatesAsync();
|
||
break;
|
||
case "4":
|
||
await ShowAllInstalledCertificatesAsync();
|
||
break;
|
||
case "5":
|
||
Console.WriteLine("\n До свидания! 👋");
|
||
return;
|
||
default:
|
||
Console.WriteLine("\n ❌ Неверный выбор. Нажмите любую клавишу...");
|
||
Console.ReadKey();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Проверка сертификатов
|
||
/// </summary>
|
||
static async Task CheckCertificatesAsync()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗");
|
||
Console.WriteLine("║ ПРОВЕРКА СЕРТИФИКАТОВ ║");
|
||
Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n");
|
||
|
||
var checker = new CertificateChecker();
|
||
|
||
Console.WriteLine("📂 Загрузка сертификатов из ресурсов...\n");
|
||
var certificates = checker.LoadCertificatesFromResources();
|
||
|
||
if (!certificates.Any())
|
||
{
|
||
Console.WriteLine("\n❌ Сертификаты не найдены в ресурсах.");
|
||
Console.WriteLine("\n💡 Проверьте:");
|
||
Console.WriteLine(" 1. Что файл Resources.resx существует");
|
||
Console.WriteLine(" 2. Что сертификаты добавлены как ресурсы (тип: byte[])");
|
||
Console.WriteLine(" 3. Что ключи ресурсов содержат: cert, ca, root или sub");
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"\n✅ Загружено сертификатов: {certificates.Count}\n");
|
||
Console.WriteLine(new string('═', 100));
|
||
|
||
// Проверяем каждый сертификат
|
||
var results = new List<CertificateCheckResult>();
|
||
|
||
for (int i = 0; i < certificates.Count; i++)
|
||
{
|
||
var cert = certificates[i];
|
||
Console.WriteLine($"\n🔍 Проверка сертификата #{i + 1}: {cert.FriendlyName}");
|
||
Console.WriteLine(new string('─', 80));
|
||
|
||
var result = await checker.CheckCertificateInstalledAsync(cert);
|
||
results.Add(result);
|
||
|
||
Console.WriteLine($" 📋 Имя: {result.FriendlyName}");
|
||
Console.WriteLine($" 🔑 Отпечаток: {result.Thumbprint}");
|
||
Console.WriteLine($" 📅 Действителен: {result.NotBefore:dd.MM.yyyy} → {result.NotAfter:dd.MM.yyyy}");
|
||
Console.WriteLine($" 📊 Статус: {(result.IsInstalled ? "✅ УСТАНОВЛЕН" : "❌ НЕ УСТАНОВЛЕН")}");
|
||
|
||
if (result.IsInstalled)
|
||
{
|
||
Console.WriteLine($" 📁 Хранилище: {result.StoreLocation}\\{result.StoreName}");
|
||
Console.WriteLine($" 🔒 Закрытый ключ: {(result.HasPrivateKey ? "✅ Есть" : "❌ Нет")}");
|
||
Console.WriteLine($" ✅ Цепочка: {(result.ChainValidationResult.IsValid ? "Действительна" : "Проблемы")}");
|
||
|
||
if (result.FoundInStores.Any())
|
||
{
|
||
Console.WriteLine($" 📂 Найден в хранилищах:");
|
||
foreach (var store in result.FoundInStores)
|
||
{
|
||
Console.WriteLine($" • {store}");
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" ⚠️ Сертификат не найден в системных хранилищах");
|
||
if (result.HasPrivateKey)
|
||
{
|
||
Console.WriteLine($" 💡 Сертификат содержит закрытый ключ и может быть импортирован");
|
||
}
|
||
}
|
||
|
||
var daysUntilExpiry = (result.NotAfter - DateTime.Now).Days;
|
||
if (daysUntilExpiry < 0)
|
||
{
|
||
Console.WriteLine($" ⚠️ СЕРТИФИКАТ ПРОСРОЧЕН на {Math.Abs(daysUntilExpiry)} дней!");
|
||
}
|
||
else if (daysUntilExpiry < 30)
|
||
{
|
||
Console.WriteLine($" ⚠️ Сертификат истекает через {daysUntilExpiry} дней");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" ℹ️ Сертификат действителен еще {daysUntilExpiry} дней");
|
||
}
|
||
}
|
||
|
||
// Выводим итоговую таблицу
|
||
Console.WriteLine("\n" + new string('═', 100));
|
||
Console.WriteLine("\n📊 ИТОГОВАЯ ТАБЛИЦА ПРОВЕРЕННЫХ СЕРТИФИКАТОВ");
|
||
Console.WriteLine(new string('═', 100));
|
||
|
||
PrintCertificateTable(results);
|
||
|
||
// Статистика
|
||
var installedCount = results.Count(r => r.IsInstalled);
|
||
var validCount = results.Count(r => r.IsValid);
|
||
var expiredCount = results.Count(r => r.NotAfter < DateTime.Now);
|
||
|
||
Console.WriteLine("\n" + new string('═', 100));
|
||
Console.WriteLine("\n📈 СТАТИСТИКА:");
|
||
Console.WriteLine($" • Всего сертификатов: {results.Count}");
|
||
Console.WriteLine($" • Установлено: {installedCount} ({(results.Count > 0 ? installedCount * 100 / results.Count : 0)}%)");
|
||
Console.WriteLine($" • Не установлено: {results.Count - installedCount} ({(results.Count > 0 ? (results.Count - installedCount) * 100 / results.Count : 0)}%)");
|
||
Console.WriteLine($" • Действительные: {validCount} ({(results.Count > 0 ? validCount * 100 / results.Count : 0)}%)");
|
||
Console.WriteLine($" • Просроченные: {expiredCount} ({(results.Count > 0 ? expiredCount * 100 / results.Count : 0)}%)");
|
||
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Установка сертификатов
|
||
/// </summary>
|
||
static async Task InstallCertificatesAsync()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗");
|
||
Console.WriteLine("║ УСТАНОВКА СЕРТИФИКАТОВ ║");
|
||
Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n");
|
||
|
||
var checker = new CertificateChecker();
|
||
|
||
Console.WriteLine("📂 Загрузка сертификатов из ресурсов...\n");
|
||
var certificates = checker.LoadCertificatesFromResources();
|
||
|
||
if (!certificates.Any())
|
||
{
|
||
Console.WriteLine("\n❌ Сертификаты не найдены в ресурсах.");
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"\n✅ Загружено сертификатов: {certificates.Count}\n");
|
||
|
||
// Проверяем, какие сертификаты уже установлены
|
||
var results = new List<CertificateCheckResult>();
|
||
foreach (var cert in certificates)
|
||
{
|
||
var result = await checker.CheckCertificateInstalledAsync(cert);
|
||
results.Add(result);
|
||
}
|
||
|
||
var missing = results.Where(r => !r.IsInstalled).ToList();
|
||
|
||
if (!missing.Any())
|
||
{
|
||
Console.WriteLine("✅ Все сертификаты уже установлены!");
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"🔧 Обнаружено {missing.Count} сертификатов для установки:\n");
|
||
|
||
for (int i = 0; i < missing.Count; i++)
|
||
{
|
||
var cert = missing[i];
|
||
Console.WriteLine($" {i + 1}. {cert.FriendlyName}");
|
||
Console.WriteLine($" Субъект: {cert.Subject}");
|
||
Console.WriteLine($" Действителен до: {cert.NotAfter:dd.MM.yyyy}");
|
||
Console.WriteLine();
|
||
}
|
||
|
||
Console.WriteLine(" Выберите действие:");
|
||
Console.WriteLine(" [1] Установить все");
|
||
Console.WriteLine(" [2] Выборочная установка");
|
||
Console.WriteLine(" [3] Отмена");
|
||
Console.Write("\n Ваш выбор: ");
|
||
|
||
var choice = Console.ReadLine();
|
||
|
||
if (choice == "1")
|
||
{
|
||
await InstallAllCertificatesAsync(checker, certificates, results);
|
||
}
|
||
else if (choice == "2")
|
||
{
|
||
await InstallSelectedCertificatesAsync(checker, certificates, results);
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("\n Установка отменена.");
|
||
}
|
||
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Удаление сертификатов
|
||
/// </summary>
|
||
static async Task DeleteCertificatesAsync()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗");
|
||
Console.WriteLine("║ УДАЛЕНИЕ СЕРТИФИКАТОВ ║");
|
||
Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n");
|
||
|
||
var checker = new CertificateChecker();
|
||
|
||
Console.WriteLine("📂 Загрузка сертификатов из ресурсов...\n");
|
||
var certificates = checker.LoadCertificatesFromResources();
|
||
|
||
if (!certificates.Any())
|
||
{
|
||
Console.WriteLine("\n❌ Сертификаты не найдены в ресурсах.");
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"\n✅ Загружено сертификатов: {certificates.Count}\n");
|
||
|
||
// Проверяем, какие сертификаты установлены
|
||
var results = new List<CertificateCheckResult>();
|
||
foreach (var cert in certificates)
|
||
{
|
||
var result = await checker.CheckCertificateInstalledAsync(cert);
|
||
results.Add(result);
|
||
}
|
||
|
||
var installed = results.Where(r => r.IsInstalled).ToList();
|
||
|
||
if (!installed.Any())
|
||
{
|
||
Console.WriteLine("⚠️ Нет установленных сертификатов для удаления!");
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"🔧 Обнаружено {installed.Count} установленных сертификатов:\n");
|
||
|
||
for (int i = 0; i < installed.Count; i++)
|
||
{
|
||
var cert = installed[i];
|
||
Console.WriteLine($" {i + 1}. {cert.FriendlyName}");
|
||
Console.WriteLine($" Субъект: {cert.Subject}");
|
||
Console.WriteLine($" Хранилище: {cert.StoreLocation}\\{cert.StoreName}");
|
||
Console.WriteLine($" Действителен до: {cert.NotAfter:dd.MM.yyyy}");
|
||
Console.WriteLine();
|
||
}
|
||
|
||
Console.WriteLine(" ⚠️ ВНИМАНИЕ! Удаление сертификатов может нарушить работу приложений!");
|
||
Console.WriteLine(" Выберите действие:");
|
||
Console.WriteLine(" [1] Удалить все");
|
||
Console.WriteLine(" [2] Выборочное удаление");
|
||
Console.WriteLine(" [3] Отмена");
|
||
Console.Write("\n Ваш выбор: ");
|
||
|
||
var choice = Console.ReadLine();
|
||
|
||
if (choice == "1")
|
||
{
|
||
await DeleteAllCertificatesAsync(checker, certificates, results);
|
||
}
|
||
else if (choice == "2")
|
||
{
|
||
await DeleteSelectedCertificatesAsync(checker, certificates, results);
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("\n Удаление отменено.");
|
||
}
|
||
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Показать все установленные сертификаты
|
||
/// </summary>
|
||
static async Task ShowAllInstalledCertificatesAsync()
|
||
{
|
||
Console.Clear();
|
||
Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗");
|
||
Console.WriteLine("║ ВСЕ УСТАНОВЛЕННЫЕ СЕРТИФИКАТЫ ║");
|
||
Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n");
|
||
|
||
var checker = new CertificateChecker();
|
||
var allCerts = new List<CertificateCheckResult>();
|
||
|
||
// Проверяем все хранилища
|
||
var stores = new[]
|
||
{
|
||
(StoreName.My, StoreLocation.CurrentUser, "Личные (CurrentUser)"),
|
||
(StoreName.My, StoreLocation.LocalMachine, "Личные (LocalMachine)"),
|
||
(StoreName.Root, StoreLocation.CurrentUser, "Доверенные корневые (CurrentUser)"),
|
||
(StoreName.Root, StoreLocation.LocalMachine, "Доверенные корневые (LocalMachine)"),
|
||
(StoreName.TrustedPeople, StoreLocation.CurrentUser, "Доверенные лица (CurrentUser)"),
|
||
(StoreName.TrustedPeople, StoreLocation.LocalMachine, "Доверенные лица (LocalMachine)"),
|
||
(StoreName.CertificateAuthority, StoreLocation.CurrentUser, "Промежуточные (CurrentUser)"),
|
||
(StoreName.CertificateAuthority, StoreLocation.LocalMachine, "Промежуточные (LocalMachine)")
|
||
};
|
||
|
||
Console.WriteLine("📂 Сканирование хранилищ...\n");
|
||
|
||
foreach (var (storeName, storeLocation, displayName) in stores)
|
||
{
|
||
try
|
||
{
|
||
using var store = new X509Store(storeName, storeLocation);
|
||
store.Open(OpenFlags.ReadOnly);
|
||
|
||
var certs = store.Certificates;
|
||
if (certs.Count > 0)
|
||
{
|
||
Console.WriteLine($"📁 {displayName} ({certs.Count} сертификатов):");
|
||
foreach (var cert in certs)
|
||
{
|
||
var result = new CertificateCheckResult
|
||
{
|
||
FriendlyName = string.IsNullOrEmpty(cert.FriendlyName) ? cert.Subject : cert.FriendlyName,
|
||
Subject = cert.Subject,
|
||
Issuer = cert.Issuer,
|
||
Thumbprint = cert.Thumbprint,
|
||
NotAfter = cert.NotAfter,
|
||
NotBefore = cert.NotBefore,
|
||
IsInstalled = true,
|
||
StoreName = storeName,
|
||
StoreLocation = storeLocation,
|
||
HasPrivateKey = cert.HasPrivateKey,
|
||
FoundCertificate = cert
|
||
};
|
||
allCerts.Add(result);
|
||
}
|
||
|
||
foreach (var cert in certs)
|
||
{
|
||
var name = string.IsNullOrEmpty(cert.FriendlyName) ? "Без имени" : cert.FriendlyName;
|
||
Console.WriteLine($" • {name}");
|
||
Console.WriteLine($" Отпечаток: {cert.Thumbprint.Substring(0, 16)}...");
|
||
Console.WriteLine($" Действителен до: {cert.NotAfter:dd.MM.yyyy}");
|
||
Console.WriteLine($" Закрытый ключ: {(cert.HasPrivateKey ? "✅ Есть" : "❌ Нет")}");
|
||
Console.WriteLine();
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// Пропускаем недоступные хранилища
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n📊 Всего найдено: {allCerts.Count} сертификатов");
|
||
|
||
// Статистика
|
||
var withPrivateKey = allCerts.Count(c => c.HasPrivateKey);
|
||
var expired = allCerts.Count(c => c.NotAfter < DateTime.Now);
|
||
|
||
Console.WriteLine($" • С закрытым ключом: {withPrivateKey}");
|
||
Console.WriteLine($" • Просроченных: {expired}");
|
||
|
||
Console.WriteLine("\nНажмите любую клавишу для возврата в меню...");
|
||
Console.ReadKey();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Установка всех сертификатов
|
||
/// </summary>
|
||
static async Task InstallAllCertificatesAsync(CertificateChecker checker, List<X509Certificate2> certificates, List<CertificateCheckResult> results)
|
||
{
|
||
Console.WriteLine("\n🔧 НАЧАЛО УСТАНОВКИ ВСЕХ СЕРТИФИКАТОВ...");
|
||
Console.WriteLine(new string('─', 80));
|
||
|
||
var successCount = 0;
|
||
var failCount = 0;
|
||
|
||
for (int i = 0; i < certificates.Count; i++)
|
||
{
|
||
var cert = certificates[i];
|
||
var result = results[i];
|
||
|
||
if (!result.IsInstalled)
|
||
{
|
||
Console.WriteLine($"\n 📥 Установка сертификата: {cert.FriendlyName}");
|
||
Console.WriteLine($" Субъект: {cert.Subject}");
|
||
|
||
var installResult = await checker.InstallCertificateWithAutoStoreAsync(cert);
|
||
|
||
if (installResult.Success)
|
||
{
|
||
successCount++;
|
||
Console.WriteLine($" ✅ Успешно установлен");
|
||
foreach (var msg in installResult.Messages)
|
||
{
|
||
Console.WriteLine($" {msg}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
failCount++;
|
||
Console.WriteLine($" ❌ Ошибка установки");
|
||
foreach (var msg in installResult.Messages)
|
||
{
|
||
Console.WriteLine($" {msg}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n 📊 ИТОГО УСТАНОВЛЕНО: {successCount}, ОШИБОК: {failCount}");
|
||
|
||
if (failCount == 0)
|
||
{
|
||
Console.WriteLine("\n 🎉 Все сертификаты успешно установлены!");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"\n ⚠️ {failCount} сертификатов не удалось установить.");
|
||
Console.WriteLine(" Попробуйте запустить приложение от имени администратора.");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выборочная установка сертификатов
|
||
/// </summary>
|
||
static async Task InstallSelectedCertificatesAsync(CertificateChecker checker, List<X509Certificate2> certificates, List<CertificateCheckResult> results)
|
||
{
|
||
var missing = results.Where(r => !r.IsInstalled).ToList();
|
||
|
||
if (!missing.Any())
|
||
{
|
||
Console.WriteLine("\n Нет сертификатов для установки.");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine("\n🔧 ВЫБЕРИТЕ СЕРТИФИКАТЫ ДЛЯ УСТАНОВКИ:");
|
||
Console.WriteLine(" Введите номера через запятую (например: 1,3,5) или 'all' для всех");
|
||
Console.WriteLine(" Доступные сертификаты:");
|
||
|
||
for (int i = 0; i < missing.Count; i++)
|
||
{
|
||
Console.WriteLine($" [{i + 1}] {missing[i].FriendlyName}");
|
||
}
|
||
|
||
Console.Write("\n Ваш выбор: ");
|
||
var input = Console.ReadLine();
|
||
|
||
List<int> selectedIndexes = new List<int>();
|
||
|
||
if (input?.ToLower() == "all")
|
||
{
|
||
selectedIndexes = Enumerable.Range(0, missing.Count).ToList();
|
||
}
|
||
else if (!string.IsNullOrEmpty(input))
|
||
{
|
||
var parts = input.Split(',');
|
||
foreach (var part in parts)
|
||
{
|
||
if (int.TryParse(part.Trim(), out int num) && num > 0 && num <= missing.Count)
|
||
{
|
||
selectedIndexes.Add(num - 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!selectedIndexes.Any())
|
||
{
|
||
Console.WriteLine(" ❌ Не выбрано ни одного сертификата.");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"\n Установка {selectedIndexes.Count} сертификатов...");
|
||
|
||
var successCount = 0;
|
||
var failCount = 0;
|
||
|
||
foreach (var index in selectedIndexes)
|
||
{
|
||
var result = missing[index];
|
||
var cert = certificates.FirstOrDefault(c => c.Thumbprint == result.Thumbprint);
|
||
|
||
if (cert == null)
|
||
{
|
||
Console.WriteLine($" ❌ Сертификат {result.FriendlyName} не найден");
|
||
failCount++;
|
||
continue;
|
||
}
|
||
|
||
Console.WriteLine($"\n 📥 Установка: {cert.FriendlyName}");
|
||
|
||
var installResult = await checker.InstallCertificateWithAutoStoreAsync(cert);
|
||
|
||
if (installResult.Success)
|
||
{
|
||
successCount++;
|
||
Console.WriteLine($" ✅ Успешно установлен");
|
||
}
|
||
else
|
||
{
|
||
failCount++;
|
||
Console.WriteLine($" ❌ Ошибка установки");
|
||
foreach (var msg in installResult.Messages)
|
||
{
|
||
Console.WriteLine($" {msg}");
|
||
}
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n 📊 УСТАНОВЛЕНО: {successCount}, ОШИБОК: {failCount}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// Удаление всех сертификатов
|
||
/// </summary>
|
||
static async Task DeleteAllCertificatesAsync(CertificateChecker checker, List<X509Certificate2> certificates, List<CertificateCheckResult> results)
|
||
{
|
||
Console.WriteLine("\n🗑️ НАЧАЛО УДАЛЕНИЯ ВСЕХ СЕРТИФИКАТОВ...");
|
||
Console.WriteLine(new string('─', 80));
|
||
|
||
var successCount = 0;
|
||
var failCount = 0;
|
||
|
||
for (int i = 0; i < certificates.Count; i++)
|
||
{
|
||
var cert = certificates[i];
|
||
var result = results[i];
|
||
|
||
if (result.IsInstalled)
|
||
{
|
||
Console.WriteLine($"\n 🗑️ Удаление сертификата: {cert.FriendlyName}");
|
||
Console.WriteLine($" Хранилище: {result.StoreLocation}\\{result.StoreName}");
|
||
|
||
try
|
||
{
|
||
using var store = new X509Store(result.StoreName, result.StoreLocation);
|
||
store.Open(OpenFlags.ReadWrite);
|
||
|
||
var foundCerts = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false);
|
||
if (foundCerts.Count > 0)
|
||
{
|
||
store.Remove(foundCerts[0]);
|
||
successCount++;
|
||
Console.WriteLine($" ✅ Успешно удален из {result.StoreLocation}\\{result.StoreName}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" ⚠️ Сертификат не найден в хранилище");
|
||
failCount++;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
failCount++;
|
||
Console.WriteLine($" ❌ Ошибка удаления: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n 📊 ИТОГО УДАЛЕНО: {successCount}, ОШИБОК: {failCount}");
|
||
|
||
if (failCount == 0)
|
||
{
|
||
Console.WriteLine("\n 🎉 Все сертификаты успешно удалены!");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"\n ⚠️ {failCount} сертификатов не удалось удалить.");
|
||
Console.WriteLine(" Попробуйте запустить приложение от имени администратора.");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выборочное удаление сертификатов
|
||
/// </summary>
|
||
static async Task DeleteSelectedCertificatesAsync(CertificateChecker checker, List<X509Certificate2> certificates, List<CertificateCheckResult> results)
|
||
{
|
||
var installed = results.Where(r => r.IsInstalled).ToList();
|
||
|
||
if (!installed.Any())
|
||
{
|
||
Console.WriteLine("\n Нет сертификатов для удаления.");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine("\n🗑️ ВЫБЕРИТЕ СЕРТИФИКАТЫ ДЛЯ УДАЛЕНИЯ:");
|
||
Console.WriteLine(" Введите номера через запятую (например: 1,3,5) или 'all' для всех");
|
||
Console.WriteLine(" Установленные сертификаты:");
|
||
|
||
for (int i = 0; i < installed.Count; i++)
|
||
{
|
||
Console.WriteLine($" [{i + 1}] {installed[i].FriendlyName}");
|
||
Console.WriteLine($" Хранилище: {installed[i].StoreLocation}\\{installed[i].StoreName}");
|
||
}
|
||
|
||
Console.Write("\n Ваш выбор: ");
|
||
var input = Console.ReadLine();
|
||
|
||
List<int> selectedIndexes = new List<int>();
|
||
|
||
if (input?.ToLower() == "all")
|
||
{
|
||
selectedIndexes = Enumerable.Range(0, installed.Count).ToList();
|
||
}
|
||
else if (!string.IsNullOrEmpty(input))
|
||
{
|
||
var parts = input.Split(',');
|
||
foreach (var part in parts)
|
||
{
|
||
if (int.TryParse(part.Trim(), out int num) && num > 0 && num <= installed.Count)
|
||
{
|
||
selectedIndexes.Add(num - 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!selectedIndexes.Any())
|
||
{
|
||
Console.WriteLine(" ❌ Не выбрано ни одного сертификата.");
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"\n Удаление {selectedIndexes.Count} сертификатов...");
|
||
|
||
var successCount = 0;
|
||
var failCount = 0;
|
||
|
||
foreach (var index in selectedIndexes)
|
||
{
|
||
var result = installed[index];
|
||
var cert = certificates.FirstOrDefault(c => c.Thumbprint == result.Thumbprint);
|
||
|
||
if (cert == null)
|
||
{
|
||
Console.WriteLine($" ❌ Сертификат {result.FriendlyName} не найден");
|
||
failCount++;
|
||
continue;
|
||
}
|
||
|
||
Console.WriteLine($"\n 🗑️ Удаление: {cert.FriendlyName}");
|
||
Console.WriteLine($" Хранилище: {result.StoreLocation}\\{result.StoreName}");
|
||
|
||
try
|
||
{
|
||
using var store = new X509Store(result.StoreName, result.StoreLocation);
|
||
store.Open(OpenFlags.ReadWrite);
|
||
|
||
var foundCerts = store.Certificates.Find(X509FindType.FindByThumbprint, cert.Thumbprint, false);
|
||
if (foundCerts.Count > 0)
|
||
{
|
||
store.Remove(foundCerts[0]);
|
||
successCount++;
|
||
Console.WriteLine($" ✅ Успешно удален");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($" ⚠️ Сертификат не найден в хранилище");
|
||
failCount++;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
failCount++;
|
||
Console.WriteLine($" ❌ Ошибка удаления: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
Console.WriteLine($"\n 📊 УДАЛЕНО: {successCount}, ОШИБОК: {failCount}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// Выводит таблицу всех проверенных сертификатов
|
||
/// </summary>
|
||
static void PrintCertificateTable(List<CertificateCheckResult> results)
|
||
{
|
||
var colWidth = new Dictionary<string, int>
|
||
{
|
||
["#"] = 4,
|
||
["Имя"] = 30,
|
||
["Отпечаток"] = 12,
|
||
["Действителен до"] = 14,
|
||
["Статус"] = 12,
|
||
["Ключ"] = 10,
|
||
["Цепочка"] = 10,
|
||
["Хранилище"] = 20
|
||
};
|
||
|
||
foreach (var result in results)
|
||
{
|
||
colWidth["Имя"] = Math.Max(colWidth["Имя"], result.FriendlyName.Length + 2);
|
||
colWidth["Отпечаток"] = Math.Max(colWidth["Отпечаток"], Math.Min(result.Thumbprint.Length, 14) + 2);
|
||
colWidth["Хранилище"] = Math.Max(colWidth["Хранилище"],
|
||
result.IsInstalled ? $"{result.StoreLocation}\\{result.StoreName}".Length + 2 : 12);
|
||
}
|
||
|
||
var header = $"│ {"#".PadRight(colWidth["#"])} │ " +
|
||
$"{"Имя".PadRight(colWidth["Имя"])} │ " +
|
||
$"{"Отпечаток".PadRight(colWidth["Отпечаток"])} │ " +
|
||
$"{"Действителен до".PadRight(colWidth["Действителен до"])} │ " +
|
||
$"{"Статус".PadRight(colWidth["Статус"])} │ " +
|
||
$"{"Ключ".PadRight(colWidth["Ключ"])} │ " +
|
||
$"{"Цепочка".PadRight(colWidth["Цепочка"])} │ " +
|
||
$"{"Хранилище".PadRight(colWidth["Хранилище"])} │";
|
||
|
||
var separator = $"├{"─".PadRight(colWidth["#"] + 1, '─')}┼{"─".PadRight(colWidth["Имя"] + 1, '─')}┼{"─".PadRight(colWidth["Отпечаток"] + 1, '─')}┼{"─".PadRight(colWidth["Действителен до"] + 1, '─')}┼{"─".PadRight(colWidth["Статус"] + 1, '─')}┼{"─".PadRight(colWidth["Ключ"] + 1, '─')}┼{"─".PadRight(colWidth["Цепочка"] + 1, '─')}┼{"─".PadRight(colWidth["Хранилище"] + 1, '─')}┤";
|
||
var topBorder = $"┌{"─".PadRight(colWidth["#"] + 1, '─')}┬{"─".PadRight(colWidth["Имя"] + 1, '─')}┬{"─".PadRight(colWidth["Отпечаток"] + 1, '─')}┬{"─".PadRight(colWidth["Действителен до"] + 1, '─')}┬{"─".PadRight(colWidth["Статус"] + 1, '─')}┬{"─".PadRight(colWidth["Ключ"] + 1, '─')}┬{"─".PadRight(colWidth["Цепочка"] + 1, '─')}┬{"─".PadRight(colWidth["Хранилище"] + 1, '─')}┐";
|
||
var bottomBorder = $"└{"─".PadRight(colWidth["#"] + 1, '─')}┴{"─".PadRight(colWidth["Имя"] + 1, '─')}┴{"─".PadRight(colWidth["Отпечаток"] + 1, '─')}┴{"─".PadRight(colWidth["Действителен до"] + 1, '─')}┴{"─".PadRight(colWidth["Статус"] + 1, '─')}┴{"─".PadRight(colWidth["Ключ"] + 1, '─')}┴{"─".PadRight(colWidth["Цепочка"] + 1, '─')}┴{"─".PadRight(colWidth["Хранилище"] + 1, '─')}┘";
|
||
|
||
Console.WriteLine(topBorder);
|
||
Console.WriteLine(header);
|
||
Console.WriteLine(separator);
|
||
|
||
for (int i = 0; i < results.Count; i++)
|
||
{
|
||
var result = results[i];
|
||
|
||
var status = result.IsInstalled ? "✅ Уст." : "❌ Нет";
|
||
var hasKey = result.HasPrivateKey ? "✅ Есть" : "❌ Нет";
|
||
var chain = result.ChainValidationResult.IsValid ? "✅ Ок" : "⚠️ Пробл.";
|
||
var thumbprint = result.Thumbprint.Length > 14 ?
|
||
result.Thumbprint.Substring(0, 12) + "..." :
|
||
result.Thumbprint;
|
||
var store = result.IsInstalled ?
|
||
$"{result.StoreLocation}\\{result.StoreName}" :
|
||
"Не установлен";
|
||
|
||
if (!result.IsInstalled)
|
||
{
|
||
Console.ForegroundColor = ConsoleColor.Red;
|
||
}
|
||
else if (result.NotAfter < DateTime.Now)
|
||
{
|
||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||
}
|
||
else if (!result.ChainValidationResult.IsValid)
|
||
{
|
||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||
}
|
||
else
|
||
{
|
||
Console.ForegroundColor = ConsoleColor.Green;
|
||
}
|
||
|
||
var row = $"│ {(i + 1).ToString().PadRight(colWidth["#"])} │ " +
|
||
$"{result.FriendlyName.PadRight(colWidth["Имя"])} │ " +
|
||
$"{thumbprint.PadRight(colWidth["Отпечаток"])} │ " +
|
||
$"{result.NotAfter:dd.MM.yyyy}".PadRight(colWidth["Действителен до"]) + " │ " +
|
||
$"{status.PadRight(colWidth["Статус"])} │ " +
|
||
$"{hasKey.PadRight(colWidth["Ключ"])} │ " +
|
||
$"{chain.PadRight(colWidth["Цепочка"])} │ " +
|
||
$"{store.PadRight(colWidth["Хранилище"])} │";
|
||
|
||
Console.WriteLine(row);
|
||
Console.ResetColor();
|
||
}
|
||
|
||
Console.WriteLine(bottomBorder);
|
||
}
|
||
} |