МенеджерКриптографии.ПроверитьСертификатАсинх

Методы · CheckCertificateAsync

Асинхронная функция. Проверяет сертификат. В случае ошибки генерируется исключительная ситуация.

Синтаксис

ПроверитьСертификатАсинх(<Сертификат>, <РежимПроверки>, <УниверсальнаяДатаПроверки>)
Полное описание, параметры и ограничения

МенеджерКриптографии.ПроверитьСертификатАсинх (CryptoManager.CheckCertificateAsync)

МенеджерКриптографии (CryptoManager)

ПроверитьСертификатАсинх (CheckCertificateAsync)

Доступен, начиная с версии 8.3.18.

Синтаксис:
ПроверитьСертификатАсинх(<Сертификат>, <РежимПроверки>, <УниверсальнаяДатаПроверки>)
Параметры:

<Сертификат> (обязательный)
Тип: СертификатКриптографии.
Проверяемый сертификат.

<РежимПроверки> (необязательный)
Тип: РежимПроверкиСертификатаКриптографии, Массив.
Указывает режим проверки.
Содержит один объект или массив объектов режимов проверки.

<УниверсальнаяДатаПроверки> (необязательный)
Тип: Дата.
Время проверки и построения цепочки сертификатов, указывается в универсальном времени (UTC).
Возвращаемое значение:
Тип: Обещание.
В случае успешного результата проверки результатом выполнения обещания является Неопределено. В случае ошибки объект Обещание будет содержать исключение, которое будет выброшено из оператора Ждать, аргументом которого будет данное Обещание.
Описание:

Асинхронная функция. Проверяет сертификат. В случае ошибки генерируется исключительная ситуация.

Доступность:

Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.

См. также:
МенеджерКриптографии, метод ПроверитьСертификат
МенеджерКриптографии, метод НачатьПроверкуСертификата

Использование в версии:

Доступен, начиная с версии 8.3.18.

Описание изменено в версии 8.3.27.

Методическая информация

Практические примеры

Ждать: проверить свой локально доверенный сертификат и UTC-срок

Отдельный явный ручной trust-fixture устанавливает в Root новой VM только свой точный публичный DER. Полный1С модуль проверяет own My/Root, корректность при UTC-дате внутри срока и обязательный отказ после реального срока. Не использует AllowTest/IgnoreTime и не обещает отзыв или qualifiedCA.

Где и как запускать

Полный клиентский модуль собственной формы на новой Windows VM; только отдельный собственный manual Root trust, runtime0.

