From 010f86fffcb392ec73780d6c95f02282c6ffd6f7 Mon Sep 17 00:00:00 2001 From: MaDestro Date: Tue, 11 Aug 2026 22:19:10 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D1=8C=D1=82?= =?UTF-8?q?=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Russain SSL Installer.slnx | 3 + Russain SSL Installer/CertificateChecker.cs | 552 ++++++++++++ Russain SSL Installer/Program.cs | 807 ++++++++++++++++++ .../Properties/Resources.Designer.cs | 113 +++ .../Properties/Resources.resx | 141 +++ .../Resources/russian_trusted_root_ca.cer | 33 + .../russian_trusted_root_ca_gost_2025.cer | Bin 0 -> 1167 bytes .../Resources/russian_trusted_sub_ca.cer | 41 + .../Resources/russian_trusted_sub_ca_2024.cer | 39 + .../russian_trusted_sub_ca_gost_2025.cer | Bin 0 -> 1649 bytes .../Russain SSL Installer.csproj | 26 + 11 files changed, 1755 insertions(+) create mode 100644 Russain SSL Installer.slnx create mode 100644 Russain SSL Installer/CertificateChecker.cs create mode 100644 Russain SSL Installer/Program.cs create mode 100644 Russain SSL Installer/Properties/Resources.Designer.cs create mode 100644 Russain SSL Installer/Properties/Resources.resx create mode 100644 Russain SSL Installer/Resources/russian_trusted_root_ca.cer create mode 100644 Russain SSL Installer/Resources/russian_trusted_root_ca_gost_2025.cer create mode 100644 Russain SSL Installer/Resources/russian_trusted_sub_ca.cer create mode 100644 Russain SSL Installer/Resources/russian_trusted_sub_ca_2024.cer create mode 100644 Russain SSL Installer/Resources/russian_trusted_sub_ca_gost_2025.cer create mode 100644 Russain SSL Installer/Russain SSL Installer.csproj diff --git a/Russain SSL Installer.slnx b/Russain SSL Installer.slnx new file mode 100644 index 0000000..e6ab6b9 --- /dev/null +++ b/Russain SSL Installer.slnx @@ -0,0 +1,3 @@ + + + diff --git a/Russain SSL Installer/CertificateChecker.cs b/Russain SSL Installer/CertificateChecker.cs new file mode 100644 index 0000000..4ff87e3 --- /dev/null +++ b/Russain SSL Installer/CertificateChecker.cs @@ -0,0 +1,552 @@ +using System.Collections; +using System.Reflection; +using System.Resources; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace CertificateChecker; + +/// +/// Основной класс для проверки сертификатов +/// +public class CertificateChecker +{ + /// + /// Загружает сертификаты из Resources.resx + /// + public List LoadCertificatesFromResources() + { + var certificates = new List(); + var assembly = Assembly.GetExecutingAssembly(); + + Console.WriteLine(" 📂 Поиск сертификатов в ресурсах..."); + Console.WriteLine($" Сборка: {assembly.GetName().Name}"); + + try + { + // Получаем ВСЕ ресурсы из сборки + var resourceNames = assembly.GetManifestResourceNames(); + + Console.WriteLine($" Найдено ресурсов: {resourceNames.Length}"); + + if (resourceNames.Length == 0) + { + Console.WriteLine(" ⚠️ Ресурсы не найдены. Проверьте файл Resources.resx"); + return certificates; + } + + // Ищем ресурсы, которые содержат "Resources" в названии + var resourcesFile = resourceNames.FirstOrDefault(r => r.Contains("Resources")); + + if (string.IsNullOrEmpty(resourcesFile)) + { + Console.WriteLine(" ⚠️ Файл Resources.resx не найден"); + Console.WriteLine($" Доступные ресурсы: {string.Join(", ", resourceNames)}"); + return certificates; + } + + Console.WriteLine($" Найден файл ресурсов: {resourcesFile}"); + + // Создаем ResourceManager для найденного файла + var resourceManagerName = Path.GetFileNameWithoutExtension(resourcesFile); + Console.WriteLine($" Имя ResourceManager: {resourceManagerName}"); + + var resourceManager = new ResourceManager(resourceManagerName, assembly); + + // Получаем все ресурсы + var resourceSet = resourceManager.GetResourceSet(System.Globalization.CultureInfo.InvariantCulture, true, true); + + if (resourceSet == null) + { + Console.WriteLine(" ❌ Не удалось загрузить ResourceSet"); + return certificates; + } + + // Собираем все ключи ресурсов + var keys = new List(); + foreach (DictionaryEntry entry in resourceSet) + { + keys.Add(entry.Key.ToString()); + } + + Console.WriteLine($" Найдено ключей в ресурсах: {keys.Count}"); + Console.WriteLine($" Ключи: {string.Join(", ", keys)}"); + + // Фильтруем ключи, которые содержат "cert", "ca", "root", "sub" + var certKeys = keys + .Where(key => key.ToLower().Contains("cert") || + key.ToLower().Contains("ca") || + key.ToLower().Contains("root") || + key.ToLower().Contains("sub")) + .ToList(); + + if (!certKeys.Any()) + { + Console.WriteLine(" ⚠️ Сертификаты в ресурсах не найдены"); + Console.WriteLine($" Ищите ключи содержащие: cert, ca, root, sub"); + return certificates; + } + + Console.WriteLine($"\n Найдено сертификатов: {certKeys.Count}"); + + foreach (var key in certKeys) + { + try + { + Console.WriteLine($"\n 📄 Загрузка: {key}"); + + // Получаем значение ресурса + var value = resourceManager.GetObject(key); + + if (value == null) + { + Console.WriteLine($" ❌ Ресурс {key} пустой"); + continue; + } + + // Проверяем тип ресурса + if (value is byte[] bytes) + { + if (bytes.Length == 0) + { + Console.WriteLine($" ❌ Ресурс {key} пустой (0 байт)"); + continue; + } + + Console.WriteLine($" Размер: {bytes.Length} байт"); + + try + { + // Пробуем загрузить как сертификат + var certificate = new X509Certificate2(bytes); + + // Устанавливаем понятное имя + if (string.IsNullOrEmpty(certificate.FriendlyName)) + { + certificate.FriendlyName = key.Replace("_", " ").Trim(); + } + + certificates.Add(certificate); + + Console.WriteLine($" ✅ Загружен сертификат: {certificate.FriendlyName}"); + Console.WriteLine($" Субъект: {certificate.Subject}"); + Console.WriteLine($" Отпечаток: {certificate.Thumbprint}"); + Console.WriteLine($" Действителен до: {certificate.NotAfter:dd.MM.yyyy}"); + Console.WriteLine($" Закрытый ключ: {(certificate.HasPrivateKey ? "✅ Есть" : "❌ Нет")}"); + } + catch (Exception ex) + { + Console.WriteLine($" ⚠️ Не удалось загрузить {key} как сертификат: {ex.Message}"); + Console.WriteLine($" Возможно это не сертификат или требуется пароль"); + + // Пробуем с паролем для PFX + if (key.ToLower().Contains("pfx") || key.ToLower().Contains("p12") || key.ToLower().Contains("gost")) + { + Console.Write(" 🔑 Введите пароль для {0}: ", key); + var password = Console.ReadLine(); + + if (!string.IsNullOrEmpty(password)) + { + try + { + var certificate = new X509Certificate2(bytes, password); + certificate.FriendlyName = key.Replace("_", " ").Trim(); + certificates.Add(certificate); + + Console.WriteLine($" ✅ Загружен с паролем: {certificate.FriendlyName}"); + } + catch (Exception ex2) + { + Console.WriteLine($" ❌ Ошибка загрузки с паролем: {ex2.Message}"); + } + } + } + } + } + else + { + Console.WriteLine($" ⚠️ Ресурс {key} имеет тип {value.GetType().Name}, ожидался byte[]"); + } + } + catch (Exception ex) + { + Console.WriteLine($" ❌ Ошибка обработки {key}: {ex.Message}"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($" ❌ Общая ошибка: {ex.Message}"); + Console.WriteLine($" {ex.StackTrace}"); + } + + Console.WriteLine($"\n ИТОГО загружено сертификатов: {certificates.Count}"); + return certificates; + } + + /// + /// Проверяет, установлен ли сертификат на ПК + /// + public async Task CheckCertificateInstalledAsync(X509Certificate2 certificate) + { + var result = new CertificateCheckResult + { + FriendlyName = certificate.FriendlyName, + Subject = certificate.Subject, + Issuer = certificate.Issuer, + SerialNumber = certificate.SerialNumber, + NotBefore = certificate.NotBefore, + NotAfter = certificate.NotAfter, + Thumbprint = certificate.Thumbprint, + IsInstalled = false, + FoundInStores = new List(), + HasPrivateKey = certificate.HasPrivateKey + }; + + // Проверяем в разных хранилищах + 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)"), + (StoreName.AddressBook, StoreLocation.CurrentUser, "Адресная книга (CurrentUser)"), + (StoreName.AddressBook, StoreLocation.LocalMachine, "Адресная книга (LocalMachine)") + }; + + foreach (var (storeName, storeLocation, displayName) in stores) + { + try + { + using var store = new X509Store(storeName, storeLocation); + store.Open(OpenFlags.ReadOnly); + + // Ищем по отпечатку + var foundCerts = store.Certificates.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false); + + if (foundCerts.Count > 0) + { + result.IsInstalled = true; + result.StoreName = storeName; + result.StoreLocation = storeLocation; + result.FoundCertificate = foundCerts[0]; + result.FoundInStores.Add(displayName); + } + } + catch + { + // Некоторые хранилища могут быть недоступны + } + } + + // Проверка цепочки сертификатов + result.ChainValidationResult = await ValidateCertificateChainAsync(certificate); + + // Проверка срока действия + result.IsValid = DateTime.Now >= certificate.NotBefore && + DateTime.Now <= certificate.NotAfter; + + return result; + } + + /// + /// Проверка цепочки сертификатов + /// + private async Task ValidateCertificateChainAsync(X509Certificate2 certificate) + { + var result = new ChainValidationResult(); + + try + { + using var chain = new X509Chain(); + chain.ChainPolicy.RevocationMode = X509RevocationMode.Online; + chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; + + var isValid = chain.Build(certificate); + + result.IsValid = isValid; + result.Status = chain.ChainStatus + .Select(s => new ChainStatusInfo + { + Status = s.Status, + StatusInformation = s.StatusInformation + }) + .ToList(); + } + catch (Exception ex) + { + result.ErrorMessage = ex.Message; + } + + return result; + } + + /// + /// Проверяет сертификат по отпечатку + /// + public bool IsCertificateInstalled(string thumbprint) + { + var stores = new[] + { + (StoreName.My, StoreLocation.CurrentUser), + (StoreName.My, StoreLocation.LocalMachine), + (StoreName.Root, StoreLocation.CurrentUser), + (StoreName.Root, StoreLocation.LocalMachine) + }; + + foreach (var (storeName, storeLocation) in stores) + { + try + { + using var store = new X509Store(storeName, storeLocation); + store.Open(OpenFlags.ReadOnly); + var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); + if (certificates.Count > 0) + return true; + } + catch + { + // Пропускаем недоступные хранилища + } + } + + return false; + } + + /// + /// Устанавливает сертификат в указанное хранилище + /// + public async Task InstallCertificateAsync(X509Certificate2 certificate, StoreName storeName, StoreLocation storeLocation, string friendlyName = "") + { + try + { + Console.WriteLine($"\n 📥 Установка сертификата {friendlyName} в {storeLocation}\\{storeName}..."); + + using var store = new X509Store(storeName, storeLocation); + store.Open(OpenFlags.ReadWrite); + + // Проверяем, не установлен ли уже + var existing = store.Certificates.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false); + if (existing.Count > 0) + { + Console.WriteLine($" ⚠️ Сертификат уже установлен в {storeLocation}\\{storeName}"); + return true; + } + + // Устанавливаем понятное имя + if (!string.IsNullOrEmpty(friendlyName)) + { + certificate.FriendlyName = friendlyName; + } + + store.Add(certificate); + store.Close(); + + Console.WriteLine($" ✅ Сертификат успешно установлен в {storeLocation}\\{storeName}"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($" ❌ Ошибка установки: {ex.Message}"); + return false; + } + } + + /// + /// Устанавливает сертификат с автоматическим выбором хранилища + /// + public async Task InstallCertificateWithAutoStoreAsync(X509Certificate2 certificate) + { + var result = new InstallResult + { + Certificate = certificate, + Success = false, + Messages = new List() + }; + + // Определяем куда устанавливать в зависимости от типа сертификата + var subject = certificate.Subject.ToLower(); + var isRoot = subject.Contains("root") || subject.Contains("ca") && !subject.Contains("sub"); + var isCA = subject.Contains("ca"); + var isPersonal = subject.Contains("client") || subject.Contains("user") || subject.Contains("person"); + + List<(StoreName store, StoreLocation location, string description)> storesToInstall; + + if (isRoot) + { + // Корневой сертификат + storesToInstall = new List<(StoreName, StoreLocation, string)> + { + (StoreName.Root, StoreLocation.LocalMachine, "Доверенные корневые (LocalMachine)"), + (StoreName.Root, StoreLocation.CurrentUser, "Доверенные корневые (CurrentUser)") + }; + result.InstallType = "Корневой сертификат"; + } + else if (isCA && !isRoot) + { + // Промежуточный сертификат + storesToInstall = new List<(StoreName, StoreLocation, string)> + { + (StoreName.CertificateAuthority, StoreLocation.LocalMachine, "Промежуточные (LocalMachine)"), + (StoreName.CertificateAuthority, StoreLocation.CurrentUser, "Промежуточные (CurrentUser)") + }; + result.InstallType = "Промежуточный сертификат"; + } + else if (isPersonal) + { + // Личный сертификат + storesToInstall = new List<(StoreName, StoreLocation, string)> + { + (StoreName.My, StoreLocation.CurrentUser, "Личные (CurrentUser)"), + (StoreName.My, StoreLocation.LocalMachine, "Личные (LocalMachine)") + }; + result.InstallType = "Личный сертификат"; + } + else + { + // Неопределенный тип - устанавливаем в личные + storesToInstall = new List<(StoreName, StoreLocation, string)> + { + (StoreName.My, StoreLocation.CurrentUser, "Личные (CurrentUser)") + }; + result.InstallType = "Неопределенный тип (личный)"; + } + + Console.WriteLine($"\n 📌 Тип сертификата: {result.InstallType}"); + Console.WriteLine($" 📌 Субъект: {certificate.Subject}"); + + // Устанавливаем в каждое хранилище + foreach (var (store, location, description) in storesToInstall) + { + try + { + var success = await InstallCertificateAsync(certificate, store, location, certificate.FriendlyName); + if (success) + { + result.Success = true; + result.InstalledStores.Add($"{location}\\{store}"); + result.Messages.Add($"✅ Установлен в {description}"); + } + else + { + result.Messages.Add($"❌ Не удалось установить в {description}"); + } + } + catch (Exception ex) + { + result.Messages.Add($"❌ Ошибка при установке в {description}: {ex.Message}"); + } + } + + // Если не удалось установить никуда, пробуем в CurrentUser + if (!result.Success) + { + Console.WriteLine($" ⚠️ Пробуем установить в CurrentUser..."); + try + { + var success = await InstallCertificateAsync(certificate, StoreName.My, StoreLocation.CurrentUser, certificate.FriendlyName); + if (success) + { + result.Success = true; + result.InstalledStores.Add($"CurrentUser\\My"); + result.Messages.Add($"✅ Установлен в Личные (CurrentUser)"); + } + } + catch (Exception ex) + { + result.Messages.Add($"❌ Ошибка при установке в CurrentUser: {ex.Message}"); + } + } + + return result; + } + + /// + /// Удаляет сертификат из указанного хранилища + /// + public async Task DeleteCertificateAsync(string thumbprint, StoreName storeName, StoreLocation storeLocation) + { + try + { + Console.WriteLine($"\n 🗑️ Удаление сертификата из {storeLocation}\\{storeName}..."); + + using var store = new X509Store(storeName, storeLocation); + store.Open(OpenFlags.ReadWrite); + + var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); + if (certificates.Count == 0) + { + Console.WriteLine($" ⚠️ Сертификат не найден в {storeLocation}\\{storeName}"); + return false; + } + + store.Remove(certificates[0]); + store.Close(); + + Console.WriteLine($" ✅ Сертификат удален из {storeLocation}\\{storeName}"); + return true; + } + catch (Exception ex) + { + Console.WriteLine($" ❌ Ошибка удаления: {ex.Message}"); + return false; + } + } +} + +/// +/// Результат проверки сертификата +/// +public class CertificateCheckResult +{ + public string FriendlyName { get; set; } = string.Empty; + public string Subject { get; set; } = string.Empty; + public string Issuer { get; set; } = string.Empty; + public string SerialNumber { get; set; } = string.Empty; + public DateTime NotBefore { get; set; } + public DateTime NotAfter { get; set; } + public string Thumbprint { get; set; } = string.Empty; + public bool IsInstalled { get; set; } + public bool IsValid { get; set; } + public bool HasPrivateKey { get; set; } + public StoreName StoreName { get; set; } + public StoreLocation StoreLocation { get; set; } + public X509Certificate2? FoundCertificate { get; set; } + public List FoundInStores { get; set; } = new(); + public ChainValidationResult ChainValidationResult { get; set; } = new(); +} + +/// +/// Результат установки сертификата +/// +public class InstallResult +{ + public X509Certificate2 Certificate { get; set; } = null!; + public bool Success { get; set; } + public string InstallType { get; set; } = string.Empty; + public List InstalledStores { get; set; } = new(); + public List Messages { get; set; } = new(); +} + +/// +/// Результат проверки цепочки сертификатов +/// +public class ChainValidationResult +{ + public bool IsValid { get; set; } + public string? ErrorMessage { get; set; } + public List Status { get; set; } = new(); +} + +/// +/// Информация о статусе цепочки +/// +public class ChainStatusInfo +{ + public X509ChainStatusFlags Status { get; set; } + public string? StatusInformation { get; set; } +} \ No newline at end of file diff --git a/Russain SSL Installer/Program.cs b/Russain SSL Installer/Program.cs new file mode 100644 index 0000000..6e68209 --- /dev/null +++ b/Russain SSL Installer/Program.cs @@ -0,0 +1,807 @@ +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; + } + } + } + + /// + /// Проверка сертификатов + /// + 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(); + + 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(); + } + + /// + /// Установка сертификатов + /// + 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(); + 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(); + } + + /// + /// Удаление сертификатов + /// + 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(); + 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(); + } + + /// + /// Показать все установленные сертификаты + /// + static async Task ShowAllInstalledCertificatesAsync() + { + Console.Clear(); + Console.WriteLine("╔══════════════════════════════════════════════════════════════════════════╗"); + Console.WriteLine("║ ВСЕ УСТАНОВЛЕННЫЕ СЕРТИФИКАТЫ ║"); + Console.WriteLine("╚══════════════════════════════════════════════════════════════════════════╝\n"); + + var checker = new CertificateChecker(); + var allCerts = new List(); + + // Проверяем все хранилища + 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(); + } + + /// + /// Установка всех сертификатов + /// + static async Task InstallAllCertificatesAsync(CertificateChecker checker, List certificates, List 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(" Попробуйте запустить приложение от имени администратора."); + } + } + + /// + /// Выборочная установка сертификатов + /// + static async Task InstallSelectedCertificatesAsync(CertificateChecker checker, List certificates, List 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 selectedIndexes = new List(); + + 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}"); + } + + /// + /// Удаление всех сертификатов + /// + static async Task DeleteAllCertificatesAsync(CertificateChecker checker, List certificates, List 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(" Попробуйте запустить приложение от имени администратора."); + } + } + + /// + /// Выборочное удаление сертификатов + /// + static async Task DeleteSelectedCertificatesAsync(CertificateChecker checker, List certificates, List 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 selectedIndexes = new List(); + + 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}"); + } + + /// + /// Выводит таблицу всех проверенных сертификатов + /// + static void PrintCertificateTable(List results) + { + var colWidth = new Dictionary + { + ["#"] = 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); + } +} \ No newline at end of file diff --git a/Russain SSL Installer/Properties/Resources.Designer.cs b/Russain SSL Installer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..dbd3223 --- /dev/null +++ b/Russain SSL Installer/Properties/Resources.Designer.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// +// Этот код создан программой. +// Исполняемая версия:4.0.30319.42000 +// +// Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае +// повторной генерации кода. +// +//------------------------------------------------------------------------------ + +namespace Russain_SSL_Installer.Properties { + using System; + + + /// + /// Класс ресурса со строгой типизацией для поиска локализованных строк и т.д. + /// + // Этот класс создан автоматически классом StronglyTypedResourceBuilder + // с помощью такого средства, как ResGen или Visual Studio. + // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen + // с параметром /str или перестройте свой проект VS. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Возвращает кэшированный экземпляр ResourceManager, использованный этим классом. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Russain_SSL_Installer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Перезаписывает свойство CurrentUICulture текущего потока для всех + /// обращений к ресурсу с помощью этого класса ресурса со строгой типизацией. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] russian_trusted_root_ca { + get { + object obj = ResourceManager.GetObject("russian_trusted_root_ca", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] russian_trusted_root_ca_gost_2025 { + get { + object obj = ResourceManager.GetObject("russian_trusted_root_ca_gost_2025", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] russian_trusted_sub_ca { + get { + object obj = ResourceManager.GetObject("russian_trusted_sub_ca", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] russian_trusted_sub_ca_2024 { + get { + object obj = ResourceManager.GetObject("russian_trusted_sub_ca_2024", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Поиск локализованного ресурса типа System.Byte[]. + /// + internal static byte[] russian_trusted_sub_ca_gost_2025 { + get { + object obj = ResourceManager.GetObject("russian_trusted_sub_ca_gost_2025", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/Russain SSL Installer/Properties/Resources.resx b/Russain SSL Installer/Properties/Resources.resx new file mode 100644 index 0000000..eec8e9d --- /dev/null +++ b/Russain SSL Installer/Properties/Resources.resx @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\russian_trusted_root_ca.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Root + + + ..\Resources\russian_trusted_root_ca_gost_2025.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Root + + + ..\Resources\russian_trusted_sub_ca.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Sub + + + ..\Resources\russian_trusted_sub_ca_2024.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Sub + + + ..\Resources\russian_trusted_sub_ca_gost_2025.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Sub + + \ No newline at end of file diff --git a/Russain SSL Installer/Resources/russian_trusted_root_ca.cer b/Russain SSL Installer/Resources/russian_trusted_root_ca.cer new file mode 100644 index 0000000..4c143a2 --- /dev/null +++ b/Russain SSL Installer/Resources/russian_trusted_root_ca.cer @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFwjCCA6qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UEBhMCUlUx +PzA9BgNVBAoMNlRoZSBNaW5pc3RyeSBvZiBEaWdpdGFsIERldmVsb3BtZW50IGFu +ZCBDb21tdW5pY2F0aW9uczEgMB4GA1UEAwwXUnVzc2lhbiBUcnVzdGVkIFJvb3Qg +Q0EwHhcNMjIwMzAxMjEwNDE1WhcNMzIwMjI3MjEwNDE1WjBwMQswCQYDVQQGEwJS +VTE/MD0GA1UECgw2VGhlIE1pbmlzdHJ5IG9mIERpZ2l0YWwgRGV2ZWxvcG1lbnQg +YW5kIENvbW11bmljYXRpb25zMSAwHgYDVQQDDBdSdXNzaWFuIFRydXN0ZWQgUm9v +dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMfFOZ8pUAL3+r2n +qqE0Zp52selXsKGFYoG0GM5bwz1bSFtCt+AZQMhkWQheI3poZAToYJu69pHLKS6Q +XBiwBC1cvzYmUYKMYZC7jE5YhEU2bSL0mX7NaMxMDmH2/NwuOVRj8OImVa5s1F4U +zn4Kv3PFlDBjjSjXKVY9kmjUBsXQrIHeaqmUIsPIlNWUnimXS0I0abExqkbdrXbX +YwCOXhOO2pDUx3ckmJlCMUGacUTnylyQW2VsJIyIGA8V0xzdaeUXg0VZ6ZmNUr5Y +Ber/EAOLPb8NYpsAhJe2mXjMB/J9HNsoFMBFJ0lLOT/+dQvjbdRZoOT8eqJpWnVD +U+QL/qEZnz57N88OWM3rabJkRNdU/Z7x5SFIM9FrqtN8xewsiBWBI0K6XFuOBOTD +4V08o4TzJ8+Ccq5XlCUW2L48pZNCYuBDfBh7FxkB7qDgGDiaftEkZZfApRg2E+M9 +G8wkNKTPLDc4wH0FDTijhgxR3Y4PiS1HL2Zhw7bD3CbslmEGgfnnZojNkJtcLeBH +BLa52/dSwNU4WWLubaYSiAmA9IUMX1/RpfpxOxd4Ykmhz97oFbUaDJFipIggx5sX +ePAlkTdWnv+RWBxlJwMQ25oEHmRguNYf4Zr/Rxr9cS93Y+mdXIZaBEE0KS2iLRqa +OiWBki9IMQU4phqPOBAaG7A+eP8PAgMBAAGjZjBkMB0GA1UdDgQWBBTh0YHlzlpf +BKrS6badZrHF+qwshzAfBgNVHSMEGDAWgBTh0YHlzlpfBKrS6badZrHF+qwshzAS +BgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsF +AAOCAgEAALIY1wkilt/urfEVM5vKzr6utOeDWCUczmWX/RX4ljpRdgF+5fAIS4vH +tmXkqpSCOVeWUrJV9QvZn6L227ZwuE15cWi8DCDal3Ue90WgAJJZMfTshN4OI8cq +W9E4EG9wglbEtMnObHlms8F3CHmrw3k6KmUkWGoa+/ENmcVl68u/cMRl1JbW2bM+ +/3A+SAg2c6iPDlehczKx2oa95QW0SkPPWGuNA/CE8CpyANIhu9XFrj3RQ3EqeRcS +AQQod1RNuHpfETLU/A2gMmvn/w/sx7TB3W5BPs6rprOA37tutPq9u6FTZOcG1Oqj +C/B7yTqgI7rbyvox7DEXoX7rIiEqyNNUguTk/u3SZ4VXE2kmxdmSh3TQvybfbnXV +4JbCZVaqiZraqc7oZMnRoWrXRG3ztbnbes/9qhRGI7PqXqeKJBztxRTEVj8ONs1d +WN5szTwaPIvhkhO3CO5ErU2rVdUr89wKpNXbBODFKRtgxUT70YpmJ46VVaqdAhOZ +D9EUUn4YaeLaS8AjSF/h7UkjOibNc4qVDiPP+rkehFWM66PVnP1Msh93tc+taIfC +EYVMxjh8zNbFuoc7fzvvrFILLe7ifvEIUqSVIC/AzplM/Jxw7buXFeGP1qVCBEHq +391d/9RAfaZ12zkwFsl+IKwE/OZxW8AHa9i1p4GO0YSNuczzEm4= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/Russain SSL Installer/Resources/russian_trusted_root_ca_gost_2025.cer b/Russain SSL Installer/Resources/russian_trusted_root_ca_gost_2025.cer new file mode 100644 index 0000000000000000000000000000000000000000..873460eff54c3c3b230b595754affaf98c1eb3d9 GIT binary patch literal 1167 zcmXqLV(B($V*b8>nTe5!Nt9t{eeRY$WhxTyj>j2R$$pT{u=TlTz{SR))ymAy$jHoW z(8Oq9C~6?g#tIZkVG-goH#ameF*h+bH#L+n5Q7La3h{yj%?*qUjLggp3=M+~0@;{D zSvYyTF3i8!aAE7k#tVBdY`w4-NbkC^;bOl6kh|f+MxX>x^1?O{?_$4>!i6mt_FdSc zU}&JDaIx`X6Hsy=NY{lO7q%)G8A=+6gA8To5xB5fPvOFx3;V#vZMv`l>=K|92M@ow zIjRh|0VhZkn=n&QsG*vH3W&qSBMa2M1L&N#3p*~hTx_`5t#Dxh$T*;ZJ1*=nv@@^) zsbl6b#j8%?!rTjsFDz34`e`4~tsoz60=jsoft)z6k*R^Hk%ghDiJ^&MlsK=60g!6~ z<&K6a?y$!hrj4r%6k*Adk;y=mjT4+ifvK1gCd|al+}Ogv(%4Xz7*iCQ-gTn}bQKb|d;eDQK*KWDPN;zUM~ zXRL}_Id< z9${i9ZZ|qj<*Av}{mT5g;L^RX4ER9O{2(nXzzoV};1A*}uy`1_K{F+jBqJZQ0UH|& zP?*7hgN+T8EejdpEG9UM8O~yXvsjU{HgjVmL*DvdT0ev9-Wl+F2zmG##aG&@?TUAO zqqlQoM8xq>c7B88pYs$Ri+lOP%Yrl%S8h-WvQCU&s4d{STLlV8fEA z!-8!&XN6KzbTbqLS2flY?^E$?=;!{lc!k2L53%uQ0^FwEIeh<0vrJ|C#@f;cWzJzS K3nFCF5>o-TP1EuK literal 0 HcmV?d00001 diff --git a/Russain SSL Installer/Resources/russian_trusted_sub_ca.cer b/Russain SSL Installer/Resources/russian_trusted_sub_ca.cer new file mode 100644 index 0000000..2e3f828 --- /dev/null +++ b/Russain SSL Installer/Resources/russian_trusted_sub_ca.cer @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIHQjCCBSqgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UEBhMCUlUx +PzA9BgNVBAoMNlRoZSBNaW5pc3RyeSBvZiBEaWdpdGFsIERldmVsb3BtZW50IGFu +ZCBDb21tdW5pY2F0aW9uczEgMB4GA1UEAwwXUnVzc2lhbiBUcnVzdGVkIFJvb3Qg +Q0EwHhcNMjIwMzAyMTEyNTE5WhcNMjcwMzA2MTEyNTE5WjBvMQswCQYDVQQGEwJS +VTE/MD0GA1UECgw2VGhlIE1pbmlzdHJ5IG9mIERpZ2l0YWwgRGV2ZWxvcG1lbnQg +YW5kIENvbW11bmljYXRpb25zMR8wHQYDVQQDDBZSdXNzaWFuIFRydXN0ZWQgU3Vi +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9YPqBKOk19NFymrE +wehzrhBEgT2atLezpduB24mQ7CiOa/HVpFCDRZzdxqlh8drku408/tTmWzlNH/br +HuQhZ/miWKOf35lpKzjyBd6TPM23uAfJvEOQ2/dnKGGJbsUo1/udKSvxQwVHpVv3 +S80OlluKfhWPDEXQpgyFqIzPoxIQTLZ0deirZwMVHarZ5u8HqHetRuAtmO2ZDGQn +vVOJYAjls+Hiueq7Lj7Oce7CQsTwVZeP+XQx28PAaEZ3y6sQEt6rL06ddpSdoTMp +BnCqTbxW+eWMyjkIn6t9GBtUV45yB1EkHNnj2Ex4GwCiN9T84QQjKSr+8f0psGrZ +vPbCbQAwNFJjisLixnjlGPLKa5vOmNwIh/LAyUW5DjpkCx004LPDuqPpFsKXNKpa +L2Dm6uc0x4Jo5m+gUTVORB6hOSzWnWDj2GWfomLzzyjG81DRGFBpco/O93zecsIN +3SL2Ysjpq1zdoS01CMYxie//9zWvYwzI25/OZigtnpCIrcd2j1Y6dMUFQAzAtHE+ +qsXflSL8HIS+IJEFIQobLlYhHkoE3avgNx5jlu+OLYe0dF0Ykx1PGNjbwqvTX37R +Cn32NMjlotW2QcGEZhDKj+3urZizp5xdTPZitA+aEjZM/Ni71VOdiOP0igbw6asZ +2fxdozZ1TnSSYNYvNATwthNmZysCAwEAAaOCAeUwggHhMBIGA1UdEwEB/wQIMAYB +Af8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTR4XENCy2BTm6KSo9MI7NM +XqtpCzAfBgNVHSMEGDAWgBTh0YHlzlpfBKrS6badZrHF+qwshzCBxwYIKwYBBQUH +AQEEgbowgbcwOwYIKwYBBQUHMAKGL2h0dHA6Ly9yb3N0ZWxlY29tLnJ1L2NkcC9y +b290Y2Ffc3NsX3JzYTIwMjIuY3J0MDsGCCsGAQUFBzAChi9odHRwOi8vY29tcGFu +eS5ydC5ydS9jZHAvcm9vdGNhX3NzbF9yc2EyMDIyLmNydDA7BggrBgEFBQcwAoYv +aHR0cDovL3JlZXN0ci1wa2kucnUvY2RwL3Jvb3RjYV9zc2xfcnNhMjAyMi5jcnQw +gbAGA1UdHwSBqDCBpTA1oDOgMYYvaHR0cDovL3Jvc3RlbGVjb20ucnUvY2RwL3Jv +b3RjYV9zc2xfcnNhMjAyMi5jcmwwNaAzoDGGL2h0dHA6Ly9jb21wYW55LnJ0LnJ1 +L2NkcC9yb290Y2Ffc3NsX3JzYTIwMjIuY3JsMDWgM6Axhi9odHRwOi8vcmVlc3Ry +LXBraS5ydS9jZHAvcm9vdGNhX3NzbF9yc2EyMDIyLmNybDANBgkqhkiG9w0BAQsF +AAOCAgEARBVzZls79AdiSCpar15dA5Hr/rrT4WbrOfzlpI+xrLeRPrUG6eUWIW4v +Sui1yx3iqGLCjPcKb+HOTwoRMbI6ytP/ndp3TlYua2advYBEhSvjs+4vDZNwXr/D +anbwIWdurZmViQRBDFebpkvnIvru/RpWud/5r624Wp8voZMRtj/cm6aI9LtvBfT9 +cfzhOaexI/99c14dyiuk1+6QhdwKaCRTc1mdfNQmnfWNRbfWhWBlK3h4GGE9JK33 +Gk8ZS8DMrkdAh0xby4xAQ/mSWAfWrBmfzlOqGyoB1U47WTOeqNbWkkoAP2ys94+s +Jg4NTkiDVtXRF6nr6fYi0bSOvOFg0IQrMXO2Y8gyg9ARdPJwKtvWX8VPADCYMiWH +h4n8bZokIrImVKLDQKHY4jCsND2HHdJfnrdL2YJw1qFskNO4cSNmZydw0Wkgjv9k +F+KxqrDKlB8MZu2Hclph6v/CZ0fQ9YuE8/lsHZ0Qc2HyiSMnvjgK5fDc3TD4fa8F +E8gMNurM+kV8PT8LNIM+4Zs+LKEV8nqRWBaxkIVJGekkVKO8xDBOG/aN62AZKHOe +GcyIdu7yNMMRihGVZCYr8rYiJoKiOzDqOkPkLOPdhtVlgnhowzHDxMHND/E2WA5p +ZHuNM/m0TXt2wTTPL7JH2YC0gPz/BvvSzjksgzU5rLbRyUKQkgU= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/Russain SSL Installer/Resources/russian_trusted_sub_ca_2024.cer b/Russain SSL Installer/Resources/russian_trusted_sub_ca_2024.cer new file mode 100644 index 0000000..1fbc4a4 --- /dev/null +++ b/Russain SSL Installer/Resources/russian_trusted_sub_ca_2024.cer @@ -0,0 +1,39 @@ +-----BEGIN CERTIFICATE----- +MIIG6DCCBNCgAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UEBhMCUlUx +PzA9BgNVBAoMNlRoZSBNaW5pc3RyeSBvZiBEaWdpdGFsIERldmVsb3BtZW50IGFu +ZCBDb21tdW5pY2F0aW9uczEgMB4GA1UEAwwXUnVzc2lhbiBUcnVzdGVkIFJvb3Qg +Q0EwHhcNMjQwNzE1MTI1MDQxWhcNMjkwNzE5MTI1MDQxWjBvMQswCQYDVQQGEwJS +VTE/MD0GA1UECgw2VGhlIE1pbmlzdHJ5IG9mIERpZ2l0YWwgRGV2ZWxvcG1lbnQg +YW5kIENvbW11bmljYXRpb25zMR8wHQYDVQQDDBZSdXNzaWFuIFRydXN0ZWQgU3Vi +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1j0rkZECOt1S8o7I +JY+4YKAxuEa5xaHKHXT2EpkuC/0krqMOjUy2oPIRNgR5g8X0Jl6jamxeGLc4Q1tf +ju6or9oSRYThIUhRsFDQNBiBBEXoBgWxTfiKB2eyT97+pz5TBtBiRCPaLGRHYLRb +9Jz2HkJlxbtNPjtDrF5DPHym+mZ1M1z3hIQYAqJwLpsEBnsw/VxWMlxqHoeewd0h +uJMd71KQ5vOKlz7KrIZ6EobNNa6wItuvsfj3kYCK7O78uLHGXXFxdr8Hae9lMUmC +8F7AFwa+bO1LRlTlqW7rE3rLf+jj70N01N8T3o22v14YBaFBWQWncAVYD2JuL3tH +252+kdNOERf1fLbLRigJAbd+hOhWYlNf963TFDgnNPliHNIW72SygVBnI2V3JwO1 +dp1hVKpK/zt8ziGdHW4gmOLTsH50YKdR4jNqUgQv4wASlKn9OpN6zHYc5G8h86fY +BM+zxE5ikGI+I/vIqBuI0eaDU92AWN/YjFLpu8tMu9kLRSCf1vug6FIfDPWVo7iP +ac/SI2v8jnnpaW7ph/Pz3WkzaG7ZZJsfFs+8dploWc6LOoDtbFBhMdGMxu024msC +0PSjZb5ODXPIaO2NsA7fMiAtZcoK6anTUJh4zOP/stA9qsJGNxdrEmiPXSmBZY/N +Y0wkZgZ6JTDhw7038bPvctkblJkCAwEAAaOCAYswggGHMB0GA1UdDgQWBBR3Pdk5 +r0K93FvKduru/c4+YSkwXzAfBgNVHSMEGDAWgBTh0YHlzlpfBKrS6badZrHF+qws +hzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADCBmAYIKwYBBQUH +AQEEgYswgYgwQAYIKwYBBQUHMAKGNGh0dHA6Ly9udWMtY2RwLnZvc2tob2QucnUv +Y2RwL3Jvb3RjYV9zc2xfcnNhMjAyMi5jcnQwRAYIKwYBBQUHMAKGOGh0dHA6Ly9u +dWMtY2RwLmRpZ2l0YWwuZ292LnJ1L2NkcC9yb290Y2Ffc3NsX3JzYTIwMjIuY3J0 +MIGFBgNVHR8EfjB8MDqgOKA2hjRodHRwOi8vbnVjLWNkcC52b3NraG9kLnJ1L2Nk +cC9yb290Y2Ffc3NsX3JzYTIwMjIuY3JsMD6gPKA6hjhodHRwOi8vbnVjLWNkcC5k +aWdpdGFsLmdvdi5ydS9jZHAvcm9vdGNhX3NzbF9yc2EyMDIyLmNybDANBgkqhkiG +9w0BAQsFAAOCAgEAmsINXtQ7wwUWvIeOr80MdJS/5G4xhyZOVEmeUorThquT672y +cCg3XCxc4fwbiZqSSbBqntQ7RtiTAKMYMvBageKoVHbzz+R4jX01tKcTx8cDePrz +dJ73bLNUorE7RU9QsW4KyiUeRmjMDV23AUlEvuQFTwgkHXvbac1BBdPn9CrssQuF +5EGohZKcQPFiAAc4SHbRNhlr7uAwgpc/erzI9EAcvA6BVAXcVKoeGpV01uexUgZ6 +St5RP9UmDWNA7T4yVXWJ233N0Q8bl+6AswINQ3PosPu6yQQHQjr65YS06epK+AeI +6j+oGR4xI7EhTQhQvaobnGmX/8QQ7XDRYCP2HXYxiffnn/CfZ/BVyKLYeY1ZipjE +nzqdQIC2+Q3WtY8jsVRQMP38WFRmtsIt5snehnPTs5bKGVIcYzj3o3Ex/K7agEz0 +zAJ0JR5ivXZOvNkT0g9x1v+S1IkU3e/nX1a+tpRquMtnHX0L2lXArNHUbaOO9EJt +d57WaIpofV5cVhhwShOgAuBc9UMJF3/n4t4RKiPxtsK8P67gcmphMhslj7AMYrYM +ej2NvQZY4m3ub3CPC/PrTjDONvb+8g5xrKtxBjYqC74HSB4dg9G3WimSDUuP2Su6 +G2y2TUeyJuCvCLz289VoO0vg7cNdMobE3KCqAiiNhN2VBFxHAUKmUoRcRdw= +-----END CERTIFICATE----- diff --git a/Russain SSL Installer/Resources/russian_trusted_sub_ca_gost_2025.cer b/Russain SSL Installer/Resources/russian_trusted_sub_ca_gost_2025.cer new file mode 100644 index 0000000000000000000000000000000000000000..9ed53a0212835590f102e1335756c49f733e099f GIT binary patch literal 1649 zcmXqLV#_sXV!gS5nTe5!NrcOp^*qm!mtE_&AKAG4(}Y#)IYQPMaItY{wKB6aGBPt8 zG%*?&iW&&Bu>wU>ScJID%?%Aq%uS5VO${Xs#2~_qLcAbBa|0s-BQtXYL&IQ$KsM%3 z7ET_o3-d2FT-bWC@xtBX>;<@v2j}F!#dZ3(FLMe%c3gE69hNfG*x?AScdiWNKh)WMOD(Vs2m-CC+PX0OXoO zxxg?r8*yRkV&DV`Q)}YFbU!d8w_I!oMH4s;?7i3x4B5t228yu6$;f0N%Ek#!sKBJm z2oq*vW^Qa@U}f|2XC%(HV{ z+5h(BrwpEJ+gGUw$IQs^cxd=ocahK6(9B1xU-{1RTag<2N_Wv}vlq{2E?PhDfax>` zm+1Ma?6>uK%hsLT+M#ta=o+)=)3w3T&HmFmoxQE6U0%X?e%E@QR@scjO-#iGO-%U) z@<5NvDzgByOM}P_k1(+lw;P?N^3+V~er5h#aOvJx20|bO!i$Vt6!9#Uy_^{pPpY_0xSzm<5Mh5EKJP| z&5|urk}M2Oj4VwJlFgGXjVzK<6OGMN%?%9`O_Nem6ZMjda@yk1%udNn&n!vI(M!)S zqlWngjZfG(wAmP0S%D=ROXGEe#w!MCFcAYL+IcOt$RG>J9-4X+XctoH&D_|?Fz1Ns z@wLAuakg{3e>mUh&{@r21!{9oip(=Pb~aLQcfxEdrsaRDb~ffz2mW=fWIz0T*PYnl z2szoHck-Ry&)PE{>X|%i;Sz~4c)c`6!u-L0x%oZH+h-?nwQN%C_?j|*^^3~aeG)0+ f6FdtUD&FwDn%%qQXwt{cxAZ%UESa-(QoTa}QNDI{ literal 0 HcmV?d00001 diff --git a/Russain SSL Installer/Russain SSL Installer.csproj b/Russain SSL Installer/Russain SSL Installer.csproj new file mode 100644 index 0000000..8e82cd7 --- /dev/null +++ b/Russain SSL Installer/Russain SSL Installer.csproj @@ -0,0 +1,26 @@ + + + + Exe + net10.0 + Russain_SSL_Installer + enable + enable + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + +