НачатьПроверкуСертификата: один аргумент callback, свой Root и отказ UTC-сроку

Учебные задачи

Полная callback-проверка actual собственного сертификата, точного собственного Root и текущего срока. Native success-handler принимает только контекст К; сертификат/Булево не выдумываются. Отдельный синхронный отрицательный тест использует реальную UTC-дату после срока.

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

Полный модуль управляемой формы только толстого Windows-клиента новой VM/пустой файловой ИБ; ручной own Root stage, 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 Тогда
        ВызватьИсключение "Своя callback-проверка еще не завершена";
    КонецЕсли;
    Занято85 = Истина;
    Статус85 = "Своя callback-проверка доверия еще не подтверждена";
    Попытка
        К = ПодготовитьСвойОпыт85();
        ПроверитьСвоеКорневоеДоверие85(К);
        К.Вставить("Запуск", Строка(Новый УникальныйИдентификатор));
        К.Вставить("Стадия", "Сертификат");
        К.Вставить("Завершено", Ложь);
        К.Вставить("Отчет", "UUID " + К.UUID + ": native callback сертификата с единственным контекстным аргументом подтвердил свою локальную цепочку/текущий срок; отрицательная sync UTC-дата после срока отвергнута. Отзыв/TSA/OCSP/qualified не проверены");
        КонтекстКрипто85 = К;
        Режим = РежимПроверкиСертификатаКриптографии.ИгнорироватьПроверкуВСпискеОтозванныхСертификатов;
        К.Менеджер.НачатьПроверкуСертификата(СвоеОповещение85("СвойСертификатПроверен85", К), К.Сертификат, Режим);
    Исключение
        Занято85 = Ложь;
        Статус85 = "Своя подготовка Root/начало callback не подтверждены";
        Если КонтекстКрипто85 <> Неопределено Тогда
            ЗавершитьСвойОпыт85(КонтекстКрипто85, Ложь);
        КонецЕсли;
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура СвойСертификатПроверен85(К) Экспорт
    Попытка
        ПроверитьСвоюСтадию85(К, "Сертификат");
        ПроверитьСвоеКорневоеДоверие85(К);
        ОтказСрока = Ложь;
        Попытка
            К.Менеджер.ПроверитьСертификат(К.Сертификат,
                РежимПроверкиСертификатаКриптографии.ИгнорироватьПроверкуВСпискеОтозванныхСертификатов,
                К.Сертификат.ДатаОкончания + 86400);
        Исключение
            ОтказСрока = Истина;
        КонецПопытки;
        Если Не ОтказСрока Тогда
            ВызватьИсключение "Своя дата после срока ошибочно принята";
        КонецЕсли;
        ЗавершитьСвойОпыт85(К, Истина);
    Исключение
        ЗавершитьСвойОпыт85(К, Ложь);
    КонецПопытки;
КонецПроцедуры

&НаКлиенте
Процедура ОшибкаСвоегоОпыта85(ИнформацияОбОшибке, СтандартнаяОбработка, К) Экспорт
    СтандартнаяОбработка = Ложь;
    Если ТипЗнч(ИнформацияОбОшибке) = Тип("ИнформацияОбОшибке") Тогда
        ЗавершитьСвойОпыт85(К, Ложь);
    Иначе
        ЗавершитьСвойОпыт85(К, Ложь);
        ВызватьИсключение "Ошибка callback не имеет native диагностического типа";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Перем КонтекстКрипто85;

&НаКлиенте
Функция СвоеОповещение85(Имя, К)
    Возврат Новый ОписаниеОповещения(Имя, ЭтотОбъект, К, "ОшибкаСвоегоОпыта85", ЭтотОбъект);
КонецФункции

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

&НаКлиенте
Процедура ЗавершитьСвойОпыт85(К, Успех)
    Если К.Завершено Тогда
        Возврат;
    КонецЕсли;
    К.Завершено = Истина;
    К.Менеджер.ПарольДоступаКЗакрытомуКлючу = "";
    Занято85 = Ложь;
    Если Успех Тогда
        Статус85 = К.Отчет;
    Иначе
        Статус85 = "Собственный криптографический опыт не подтвержден. Проверьте только свою изолированную VM; секреты и диагностический объект не выводятся";
    КонецЕсли;
    КонтекстКрипто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. На своей VM отдельно подготовьте own CSP/DER и explicit own Root-траст, сверив0ownдо/1точныйпосле. В форме укажите UUID и оба отдельных подтверждения.

  2. ПодготовитьСвойОпыт85 проверяет собственный пустой стенд/DER/реальные provider-имена; ПроверитьСвоеКорневоеДоверие85 еще раз сверяет точный own Root.

  3. Создайте контекст со свежим UUID запуска, фазой Сертификат и активным флагом. Не допускайте повторной команды.

  4. НачатьПроверкуСертификата принимает ОписаниеОповещения, actual СертификатКриптографии и режим только игнорирования CRL. В нем нет аргумента UTC-даты: дата проверяется текущая, четвертый выдуманный параметр не передается.

  5. У native success callback ровно1аргумент — ДополнительныеПараметры, здесь К. Это не callback НачатьПроверкуПодписи, где приходит сертификат плюс К.

  6. В СвойСертификатПроверен85 перепроверьте UUID/фазу/own Root. Отдельный sync ПроверитьСертификат с фактической ДатаОкончания+86400 должен отказать; native callback не изображается имеющим дату, которой у него нет.

  7. Error callback получает ИнформацияОбОшибке, СтандартнаяОбработка, К и всегда завершает эту задачу неподтвержденной. В этом certificate-уроке нет ожидаемой ошибки самого callback-положительного пути.

  8. Общий успех лишь после реального success callback и отказа sync-сроку. Сбросьте пароль own менеджера/Занято85; root/key/cert остаются только в VM, автоматической очистки нет.

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

  1. Success-handler имеет ровно1аргумент и экспорт; error-handler3nativeаргумента в правильном порядке.

  2. BeginCertificate имеет ровно3аргумента; не выдумана дата или возвращенный сертификат.

  3. Фаза/own UUID/Root проверяются повторно, отрицательный UTC-тест обязателен.

  4. Локальное доверие/срок не выдаются за отзыв, qualifiedCA, доверенную метку или проверку документа.

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

Ожидаемый ручной итог: actual однопараметровый callback подтверждает собственную локальную цепочку/текущий срок; дата после срока отвергается отдельным sync API. Runtime не выполнялся.

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

  1. Ошибка сертификата не является штатной отменой: финальный статус остается неподтвержденным, не переключается в успех.

  2. Один аргумент native completion важнее привычного шаблона Результат/К; у разных Начать API разные реальные контракты.

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

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

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

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

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