Подготовка

  1. Создайте новую отдельную изолированную Windows VM, отдельного только учебного Windows-пользователя и новую пустую файловую ИБ платформы ровно8.5.1.1343. Имя корня конфигурации УчебныеКриптоОповещения85, русский встроенный язык, Такси, совместимость Не использовать. Рабочие пользователи, базы и реальные ключи запрещены.

  2. В этой конфигурации не должно быть предметных объектов, регистров, заданий, внешних источников или подписок; не устанавливайте расширения. Полный server guard каждого модуля проверяет metadata/три источника расширений/версию/транзакцию.

  3. Создайте отдельную внешнюю обработку УчебныеКриптоОповещения85 с основной управляемой формой. Для каждого урока используйте отдельную форму либо целиком заменяйте полный модуль; дублирующие одноименные процедуры не склеивайте.

  4. Реквизиты формы: UUIDКомплекта85 Строка36; ОжидаемыйОтпечаток85 Строка40; КаталогДляКомплекта85 Строка0, ТолькоПросмотр; Статус85 Строка0, многострочный ТолькоПросмотр; ПодтверждаюУчебнуюVM85 Булево исходноЛожь. Назначьте ПриСозданииНаСервере и ПриОткрытии из полного кода. Добавьте команду ВыполнитьКрипто85 с одноименным обработчиком/кнопкой, ИзменяетСохраняемыеДанныеЛожь.

  5. Для трех уроков проверки сертификата дополнительно создайте ПодтверждаюСвоеRootДоверие85 Булево исходноЛожь. Для обычного CMS/BES/callback/audit доверие Root не требуется и этот флаг не используется.

  6. Запускайте обработку только толстым управляемым Windows-клиентом8.5.1.1343 под тем же новым учебным пользователем. Включите режим синхронных вызовов: даже Ждать/callback варианты имеют синхронную подготовку DER/провайдера/собственных хранилищ. Нельзя переносить ключи/менеджер на сервер.

  7. В модуль своей формы вставьте весь основной код выбранного урока. Он проверяет собственный локальный DER и legacy CSP, реальные имена SHA256/RSA/AES256 из возможностей; не выбирает случайный персональный сертификат.

  8. В своей новой VM сохраните полный вспомогательный PowerShell как own_crypto85_fixture.ps1. После открытия формы скопируйте точный клиентский КаталогДляКомплекта85 и вручную в Windows PowerShell5.1 выполните .\own_crypto85_fixture.ps1 -BaseDirectory "скопированный каталог". Только этот ВАШ ручной этап создает один новый selfsigned RSA2048 legacy CSP key/type24/KeyExchange в CurrentUser My и новый публичный DER OwnCrypto85-UUID.

  9. Закрытый ключ NonExportable, KeyProtectionNone — только учебный. Скрипт не устанавливает Root-доверие и не экспортирует private key. Запишите UUID/публичный thumbprint; UUID введите в форму без изменения регистра, а40hexсимволов thumbprint — в ОжидаемыйОтпечаток85. Native Отпечаток имеет тип ДвоичныеДанные/SHA1, поэтому в модуле он переводится в hex перед сравнением с PowerShell. CN субъекта/издателя DER обязательно равен OwnCrypto85-UUID. Не создавайте новые комплекты без проверки результатов прежней подготовки.

  10. Для проверки сертификата сохраните ОТДЕЛЬНЫЙ полный trust-PowerShell как trust_only_own_uuid_der.ps1 и вручную выполните .\trust_only_own_uuid_der.ps1 -BaseDirectory "скопированный каталог" -OwnUUID "точный свой UUID" -ConfirmIsolatedVMTrust, только на этой VM. Он требует0 совпадающих именно СВОИХ Root-cert по UUID subject/thumbprint, не0 всех встроенных Root; сверяет единственный свой My/private key и точный DER; добавляет только свой публичный DER; проверяет1точный own Root и локальную одноэлементную цепочку. Повторный импорт/замена запрещены.

  11. Отключите внешнюю сеть только у своей VM через ее настройки до учебных запусков. Собственный selfsigned не имеет CDP/AIA/TSA адресов, проверки отзыва явно пропускаются; это отдельная ограниченная локальная модель доверия, не production политика безопасности.

  12. После собственного trust-этапа включите дополнительный флаг формы лишь для certificate-check уроков. Математика CMS/BES проверяется отдельно с ПроверятьДополнительныеАтрибутыЛожь; она не является проверкой цепочки. Проверки сертификата сохраняют контроль подписи/времени, не используют AllowTest или IgnoreTime.

  13. Не закрывайте форму/клиент во время ожидания или callback-цепочки. Повторная команда отказывает по Занято85. Успех выставляется только после всех стадий/отрицательных тестов; закрытие процесса не гарантирует выполнение финального callback.

  14. Ручная подготовка оставляет свой сертификат/ключ, а trust-этап еще и свой Root; автоматического удаления/отката нет. Никакие ключи, подписи, хранилища, сети или 1С нами здесь не запускались и не менялись. Все результаты до вашего ручного опыта — ожидаемые, runtime0.

