Объект защищенного соединения КриптоПро.
Примеры платформы
ssl1 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаОС,
Новый СертификатыУдостоверяющихЦентровОС,
РежимПроверкиОтзываСертификатовУдостоверяющихЦентров.Строгий);
ssl2 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаОС(СпособВыбораСертификатаОС.Авто),
Новый СертификатыУдостоверяющихЦентровФайл("C:/certs/myca.pem"));
ssl3 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаФайл("C:/certs/user.p12", "password" ),
Новый СертификатыУдостоверяющихЦентровФайл("C:/certs/myca.pem"));
ssl4 = Новый ЗащищенноеСоединениеКритоПро(
неопределено,
неопределено);Полное описание, параметры и ограничения
ЗащищенноеСоединениеКриптоПро (CryptoProSecureConnection)
ЗащищенноеСоединениеКриптоПро (CryptoProSecureConnection)
Доступен, начиная с версии 8.3.24.
Свойства:
РежимПроверкиОтзываTLSСертификатаСервера (ServerTLSCertificateRevocationCheckMode)
СертификатКлиента (ClientCertificate)
СертификатыУдостоверяющихЦентров (CertificationAuthorityCertificates)
Конструкторы:
По объектам используемых сертификатов
Описание:
Объект защищенного соединения КриптоПро.
Доступность:
Тонкий клиент, сервер, толстый клиент, внешнее соединение.
Пример:
ssl1 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаОС,
Новый СертификатыУдостоверяющихЦентровОС,
РежимПроверкиОтзываСертификатовУдостоверяющихЦентров.Строгий);
ssl2 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаОС(СпособВыбораСертификатаОС.Авто),
Новый СертификатыУдостоверяющихЦентровФайл("C:/certs/myca.pem"));
ssl3 = Новый ЗащищенноеСоединениеКритоПро(
Новый СертификатКлиентаФайл("C:/certs/user.p12", "password" ),
Новый СертификатыУдостоверяющихЦентровФайл("C:/certs/myca.pem"));
ssl4 = Новый ЗащищенноеСоединениеКритоПро(
неопределено,
неопределено);
См. также:
СертификатКлиентаОС
СертификатКриптографии
СертификатКлиентаФайл
СертификатыУдостоверяющихЦентровОС
СертификатыУдостоверяющихЦентровФайл
Использование в версии:
Доступен, начиная с версии 8.3.24.
Методическая информация
Практические примеры
Четыре настоящих TLS-паспорта: собственный офлайн-план 17 → 12 + 5, без соединения
Реальный public-CA file source и КриптоПро/OpenSSL-конструкторы. Readonly поля определяют конкретные отказы собственного потребителя; полный finite passport и исходный публичный файл читаются повторно. Никакого TLS, доверия или подписи результат не обещает.
Где и как запускать
Полный модуль своей ОбщаяФорма.ПаспортTLS85. Только Windows thick-managed8.5.1.1343; native profile/fileCA/hash локальны, директивы и полный serverguard приложены.
Подготовка
Только новая собственная изолированная Windows VM и собственная НОВАЯ пустая файловая ИБ по точному пути C:\1c-labs\OwnTLSProfileGuard85_932d19b2-0a48-4a03-ab90-dd39aed82704\IB. Платформа8.5.1.1343, русский встроенный язык. Все дальнейшие запуск/создание публичного сертификата/файлов выполняете вы вручную только там; агент их не выполнял.
В Конфигураторе у корня: Имя=УчебныйПаспортTLS85, РежимСовместимости=НеИспользовать, ОсновнойРежимЗапуска=УправляемоеПриложение, Такси. Прикладные справочники/документы/регистры/планы/константы/обработки/отчеты, службы, общие реквизиты, задания, подписки и расширения не добавляйте. Не открывайте рабочую ИБ. Сервер проверяет metadata enum через Метаданные.СвойстваОбъектов, не через недоступный bare enum.
Роли → единственная ПаспортTLS85: АдминистрированиеДанных, Администрирование, АктивныеПользователи, ТолстыйКлиент и просмотр/использование своей общей формы. Администрирование с необходимым АдминистрированиеДанных нужно для ПолучитьПользователей/Роли, АктивныеПользователи для описаний соединений. Администрирование → Пользователи: только TLS85Ученик с единственной ПаспортTLS85. Пароль выбирает человек и не помещает в пример. Это только лабораторные права, не рекомендация production.
ОбщиеМодули → ПаспортПрофилей85: ГлобальныйНет, СерверДа, ВызовСервераДа, КлиентОбычноеПриложениеНет, КлиентУправляемоеПриложениеНет, ВнешнееСоединениеНет, ПривилегированныйНет, ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать. Вставьте COMMON целиком. Свой общий модуль проверяет точный File-путь/версию/NoUse/схему/пользователя/роль/один сеанс; секретные данные и сертификаты не читает.
ОбщиеФормы → управляемая ПаспортTLS85. Реквизиты: КаталогДляCA85 Строка длиной0, поле ТолькоПросмотрДа; UUIDКомплекта85 Строка36 с обычным полем ввода; Статус85 Строка длиной0 с многострочным полем ТолькоПросмотрДа. Данные каждого поля равны имени соответствующего реквизита. Команда ПроверитьПрофили85, кнопка, действие ПроверитьПрофили85. Вставьте CODE целиком и назначьте настоящие ПриСозданииНаСервере2/ПриОткрытии1. Команду/события не вызывайте вручную.
Конфигурация → Модуль управляемого приложения: APP целиком, настоящее ПриНачалеРаботыСистемы0. Обновите только свою CF, закройте Конфигуратор и другие соединения. Запустите собственную ИБ толстым управляемым Windows-клиентом под TLS85Ученик. Пульт показывает реальный клиентский временный каталог; не угадывайте его по переменным окружения. Native TLS/file-source объекты и enum остаются локально на клиенте; сервер получает только вызов проверки своего сеанса без этих объектов.
В этой же собственной VM подготовьте Python3 и cryptography48.0.0. Нижний полный Python-блок сохраните как own_tls85_public_ca.py в своем учебном каталоге, НЕ в модуле1С. Запустите вручную python own_tls85_public_ca.py --base "точный КаталогДляCA85, показанный своим пультом". Не используйте никакие существующие сертификаты человека, контейнеры, клиентский PKCS12, пароль, ОС-хранилище или чужую папку. Pythonhelper создаст новый UUID-каталог и только ca.pem/manifest.json; введите показанный UUID в UUIDКомплекта85.
Helper генерирует свой временный RSA CA-ключ только в памяти, самоподписанный публичный CA с ownUUID/CN, BasicConstraints ca=True/path_length0, keyCertSign/crlSign и семь суток от фактическогоUTC. Он выполняет настоящий PEM roundtrip и проверку своей self-signature ДО записи публичного файла. Ключ не сериализуется, клиентский сертификат/ключ не создаются и доверие ОС не импортируется. Это не гарантирует стирания копий ключа из памяти Python; после ручной подготовки завершите этот учебный процесс. mode0700 не является обещанием WindowsACL.
Конструктор КриптоПро может отказать при отсутствующем/несовместимом модуле криптографии. Подготовка установленной вами учебной VM не считается гарантией поддержки провайдера или алгоритмов. При отказе СТОП: не подставляйте OpenSSL/другие сертификаты автоматически, не снижайте режим. В установленной справке прямо указан отказ на Linux/macOS без CryptoPro CPS; здесь выбран только Windows, а не утверждение, что Windows всегда гарантирует успех. Сертификат RSA используется только как собственный публичный источник данного офлайн-паспорта; успешное криптографическое применение этим не доказано.
Четыре реальные конфигурации: CSP без CA/Strict/2 заявки; CSP со своим CA/Auto/3; CSP со своим CA/Strict/5; OpenSSL со своим CA/Strict/7. Клиентский сертификат у ВСЕХ явно Неопределено. Наш учебный потребитель требует собственный CA-файл и явный эффективныйStrict, поэтому принимает только5+7=12 из17, отклоняет2+3=5. Это правило только собственного плана, НЕ универсальная рекомендация безопасности и НЕ подтверждение TLS/цепочки/отзыва/доступа.
CAНеопределено означает отсутствие проверки сертификата сервера по native контракту даже при Strict. РежимНеопределено отдельно означает Auto, а не отсутствие CA; исходное nullable значение сохраняется в паспорте. Auto зависит от IgnoreServerCertificatesChainRevocationSoftFail в conf.cfg, по справке defaulttrue/мягкий режим: код не читает и не меняет этот файл. Strict при недоступном сервере проверки отзыва приводит к ошибке реальной проверки. Этот урок НЕ обещает offlinehandshake, CRL/OCSP, mTLS, SMTP, подпись или интернет-запрос.
Нажмите только настоящую кнопку ПроверитьПрофили85. По реальным getter-полям проверятся четыре полных случая, два полных семипольных чтения каждого профиля, все собственные количества и суммы17/12/5. После повторного SHA256 своего публичногоCA и повторного паспорта своего сеанса появится успешная сводка. JSON reader: первичная ошибка сохраняется сразу; если штатный Close уже начат, повторного Close нет. Иначе разрешена ровно одна cleanup-попытка; ее ошибка сообщается отдельно, состояние читателя после ошибки считается неизвестным. При любом отказе остаетсяСТОП; новый ручной опыт требует закрыть пульт, выяснить причину и при поврежденном комплекте создать новый собственный UUID-комплект, не автоматический retry/откат.
Сверка publicUUID/маркера/имени/SHA обнаруживает случайные изменения, но не доказывает авторство против злоумышленника, способного менять и манифест, и файл. Чтения/конструкторы не атомарны; не должно быть чужих процессов, меняющих свою папку. ИмяФайла/type/passport не доказывают загрузку сертификата, пароль, срок, доверие или работу lazy native reader во время будущегоhandshake. ОС-хранилища не просматриваются. После ручного опыта завершите собственные процессы и вручную удалите только напечатанную собственную UUID-папку либо утилизируйте лабораторную VM; программа автоматически ничего не удаляет.
&НаКлиенте
Перем Остановлен85;
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПаспортПрофилей85.ПроверитьСвоюИБ85();
UUIDКомплекта85 = "";
Статус85 = "Подготовьте только собственный публичный CA. TLS-соединение здесь не устанавливается.";
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Остановлен85 <> Неопределено Тогда
ВызватьИсключение "Повторная инициализация не сбрасывает остановку";
КонецЕсли;
ПроверитьСреду85();
КаталогДляCA85 = КаталогВременныхФайлов();
Если Прав(КаталогДляCA85, 1) <> "\" Тогда
КаталогДляCA85 = КаталогДляCA85 + "\";
КонецЕсли;
Остановлен85 = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьПрофили85(Команда)
Если Остановлен85 <> Ложь Тогда
ВызватьИсключение "СТОП: закройте свой пульт, выясните причину, не повторяйте автоматически";
КонецЕсли;
Остановлен85 = Истина;
Статус85 = "Успешный паспорт пока не подтвержден";
Попытка
ПроверитьСреду85();
База = КаталогВременныхФайлов();
Если Прав(База, 1) <> "\" Тогда
База = База + "\";
КонецЕсли;
Если База <> КаталогДляCA85 Или ТипЗнч(UUIDКомплекта85) <> Тип("Строка") Или СтрДлина(UUIDКомплекта85) <> 36 Тогда
ВызватьИсключение "Нужны фактический собственный клиентский каталог и UUID комплекта";
КонецЕсли;
СвойUUID = Новый УникальныйИдентификатор(UUIDКомплекта85);
Если UUIDКомплекта85 <> НРег(Строка(СвойUUID)) Тогда
ВызватьИсключение "Нужен канонический UUID своего ручного public-CA helper";
КонецЕсли;
СвойКаталог = База + "OwnTLSProfile85-" + UUIDКомплекта85 + "\";
ИмяCA = СвойКаталог + "ca.pem";
ИмяМанифеста = СвойКаталог + "manifest.json";
ПроверитьФайл85(ИмяМанифеста, 16384);
ПроверитьФайл85(ИмяCA, 65536);
Читатель = Новый ЧтениеJSON;
ЗакрытиеНачато85 = Ложь;
Попытка
Читатель.ОткрытьФайл(ИмяМанифеста);
Манифест = ПрочитатьJSON(Читатель);
ЗакрытиеНачато85 = Истина;
Читатель.Закрыть();
Исключение
ПервичнаяОшибка85 = ОписаниеОшибки();
ОшибкаЗакрытия85 = "";
Если Не ЗакрытиеНачато85 Тогда
Попытка
Читатель.Закрыть();
Исключение
ОшибкаЗакрытия85 = ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
Если ОшибкаЗакрытия85 <> "" Тогда
ВызватьИсключение "СТОП: первичная ошибка JSON: " + ПервичнаяОшибка85
+ "; отдельная ошибка закрытия: " + ОшибкаЗакрытия85 + "; состояние читателя неизвестно";
КонецЕсли;
ВызватьИсключение "СТОП: первичная ошибка JSON: " + ПервичнаяОшибка85
+ "; состояние читателя после ошибки неизвестно, повторного Close и retry нет";
КонецПопытки;
Если ТипЗнч(Манифест) <> Тип("Структура") Или Манифест.Количество() <> 5 Тогда
ВызватьИсключение "Нужен полный собственный пятиполный манифест";
КонецЕсли;
Если Не Манифест.Свойство("lesson", Метка) Или ТипЗнч(Метка) <> Тип("Строка") Или Метка <> "OwnTLSProfile85-public-CA-only"
Или Не Манифест.Свойство("identity", UUIDМанифеста) Или ТипЗнч(UUIDМанифеста) <> Тип("Строка") Или UUIDМанифеста <> UUIDКомплекта85
Или Не Манифест.Свойство("ca_certificate_only", ТолькоПубличныйCA) Или ТипЗнч(ТолькоПубличныйCA) <> Тип("Булево") Или ТолькоПубличныйCA <> Истина
Или Не Манифест.Свойство("private_key_written", КлючЗаписан) Или ТипЗнч(КлючЗаписан) <> Тип("Булево") Или КлючЗаписан <> Ложь
Или Не Манифест.Свойство("ca_sha256", ХешCA) Или ТипЗнч(ХешCA) <> Тип("Строка") Или СтрДлина(ХешCA) <> 64 Тогда
ВызватьИсключение "Манифест не описывает только свой публичный CA";
КонецЕсли;
Если ХешФайла85(ИмяCA) <> ХешCA Тогда
ВызватьИсключение "Собственный CA изменился до native factory";
КонецЕсли;
СвоиЦентры = Новый СертификатыУдостоверяющихЦентровФайл(ИмяCA);
Если ТипЗнч(СвоиЦентры) <> Тип("СертификатыУдостоверяющихЦентровФайл") Или СвоиЦентры.ИмяФайла <> ИмяCA Тогда
ВызватьИсключение "Штатный источник потерял точное имя собственного CA";
КонецЕсли;
Профили = Новый Массив;
Профили.Добавить(Новый Структура("Код,Заявок,Профиль,Тип,Режим,CAЕсть", "CSP_NO_CA_STRICT", 2,
Новый ЗащищенноеСоединениеКриптоПро(Неопределено, Неопределено, РежимПроверкиОтзываTLSСертификатаСервера.Строгий),
Тип("ЗащищенноеСоединениеКриптоПро"), РежимПроверкиОтзываTLSСертификатаСервера.Строгий, Ложь));
Профили.Добавить(Новый Структура("Код,Заявок,Профиль,Тип,Режим,CAЕсть", "CSP_OWN_CA_AUTO", 3,
Новый ЗащищенноеСоединениеКриптоПро(Неопределено, СвоиЦентры, РежимПроверкиОтзываTLSСертификатаСервера.Авто),
Тип("ЗащищенноеСоединениеКриптоПро"), РежимПроверкиОтзываTLSСертификатаСервера.Авто, Истина));
Профили.Добавить(Новый Структура("Код,Заявок,Профиль,Тип,Режим,CAЕсть", "CSP_OWN_CA_STRICT", 5,
Новый ЗащищенноеСоединениеКриптоПро(Неопределено, СвоиЦентры, РежимПроверкиОтзываTLSСертификатаСервера.Строгий),
Тип("ЗащищенноеСоединениеКриптоПро"), РежимПроверкиОтзываTLSСертификатаСервера.Строгий, Истина));
Профили.Добавить(Новый Структура("Код,Заявок,Профиль,Тип,Режим,CAЕсть", "OPENSSL_OWN_CA_STRICT", 7,
Новый ЗащищенноеСоединениеOpenSSL(Неопределено, СвоиЦентры, РежимПроверкиОтзываTLSСертификатаСервера.Строгий),
Тип("ЗащищенноеСоединениеOpenSSL"), РежимПроверкиОтзываTLSСертификатаСервера.Строгий, Истина));
Если Профили.Количество() <> 4 Тогда
ВызватьИсключение "Нужны четыре полных собственных случая";
КонецЕсли;
Коды = СтрРазделить("CSP_NO_CA_STRICT,CSP_OWN_CA_AUTO,CSP_OWN_CA_STRICT,OPENSSL_OWN_CA_STRICT", ",");
Количества = Новый Массив;
Количества.Добавить(2);
Количества.Добавить(3);
Количества.Добавить(5);
Количества.Добавить(7);
Всего = 0;
Принято = 0;
Отклонено = 0;
Текст = "Только собственный офлайн-план, НЕ проверка TLS/доверия/подписи:";
Для Индекс = 0 По 3 Цикл
Р = Профили[Индекс];
Если ТипЗнч(Р) <> Тип("Структура") Или Р.Количество() <> 6 Или Р.Код <> Коды[Индекс]
Или ТипЗнч(Р.Заявок) <> Тип("Число") Или Р.Заявок <> Количества[Индекс]
Или Р.Тип <> ?(Индекс = 3, Тип("ЗащищенноеСоединениеOpenSSL"), Тип("ЗащищенноеСоединениеКриптоПро"))
Или Р.Режим <> ?(Индекс = 1, РежимПроверкиОтзываTLSСертификатаСервера.Авто, РежимПроверкиОтзываTLSСертификатаСервера.Строгий)
Или ТипЗнч(Р.CAЕсть) <> Тип("Булево") Или Р.CAЕсть <> (Индекс <> 0) Тогда
ВызватьИсключение "Изменился полный собственный случай";
КонецЕсли;
Было = Паспорт85(Р.Профиль, ИмяCA);
Если Было.Тип <> Р.Тип Или Было.ЭффективныйРежим <> Р.Режим Или Не Было.КлиентНеопределен
Или Было.CAНеопределен = Р.CAЕсть Или Было.ИмяCA <> ?(Р.CAЕсть, ИмяCA, "") Тогда
ВызватьИсключение "Native поля не совпали с конкретными аргументами constructor";
КонецЕсли;
Всего = Всего + Р.Заявок;
Если Было.Принято Тогда
Принято = Принято + Р.Заявок;
Иначе
Отклонено = Отклонено + Р.Заявок;
КонецЕсли;
Текст = Текст + Символы.ПС + Р.Код + ": заявок=" + Строка(Р.Заявок)
+ "; исходный native режим=" + Строка(Было.ИсходныйРежим)
+ "; CA отсутствует=" + Строка(Было.CAНеопределен)
+ "; наш потребитель принял=" + Строка(Было.Принято);
Стало = Паспорт85(Р.Профиль, ИмяCA);
СверитьПаспорта85(Было, Стало);
КонецЦикла;
Если Всего <> 17 Или Принято <> 12 Или Отклонено <> 5 Или Принято + Отклонено <> Всего Тогда
ВызватьИсключение "Фактический офлайн-план не равен 17/12/5";
КонецЕсли;
ПроверитьФайл85(ИмяCA, 65536);
Если ХешФайла85(ИмяCA) <> ХешCA Или СвоиЦентры.ИмяФайла <> ИмяCA Тогда
ВызватьИсключение "Собственный публичный источник изменился после проверки";
КонецЕсли;
ПроверитьСреду85();
Статус85 = Текст + Символы.ПС + "Всего=" + Строка(Всего) + "; принято нашим планом=" + Строка(Принято)
+ "; отклонено=" + Строка(Отклонено)
+ Символы.ПС + "НЕТ HTTP-запроса, handshake, проверки цепочки/отзыва или входа по сертификату."
+ Символы.ПС + "Strict без CA не включает проверку сервера. Auto зависит от conf.cfg. Strict может отказать при недоступном сервере отзыва.";
Остановлен85 = Ложь;
Исключение
Остановлен85 = Истина;
Статус85 = "СТОП. Паспорт не подтвержден. Не снижайте режим и не подменяйте КриптоПро на OpenSSL автоматически.";
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Функция Паспорт85(Профиль, ИмяCA)
ТипПрофиля = ТипЗнч(Профиль);
Если ТипПрофиля = Тип("ЗащищенноеСоединениеКриптоПро") Тогда
КриптоПро = Профиль;
Клиент = КриптоПро.СертификатКлиента;
Центры = КриптоПро.СертификатыУдостоверяющихЦентров;
ИсходныйРежим = КриптоПро.РежимПроверкиОтзываTLSСертификатаСервера;
ИначеЕсли ТипПрофиля = Тип("ЗащищенноеСоединениеOpenSSL") Тогда
OpenSSL = Профиль;
Клиент = OpenSSL.СертификатКлиента;
Центры = OpenSSL.СертификатыУдостоверяющихЦентров;
ИсходныйРежим = OpenSSL.РежимПроверкиОтзываTLSСертификатаСервера;
Иначе
ВызватьИсключение "Нельзя подставлять чужой/неизвестный native профиль";
КонецЕсли;
Если Клиент <> Неопределено Тогда
ВызватьИсключение "Этот собственный потребитель не использует клиентские сертификаты или ключи";
КонецЕсли;
Если ИсходныйРежим = Неопределено Тогда
ЭффективныйРежим = РежимПроверкиОтзываTLSСертификатаСервера.Авто;
Иначе
Если ТипЗнч(ИсходныйРежим) <> Тип("РежимПроверкиОтзываTLSСертификатаСервера") Тогда
ВызватьИсключение "Native режим имеет неожиданный тип";
КонецЕсли;
ЭффективныйРежим = ИсходныйРежим;
КонецЕсли;
CAНеопределен = Центры = Неопределено;
ИмяФактическогоCA = "";
Если Не CAНеопределен Тогда
Если ТипЗнч(Центры) <> Тип("СертификатыУдостоверяющихЦентровФайл") Тогда
ВызватьИсключение "Допустим только источник собственного публичного CA, не хранилище ОС";
КонецЕсли;
ИмяФактическогоCA = Центры.ИмяФайла;
Если ТипЗнч(ИмяФактическогоCA) <> Тип("Строка") Или ИмяФактическогоCA <> ИмяCA Тогда
ВызватьИсключение "Источник указывает не на собственный публичный файл";
КонецЕсли;
КонецЕсли;
ПринятоПотребителем = Не CAНеопределен И ЭффективныйРежим = РежимПроверкиОтзываTLSСертификатаСервера.Строгий;
Возврат Новый Структура("Тип,ИсходныйРежим,ЭффективныйРежим,КлиентНеопределен,CAНеопределен,ИмяCA,Принято",
ТипПрофиля, ИсходныйРежим, ЭффективныйРежим, Клиент = Неопределено, CAНеопределен, ИмяФактическогоCA, ПринятоПотребителем);
КонецФункции
&НаКлиенте
Процедура СверитьПаспорта85(Было, Стало)
Если ТипЗнч(Было) <> Тип("Структура") Или ТипЗнч(Стало) <> Тип("Структура") Или Было.Количество() <> 7 Или Стало.Количество() <> 7 Тогда
ВызватьИсключение "Сверяется полный собственный семипольный паспорт";
КонецЕсли;
Для Каждого Поле Из Было Цикл
Если Не Стало.Свойство(Поле.Ключ, Значение) Тогда
ВызватьИсключение "В свежем паспорте отсутствует поле";
КонецЕсли;
Если ТипЗнч(Поле.Значение) <> ТипЗнч(Значение) Или Поле.Значение <> Значение Тогда
ВызватьИсключение "Native доступный паспорт изменился: СТОП, не откат";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьФайл85(ИмяФайла, Максимум)
Файл85 = Новый Файл(ИмяФайла);
Если Не Файл85.Существует() Или Не Файл85.ЭтоФайл() Тогда
ВызватьИсключение "Нет собственного файла ручной подготовки";
КонецЕсли;
Размер = Файл85.Размер();
Если Размер <= 0 Или Размер > Максимум Тогда
ВызватьИсключение "Свой файл пуст или слишком велик";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ХешФайла85(ИмяФайла)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Данные = Новый ДвоичныеДанные(ИмяФайла);
Хеш = Новый ХешированиеДанных(ХешФункция.SHA256);
Хеш.Добавить(Данные);
Если ТипЗнч(Хеш.ХешСумма) <> Тип("ДвоичныеДанные") Тогда
ВызватьИсключение "SHA256 должен вернуть двоичные данные, не число CRC32";
КонецЕсли;
Возврат НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Хеш.ХешСумма));
#Иначе
ВызватьИсключение "Этот синхронный hash-процесс только для толстого управляемого клиента";
#КонецЕсли
КонецФункции
&НаКлиенте
Процедура ПроверитьСреду85()
ПроверитьСеанс85();
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Система = Новый СистемнаяИнформация;
Если (Система.ТипПлатформы <> ТипПлатформы.Windows_x86 И Система.ТипПлатформы <> ТипПлатформы.Windows_x86_64) Тогда
ВызватьИсключение "Нужен только свой Windows thick-managed клиент 8.5.1.1343";
КонецЕсли;
#Иначе
ВызватьИсключение "Не переносить урок в thin/web/mobile клиент";
#КонецЕсли
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьСеанс85()
ПаспортПрофилей85.ПроверитьСвоюИБ85();
КонецПроцедурыПолный серверный паспорт собственной пустой CF/пользователя/роли/сеанса
ОбщиеМодули → ПаспортПрофилей85 → Модуль целиком
ServerДа/ServerCallДа, обаClientНет, неглобальный/непривилегированный/безcache. Native TLS объекты не получают RPC.
Процедура ПроверитьСвоюИБ85() Экспорт
Если СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnTLSProfileGuard85_932d19b2-0a48-4a03-ab90-dd39aed82704\IB"";" Тогда
ВызватьИсключение "Только новая собственная файловая ИБ по точному учебному пути";
КонецЕсли;
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или ПривилегированныйРежим() Или ТранзакцияАктивна() Тогда
ВызватьИсключение "Версия/своя конфигурация/NoUse/непривилегированный контекст не совпали";
КонецЕсли;
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
Или Метаданные.Константы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0
Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0
Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0
Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0
Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0
Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Или Метаданные.HTTPСервисы.Количество() <> 0
Или Метаданные.WebСервисы.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0
Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.Отчеты.Количество() <> 0
Или Метаданные.Обработки.Количество() <> 0 Тогда
ВызватьИсключение "Только новая пустая прикладная модель без интеграций и заданий";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации()
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Не должно быть расширений базы или сеанса";
КонецЕсли;
Если Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеФормы.Количество() <> 1
Или Метаданные.ОбщиеФормы.Найти("ПаспортTLS85") = Неопределено Или Метаданные.Роли.Количество() <> 1 Тогда
ВызватьИсключение "Нужны только свой общий модуль, пульт и роль";
КонецЕсли;
Модуль = Метаданные.ОбщиеМодули.Найти("ПаспортПрофилей85");
Если Модуль = Неопределено Тогда
ВызватьИсключение "Нет собственного серверного паспорта";
КонецЕсли;
Если Модуль.Глобальный Или Не Модуль.Сервер Или Не Модуль.ВызовСервера
Или Модуль.КлиентОбычноеПриложение Или Модуль.КлиентУправляемоеПриложение
Или Модуль.ВнешнееСоединение Или Модуль.Привилегированный Тогда
ВызватьИсключение "Паспорт должен быть только неглобальным непривилегированным серверным модулем";
КонецЕсли;
Если Модуль.ПовторноеИспользованиеВозвращаемыхЗначений <> Метаданные.СвойстваОбъектов.ПовторноеИспользованиеВозвращаемыхЗначений.НеИспользовать Тогда
ВызватьИсключение "Для неглобального модуля кеширование должно быть отключено";
КонецЕсли;
Если Не ПравоДоступа("Администрирование", Метаданные) Или Не ПравоДоступа("АдминистрированиеДанных", Метаданные)
Или Не ПравоДоступа("АктивныеПользователи", Метаданные) Тогда
ВызватьИсключение "Только свой лабораторный администратор с просмотром соединений";
КонецЕсли;
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователь = Неопределено Или ТипЗнч(Пользователь) <> Тип("ПользовательИнформационнойБазы") Тогда
ВызватьИсключение "Нет настоящего текущего пользователя";
КонецЕсли;
Если Пользователь.Имя <> "TLS85Ученик" Тогда
ВызватьИсключение "Другой пользователь не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если ТипЗнч(Пользователи) <> Тип("Массив") Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Должен быть только свой учебный пользователь";
КонецЕсли;
Свой = Пользователи[0];
Если ТипЗнч(Свой) <> Тип("ПользовательИнформационнойБазы") Или Свой.Имя <> Пользователь.Имя
Или Свой.УникальныйИдентификатор <> Пользователь.УникальныйИдентификатор Тогда
ВызватьИсключение "Свежий список не совпал с собственным пользователем сеанса";
КонецЕсли;
СвояРоль = Метаданные.Роли.Найти("ПаспортTLS85");
Если СвояРоль = Неопределено Или Не Свой.Роли.Содержит(СвояРоль) Тогда
ВызватьИсключение "Нет собственной учебной роли";
КонецЕсли;
ЧислоРолей = 0;
Для Каждого Роль Из Свой.Роли Цикл
Если Роль <> СвояРоль Тогда
ВызватьИсключение "Чужая роль не допускается";
КонецЕсли;
ЧислоРолей = ЧислоРолей + 1;
КонецЦикла;
Если ЧислоРолей <> 1 Или ПолучитьСоединенияИнформационнойБазы().Количество() <> 1 Тогда
ВызватьИсключение "Нужны единственная собственная роль и одно соединение";
КонецЕсли;
КонецПроцедурыПолный штатный запуск своего управляемого пульта
Конфигурация → Модуль управляемого приложения
Настоящий native ПриНачалеРаботыСистемы0, GetForm3526 общей формы; не manualdelivery событий.
Процедура ПриНачалеРаботыСистемы()
СвояФорма = ПолучитьФорму("ОбщаяФорма.ПаспортTLS85");
Если СвояФорма = Неопределено Тогда
ВызватьИсключение "Нет настоящего собственного управляемого пульта";
КонецЕсли;
СвояФорма.Открыть();
КонецПроцедурыПолная будущая ручная подготовка ТОЛЬКО нового публичного CA
Отдельный own_tls85_public_ca.py в собственной новой изолированной Windows VM, НЕ модуль1С
Python3/cryptography48.0.0, вручную. Создаёт только новый ownUUID/ca.pem/manifest; ключтолькоRAM/noOSstore/noTLS. Здесь НЕ запускался.
import argparse
import hashlib
import importlib.metadata
import json
import os
import uuid
from datetime import datetime, timedelta, timezone
from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
def prepare_public_ca(base):
if os.name != "nt" or importlib.metadata.version("cryptography") != "48.0.0":
raise RuntimeError("Only your isolated Windows VM with cryptography48.0.0")
base = Path(base).resolve(strict=True)
if not base.is_dir():
raise ValueError("Use the actual client temp directory shown by your own1C form")
identity = str(uuid.uuid4())
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
now = datetime.now(timezone.utc)
name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "OwnTLSProfile85 CA " + identity)])
ca = (x509.CertificateBuilder().subject_name(name).issuer_name(name)
.public_key(key.public_key()).serial_number(x509.random_serial_number())
.not_valid_before(now - timedelta(minutes=5)).not_valid_after(now + timedelta(days=7))
.add_extension(x509.BasicConstraints(ca=True, path_length=0), critical=True)
.add_extension(x509.KeyUsage(digital_signature=True, content_commitment=False,
key_encipherment=False, data_encipherment=False,
key_agreement=False, key_cert_sign=True, crl_sign=True,
encipher_only=None, decipher_only=None), critical=True)
.sign(key, hashes.SHA256()))
ca.verify_directly_issued_by(ca)
payload = ca.public_bytes(serialization.Encoding.PEM)
reloaded = x509.load_pem_x509_certificate(payload)
reloaded.verify_directly_issued_by(reloaded)
if reloaded.subject != name or reloaded.issuer != name:
raise RuntimeError("Actual public certificate lost the own UUID subject")
if not reloaded.extensions.get_extension_for_class(x509.BasicConstraints).value.ca:
raise RuntimeError("Actual public certificate must be a CA")
if reloaded.fingerprint(hashes.SHA256()) != ca.fingerprint(hashes.SHA256()):
raise RuntimeError("Actual PEM public roundtrip changed the certificate")
folder = base / ("OwnTLSProfile85-" + identity)
folder.mkdir(mode=0o700, exist_ok=False)
manifest = dict(lesson="OwnTLSProfile85-public-CA-only", identity=identity,
ca_sha256=hashlib.sha256(payload).hexdigest(),
ca_certificate_only=True, private_key_written=False)
for filename, content in (("ca.pem", payload),
("manifest.json", json.dumps(manifest, ensure_ascii=True, indent=2).encode("utf-8"))):
with (folder / filename).open("xb") as stream:
stream.write(content)
print("Own public-CA UUID:", identity)
print("Own public-only folder:", folder)
print("No private key/client certificate/OS import/network connection produced.")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--base", required=True)
arguments = parser.parse_args()
prepare_public_ca(arguments.base)
if __name__ == "__main__":
main()
Разбор по шагам
Подготовьте собственную новую CF/VM/роль/пульт и вручную создайте только publicCA новым полным helper.
ExactUUID/путь/размер/полный5field manifest/SHA проверяются ДО native fileCA/TLS constructors.
Создаются3КриптоПро+1OpenSSL. В каждой из4строк проверяются тип/код/количество/реальные3ROполя/предполагаемыйCA и режим.
Native Undefined режима нормализуется в Auto по documentedконтракту, но rawnullable значение не теряется. UndefinedCA независим и означает отсутствие проверки сервера.
Только actualCAownfilename+effectiveStrict принимаются нашим офлайн-потребителем:5+7, не2+3. Все суммы считаются из настоящих строк.
Второй полный7field passport каждого native объекта, свежий SHApublicCA и паспорт собственной ИБ завершают опыт без сетевого обращения.
Как проверить результат
Client certificate реальных объектов должен бытьUndefined: никакого неизвестного client/private source.
CA при наличии только FileCertificationAuthorityCertificates с точным ownUUIDfilename; OS-store/чужой файл/неизвестный тип запрещены.
Readonly свойства не присваиваются; wrongBool/другой enum в constructor третьего аргумента не допускаются.
Проверены полные4строки и17/12/5, не подставленные goldenсуммы. Все7scalar fields паспорта сравниваются по ключам/типам/значениям.
Изменение своегоCA/манифеста/схемы/пользователя/снимка или ошибкаCSP оставляетSTOP без fallback/downgrade.
Положительное ownplan решение не называется verifiedcertificate или успешным TLS.
Ожидаемый результат
При ручном выполнении в своей подготовленной VM создаются4конфигурационных объекта; только наш потребитель планирует12заявок и отклоняет5. Сеть/handshake/CRL/OCSP/цепочка/аутентификация/подпись НЕ выполнялись и НЕ подтверждены.
На что обратить внимание
Строгий отзыв не включает CA-проверку при Undefined источнике. Авто зависит от actualconf.cfg, а не наших предположений.
Нативные type примеры содержат typoКритоПро и другое имя enum: используйте точныйctor365 и ServerTLSCertificateRevocationCheckMode, не копируйте ошибки справки.
Веб-клиент игнорирует первые2OpenSSL аргумента, поэтому он исключен; HashingData.Append здесь синхронный и толькоthick-managed Windows.
Новый публичныйCA/SHA/паспорт не являются prooftrust или гарантией поддержки RSA/GOST/провайдера. Privatekey никогда не сериализуется; стирание памяти не обещано.
Не обещаны атомарность/откат/универсальныйTLSуспех. Все кодовые блоки только написаны/статически проверены, реальные подготовка/сертификаты/файлы/соединения агентом не выполнялись.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.