&НаКлиенте
Асинх Процедура ВыполнитьКрипто85(Команда)
    Если Занято85 Тогда
        ВызватьИсключение "Дождитесь собственной предыдущей проверки";
    КонецЕсли;
    Занято85 = Истина;
    Статус85 = "Свое локальное доверие/срок еще не подтверждены";
    Опыт = Неопределено;
    Попытка
        Опыт = ПодготовитьСвойОпыт85();
        ПроверитьСвоеКорневоеДоверие85(Опыт);
        Режим = РежимПроверкиСертификатаКриптографии.ИгнорироватьПроверкуВСпискеОтозванныхСертификатов;
        ДатаВнутри = Опыт.Сертификат.ДатаНачала + 86400;
        ПослеОкончания = Опыт.Сертификат.ДатаОкончания + 86400;
        Если ДатаВнутри >= Опыт.Сертификат.ДатаОкончания Тогда
            ВызватьИсключение "Свой сертификат должен иметь семь дней учебного срока, UTC-границы берутся из реального DER";
        КонецЕсли;
        Итог = Ждать Опыт.Менеджер.ПроверитьСертификатАсинх(Опыт.Сертификат, Режим, ДатаВнутри);
        Если Итог <> Неопределено Тогда
            ВызватьИсключение "Успешное обещание проверки сертификата должно дать Неопределено, не Булево";
        КонецЕсли;
        ОтказСрока = Ложь;
        Попытка
            Ждать Опыт.Менеджер.ПроверитьСертификатАсинх(Опыт.Сертификат, Режим, ПослеОкончания);
        Исключение
            ОтказСрока = Истина;
        КонецПопытки;
        Если Не ОтказСрока Тогда
            ВызватьИсключение "Реальный срок собственного сертификата нельзя игнорировать";
        КонецЕсли;
        Статус85 = "UUID " + Опыт.UUID + ": точный own DER в My/Root; локальная цепочка при UTC-дате внутри срока принята; дата после срока отказана. Отзыв/OCSP/TSA/юридическая квалификация не проверены";
    Исключение
        Статус85 = "Собственное Root-доверие/срок не подтверждены. Не включайте AllowTest и не отключайте проверку времени ради успеха";
    КонецПопытки;
    Если Опыт <> Неопределено Тогда
        Опыт.Менеджер.ПарольДоступаКЗакрытомуКлючу = "";
    КонецЕсли;
    Занято85 = Ложь;
КонецПроцедуры

&НаКлиенте
Перем Занято85;

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    ПроверитьСвойПустойСтенд();
    UUIDКомплекта85 = "";
    ОжидаемыйОтпечаток85 = "";
    Статус85 = "Свой криптографический опыт не выполнен";
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Занято85 = Ложь;
    КаталогДляКомплекта85 = КаталогВременныхФайлов();
КонецПроцедуры

&НаКлиенте
Функция ПодготовитьСвойОпыт85()
    ПроверитьСеанс85();
    #Если ТолстыйКлиентУправляемоеПриложение Тогда
        Система = Новый СистемнаяИнформация;
        Если (Система.ТипПлатформы <> ТипПлатформы.Windows_x86
            И Система.ТипПлатформы <> ТипПлатформы.Windows_x86_64) Или Не ПодтверждаюУчебнуюVM85 Тогда
            ВызватьИсключение "Нужна собственная изолированная Windows VM и толстый управляемый клиент8.5.1.1343";
        КонецЕсли;
        СвойUUID = Новый УникальныйИдентификатор(UUIDКомплекта85);
        ТекстUUID = НРег(Строка(СвойUUID));
        Если UUIDКомплекта85 <> ТекстUUID Тогда
            ВызватьИсключение "Нужен точный UUID своей PowerShell-подготовки";
        КонецЕсли;
        БазаФайлов = КаталогВременныхФайлов();
        Если Прав(БазаФайлов, 1) <> "\" Тогда
            БазаФайлов = БазаФайлов + "\";
        КонецЕсли;
        ИмяDER = БазаФайлов + "OwnCrypto85-" + ТекстUUID + "\own-public.cer";
        СвойФайл = Новый Файл(ИмяDER);
        Если Не СвойФайл.Существует() Или Не СвойФайл.ЭтоФайл() Тогда
            ВызватьИсключение "Нет своего публичного DER-файла";
        КонецЕсли;
        Если СвойФайл.Размер() <= 0 Или СвойФайл.Размер() > 65536 Тогда
            ВызватьИсключение "Свой DER пуст или слишком велик";
        КонецЕсли;
        Публичный = Новый СертификатКриптографии(Новый ДвоичныеДанные(ИмяDER));
        Субъект = Публичный.Субъект;
        Издатель = Публичный.Издатель;
        Если ТипЗнч(Субъект) <> Тип("ФиксированнаяСтруктура") Или ТипЗнч(Издатель) <> Тип("ФиксированнаяСтруктура") Тогда
            ВызватьИсключение "Native subject/issuer должны быть readonly структурами собственного DER";
        КонецЕсли;
        Если Не Субъект.Свойство("CN", ИмяСубъекта) Или Не Издатель.Свойство("CN", ИмяИздателя) Тогда
            ВызватьИсключение "Нужен реальный CN собственного selfsigned DER";
        КонецЕсли;
        Если ИмяСубъекта <> "OwnCrypto85-" + ТекстUUID Или ИмяИздателя <> ИмяСубъекта Тогда
            ВызватьИсключение "Публичный DER не принадлежит нашему собственному UUID selfsigned комплекту";
        КонецЕсли;
        Если СтрДлина(ОжидаемыйОтпечаток85) <> 40
            Или ВРег(ОжидаемыйОтпечаток85) <> ВРег(ПолучитьHexСтрокуИзДвоичныхДанных(Публичный.Отпечаток)) Тогда
            ВызватьИсключение "Нужен точный публичный SHA1 hex отпечаток из собственной ручной подготовки";
        КонецЕсли;
        Менеджер = Новый МенеджерКриптографии("Microsoft Enhanced RSA and AES Cryptographic Provider", "", 24,
            ИспользованиеИнтерактивногоРежимаКриптографии.НеИспользовать);
        Информация = Менеджер.ПолучитьИнформациюМодуляКриптографии();
        Если ТипЗнч(Информация) <> Тип("ИнформацияМодуляКриптографии") Тогда
            ВызватьИсключение "Свой провайдер не вернул возможности";
        КонецЕсли;
        Если Информация.АлгоритмыХеширования.Найти("SHA256") = Неопределено
            Или Информация.АлгоритмыПодписи.Найти("RSA") = Неопределено
            Или Информация.АлгоритмыШифрования.Найти("AES256") = Неопределено Тогда
            ВызватьИсключение "Нужны подтвержденные названия SHA256/RSA/AES256 этого провайдера. Не подставляйте неизвестные имена";
        КонецЕсли;
        Менеджер.АлгоритмХеширования = "SHA256";
        Менеджер.АлгоритмПодписи = "RSA";
        Менеджер.АлгоритмШифрования = "AES256";
        Менеджер.ВключениеСертификатовВПодпись = РежимВключенияСертификатовКриптографии.ВключатьСертификатСубъекта;
        Менеджер.ПарольДоступаКЗакрытомуКлючу = "";
        Хранилище = Менеджер.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты,
            РасположениеХранилищаСертификатовКриптографии.ДанныеПользователяОС);
        Кандидат = Хранилище.НайтиПоОтпечатку(Публичный.Отпечаток);
        Если ТипЗнч(Кандидат) <> Тип("СертификатКриптографии") Тогда
            ВызватьИсключение "Нет своего сертификата с привязкой к ключу в Личном текущего пользователя";
        КонецЕсли;
        ПроверитьСвойСертификат85(Кандидат, Публичный);
        ТекстДанных = "OwnCrypto85:" + ТекстUUID + "|Книга|Количество=3|Цена=250";
        Данные = ПолучитьДвоичныеДанныеИзСтроки(ТекстДанных, КодировкаТекста.UTF8);
        Возврат Новый Структура("Менеджер,Сертификат,Данные,UUID", Менеджер, Кандидат, Данные, ТекстUUID);
    #Иначе
        ВызватьИсключение "Полный урок поддерживает только толстый управляемый клиент Windows, не сервер, тонкий, веб или мобильный";
    #КонецЕсли
КонецФункции

&НаКлиенте
Процедура ПроверитьСвойСертификат85(Кандидат, Ожидание)
    Если ТипЗнч(Кандидат) <> Тип("СертификатКриптографии") Тогда
        ВызватьИсключение "Нет реального сертификата в результате";
    КонецЕсли;
    Если Base64Строка(Кандидат.Выгрузить()) <> Base64Строка(Ожидание.Выгрузить()) Тогда
        ВызватьИсключение "Отпечаток без точного DER-совпадения не принимается";
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьСеанс85()
    ПроверитьСвойПустойСтенд();
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСвоеКорневоеДоверие85(Опыт)
    Корни = Опыт.Менеджер.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.КорневыеСертификаты,
        РасположениеХранилищаСертификатовКриптографии.ДанныеПользователяОС);
    Корневой = Корни.НайтиПоОтпечатку(Опыт.Сертификат.Отпечаток);
    Если ТипЗнч(Корневой) <> Тип("СертификатКриптографии") Тогда
        ВызватьИсключение "Сначала вручную импортируйте только свой точный DER в Root своей новой VM отдельной стадией";
    КонецЕсли;
    ПроверитьСвойСертификат85(Корневой, Опыт.Сертификат);
    Если Не ПодтверждаюСвоеRootДоверие85 Тогда
        ВызватьИсключение "Нужно отдельное явное подтверждение учебного доверия своему DER, не всей ОС";
    КонецЕсли;
КонецПроцедуры
PowerShell: own_crypto85_fixture.ps1

Новая собственная Windows VM, не модуль1С.

Отдельный полный ручной файл только на новой собственной Windows VM: новый собственный CSP-key/My-cert/publicDER; здесь не запускался.

param([Parameter(Mandatory=$true)][string]$BaseDirectory)
$ErrorActionPreference = 'Stop'
if ([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) {throw 'Use only your isolated Windows VM'}
$taskBase = (Resolve-Path -LiteralPath $BaseDirectory).Path
if (-not (Test-Path -LiteralPath $taskBase -PathType Container)) {throw 'Copy the real client temporary directory from your own1C form'}
$taskIdentity = [guid]::NewGuid().ToString()
$taskFolder = Join-Path $taskBase ('OwnCrypto85-' + $taskIdentity)
if (Test-Path -LiteralPath $taskFolder) {throw 'Own UUID directory already exists'}
$taskSubject = 'CN=OwnCrypto85-' + $taskIdentity
$taskParameters = @{
    Type = 'Custom'
    Subject = $taskSubject
    FriendlyName = 'OwnCrypto85-' + $taskIdentity
    Provider = 'Microsoft Enhanced RSA and AES Cryptographic Provider'
    Container = 'OwnCrypto85-' + $taskIdentity
    KeyAlgorithm = 'RSA'
    KeyLength = 2048
    KeySpec = 'KeyExchange'
    KeyUsage = @('DigitalSignature','KeyEncipherment')
    KeyExportPolicy = 'NonExportable'
    KeyProtection = 'None'
    HashAlgorithm = 'SHA256'
    NotAfter = (Get-Date).AddDays(7)
    CertStoreLocation = 'Cert:\CurrentUser\My'
}
$taskCertificate = New-SelfSignedCertificate @taskParameters
if ($taskCertificate.Subject -ne $taskSubject -or -not $taskCertificate.HasPrivateKey) {throw 'Own certificate identity/private key not confirmed; inspect your VM manually'}
$taskKey = $taskCertificate.PrivateKey
if ($taskKey -isnot [System.Security.Cryptography.RSACryptoServiceProvider]) {throw 'Expected own legacy RSA CSP key, not CNG'}
try {
    $taskKeyInfo = $taskKey.CspKeyContainerInfo
    if ($taskKeyInfo.ProviderName -ne $taskParameters.Provider -or $taskKeyInfo.ProviderType -ne 24 -or $taskKeyInfo.MachineKeyStore) {throw 'Wrong provider, type or account store'}
    if ($taskKeyInfo.KeyContainerName -ne $taskParameters.Container) {throw 'Wrong own key container'}
    New-Item -ItemType Directory -Path $taskFolder | Out-Null
    $taskDer = $taskCertificate.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::Cert)
    $taskFile = Join-Path $taskFolder 'own-public.cer'
    $taskStream = [System.IO.File]::Open($taskFile,[System.IO.FileMode]::CreateNew,[System.IO.FileAccess]::Write,[System.IO.FileShare]::None)
    try { $taskStream.Write($taskDer,0,$taskDer.Length) } finally { $taskStream.Dispose() }
    Write-Output ('Own UUID: ' + $taskIdentity)
    Write-Output ('Own public DER: ' + $taskFile)
    Write-Output ('Own subject: ' + $taskCertificate.Subject)
    Write-Output ('Own thumbprint: ' + $taskCertificate.Thumbprint)
    Write-Output 'A new private key remains in CurrentUser My. No root trust, network, export of private key or automatic cleanup.'
} finally {
    $taskKey.Dispose()
    $taskCertificate.Dispose()
}
PowerShell: trust_only_own_uuid_der.ps1

Только новая собственная Windows VM, никогда рабочий пользователь/компьютер.

Отдельная явно подтверждаемая ручная стадия: own DER/UUID/My/private-key;0ownRoot→1exactRoot; без смены чужих Root. Здесь trust/stores не менялись.

param(
    [Parameter(Mandatory=$true)][string]$BaseDirectory,
    [Parameter(Mandatory=$true)][string]$OwnUUID,
    [Parameter(Mandatory=$true)][switch]$ConfirmIsolatedVMTrust
)
$ErrorActionPreference = 'Stop'
if (-not $ConfirmIsolatedVMTrust -or [Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT) {throw 'Only an explicitly confirmed own isolated Windows VM'}
$taskUUID = ([guid]::Parse($OwnUUID)).ToString()
if ($taskUUID -ne $OwnUUID -or $taskUUID -eq [guid]::Empty.ToString()) {throw 'Exact nonzero own UUID required'}
$taskBase = (Resolve-Path -LiteralPath $BaseDirectory).Path
$taskFolder = Join-Path $taskBase ('OwnCrypto85-' + $taskUUID)
$taskPublicFile = Join-Path $taskFolder 'own-public.cer'
$taskResolvedFolder = (Resolve-Path -LiteralPath $taskFolder).Path
if ($taskResolvedFolder -ne [System.IO.Path]::GetFullPath($taskFolder)) {throw 'Own UUID path was redirected'}
if ((Get-Item -LiteralPath $taskResolvedFolder).Attributes -band [System.IO.FileAttributes]::ReparsePoint) {throw 'No reparse-point own directory'}
$taskFileInfo = Get-Item -LiteralPath $taskPublicFile
if ($taskFileInfo.PSIsContainer -or $taskFileInfo.Length -le 0 -or $taskFileInfo.Length -gt 65536 -or ($taskFileInfo.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {throw 'Only own bounded public DER file'}
$taskPublic = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $taskPublicFile
$taskExpectedSubject = 'CN=OwnCrypto85-' + $taskUUID
$taskOwnDer = [Convert]::ToBase64String($taskPublic.RawData)
$taskMy = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList 'My','CurrentUser'
$taskRoot = New-Object System.Security.Cryptography.X509Certificates.X509Store -ArgumentList 'Root','CurrentUser'
try {
    if ($taskPublic.Subject -ne $taskExpectedSubject -or $taskPublic.Issuer -ne $taskExpectedSubject) {throw 'Only exact own self-signed UUID certificate'}
    if ([DateTime]::UtcNow -lt $taskPublic.NotBefore.ToUniversalTime() -or [DateTime]::UtcNow -ge $taskPublic.NotAfter.ToUniversalTime()) {throw 'Own certificate is not currently valid'}
    $taskMy.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
    $taskOwnMy = @($taskMy.Certificates | Where-Object {$_.Thumbprint -eq $taskPublic.Thumbprint -or $_.Subject -eq $taskExpectedSubject})
    if ($taskOwnMy.Count -ne 1 -or -not $taskOwnMy[0].HasPrivateKey -or [Convert]::ToBase64String($taskOwnMy[0].RawData) -ne $taskOwnDer) {throw 'Exact sole own My certificate/private-key binding not proven'}
    $taskRoot.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
    $taskOwnRootBefore = @($taskRoot.Certificates | Where-Object {$_.Thumbprint -eq $taskPublic.Thumbprint -or $_.Subject -eq $taskExpectedSubject})
    if ($taskOwnRootBefore.Count -ne 0) {throw 'Own UUID root already exists; do not automatically repeat or replace trust'}
    $taskRoot.Add($taskPublic)
    $taskOwnRootAfter = @($taskRoot.Certificates | Where-Object {$_.Thumbprint -eq $taskPublic.Thumbprint -or $_.Subject -eq $taskExpectedSubject})
    if ($taskOwnRootAfter.Count -ne 1 -or [Convert]::ToBase64String($taskOwnRootAfter[0].RawData) -ne $taskOwnDer) {throw 'Own root DER postcondition not proven; inspect only own VM manually'}
    $taskChain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
    try {
        $taskChain.ChainPolicy.RevocationMode = [System.Security.Cryptography.X509Certificates.X509RevocationMode]::NoCheck
        $taskChain.ChainPolicy.VerificationFlags = [System.Security.Cryptography.X509Certificates.X509VerificationFlags]::NoFlag
        $taskChain.ChainPolicy.UrlRetrievalTimeout = [TimeSpan]::Zero
        if (-not $taskChain.Build($taskPublic)) {throw 'Only local own trust chain failed; no success promised'}
        if ($taskChain.ChainElements.Count -ne 1 -or [Convert]::ToBase64String($taskChain.ChainElements[0].Certificate.RawData) -ne $taskOwnDer) {throw 'Expected only our one self-signed local chain element'}
    } finally {$taskChain.Dispose()}
    Write-Output ('Own UUID root trust added: ' + $taskUUID)
    Write-Output ('Own public thumbprint: ' + $taskPublic.Thumbprint)
    Write-Output 'Only own DER imported to CurrentUser Root. No revocation/TSA/OCSP/qualified-signature claim; no automatic cleanup.'
} finally {
    $taskRoot.Close()
    $taskRoot.Dispose()
    $taskMy.Close()
    $taskMy.Dispose()
    $taskPublic.Dispose()
}

Разбор по шагам

  1. Сначала выполните свою CSP/DER-подготовку в новой VM; не ставьте Root-доверие для уроков математики CMS/BES без отдельной необходимости.

  2. Для этой задачи отдельно вручную запустите полный trust-script с точным BaseDirectory, своимUUID и ConfirmIsolatedVMTrust. До Add он доказывает0 совпадающих own Root, после1точный DER; чужие встроенные Root не удаляются/не заменяются.

  3. Подтвердите отдельный Root-флаг формы. 1С получает Root текущего пользователя и ищет именно отпечаток собственного сертификата, затем сравнивает DER побайтно с найденным собственным My.

  4. Даты ДатаНачала/ДатаОкончания в native СертификатКриптографии читаются в UTC. Для положительного пути выбираем реальную ДатаНачала+1день, проверяя ее нахождение до окончания7-дневного сертификата.

  5. ПроверитьСертификатАсинх черезЖдать проверяет actual own cert и дату внутри срока. Пропускается только CRL, поскольку offline-модель не содержит сервера отзыва; подпись и срок не отключаются.

  6. Успешное обещание возвращает Неопределено; проверьте это. Булево/сертификат не являются результатом этого native API.

  7. Отрицательная дата = реальная ДатаОкончания+1день в UTC. Второй вызов должен отказать по сроку; если его нет, итог запрещен.

  8. Итог различает local Root-доверие и срок от математической подписи файла. Ни CRL/OCSP, ни внешняя цепочкаУЦ, ни TSA, ни юридический статус не проверены; не меняйте эти границы сообщением об успехе.

Как проверить результат

  1. My и Root указывают на точный own DER/UUID; неизвестный Root или один похожий thumbprint без DER не принимается.

  2. Положительный UTC-интервал принимается, дата после срока обязательно отвергается.

  3. AllowTest/IgnoreTime/IgnoreSignature отсутствуют; единственное послабление CRL явно объявлено ограничением.

  4. До ручного запуска хранилища и доверие не менялись. Три вида проверки (математика, локальная цепочка, срок) не смешиваются.

Ожидаемый результат

Ожидаемый ручной результат: точный собственный Root принят для локальной одноэлементной цепочки, UTC-дата внутри срока принята, после срока отвергнута. Отзыв/TSA/OCSP/юридическая квалификация не подтверждены.

На что обратить внимание

  1. Импорт публичного DER в Root действительно меняет доверие только после вашего отдельного ручного запуска. На рабочем компьютере такую подготовку использовать запрещено.

  2. РазрешитьТестовыеСертификаты не является доказательством доверия. Урок не использует этот режим и не отключает реальный срок ради успеха.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.