Преобразует строку в формате Base 16 (Hex) в двоичные данные.
Синтаксис
ПолучитьДвоичныеДанныеИзHexСтроки(<Строка>)Полное описание, параметры и ограничения
Глобальный контекст.ПолучитьДвоичныеДанныеИзHexСтроки (Global context.GetBinaryDataFromHexString)
Глобальный контекст (Global context)
ПолучитьДвоичныеДанныеИзHexСтроки (GetBinaryDataFromHexString)
Доступен, начиная с версии 8.3.10.
Синтаксис:
ПолучитьДвоичныеДанныеИзHexСтроки(<Строка>)
Параметры:
<Строка> (обязательный)
Тип: Строка.
Строка в формате Base 16 (Hex).
Возвращаемое значение:
Тип: ДвоичныеДанные.
Описание:
Преобразует строку в формате Base 16 (Hex) в двоичные данные.
Доступность:
Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.
Использование в версии:
Доступен, начиная с версии 8.3.10.
Методическая информация
Практические примеры
Передать байты как Base64 или показать их в Hex
Для JSON удобно строковое Base64, для диагностики — Hex. Отдельно демонстрируем варианты, где результат хранится буфером или двоичными данными.
Где и как запускать
Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.
Подготовка
Серверный контекст. Учебная строка abc кодируется в UTF-8 без BOM.
В примере стандартное Base64, не вариант base64url для URL или токенов.
Данные = ПолучитьДвоичныеДанныеИзСтроки("abc", КодировкаТекста.UTF8, Ложь);
Буфер = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(Данные);
Base64Текст = ПолучитьBase64СтрокуИзДвоичныхДанных(Данные);
HexТекст = ПолучитьHexСтрокуИзБуфераДвоичныхДанных(Буфер);
Сообщить(Base64Текст);
Сообщить(HexТекст);
ИзBase64 = ПолучитьДвоичныеДанныеИзBase64Строки(Base64Текст);
ИзHex = ПолучитьБуферДвоичныхДанныхИзHexСтроки(HexТекст);
Сообщить(ПолучитьСтрокуИзДвоичныхДанных(ИзBase64, КодировкаТекста.UTF8));
Сообщить(ПолучитьСтрокуИзБуфераДвоичныхДанных(ИзHex, КодировкаТекста.UTF8));
Base64Буфер = ПолучитьBase64БуферДвоичныхДанныхИзБуфераДвоичныхДанных(Буфер);
ВосстановленныйБуфер = ПолучитьБуферДвоичныхДанныхИзBase64БуфераДвоичныхДанных(Base64Буфер);
Base64Данные = ПолучитьBase64ДвоичныеДанныеИзДвоичныхДанных(Данные);
ВосстановленныеДанные = ПолучитьДвоичныеДанныеИзBase64ДвоичныхДанных(Base64Данные);
HexБуфер = ПолучитьHexБуферДвоичныхДанныхИзБуфераДвоичныхДанных(Буфер);
БуферПослеHex = ПолучитьБуферДвоичныхДанныхИзHexБуфераДвоичныхДанных(HexБуфер);
HexДанные = ПолучитьHexДвоичныеДанныеИзДвоичныхДанных(Данные);
ДанныеПослеHex = ПолучитьДвоичныеДанныеИзHexДвоичныхДанных(HexДанные);
Сообщить(ПолучитьBase64СтрокуИзБуфераДвоичныхДанных(ВосстановленныйБуфер) = Base64Текст);
Сообщить(ПолучитьHexСтрокуИзДвоичныхДанных(ВосстановленныеДанные) = HexТекст);
Сообщить(ПолучитьСтрокуИзБуфераДвоичныхДанных(БуферПослеHex, КодировкаТекста.UTF8));
Сообщить(ПолучитьСтрокуИзДвоичныхДанных(ДанныеПослеHex, КодировкаТекста.UTF8));
Сообщить(ПолучитьСтрокуИзДвоичныхДанных(ПолучитьДвоичныеДанныеИзHexСтроки(HexТекст), КодировкаТекста.UTF8));
Сообщить(ПолучитьСтрокуИзБуфераДвоичныхДанных(ПолучитьБуферДвоичныхДанныхИзBase64Строки(Base64Текст), КодировкаТекста.UTF8));
Сообщить(Base64Строка(Данные) = Base64Текст);
Сообщить(ПолучитьСтрокуИзДвоичныхДанных(Base64Значение(Base64Текст), КодировкаТекста.UTF8));Разбор по шагам
Получаем три байта abc и показываем строковые Base64 и Hex.
Декодируем строковые представления и проверяем исходный текст.
Буферные и двоичные варианты кодирования содержат символы кодированного представления, а не исходные три байта.
Декодируем каждый вариант; Base64Строка и Base64Значение показывают старые краткие функции для двоичных данных.
Как проверить результат
Base64 равно YWJj, Hex равно 616263.
Все обратные преобразования выводят abc, сравнения представлений дают Истина.
Не передавайте Hex-строку декодировщику Base64: это другой формат и другой смысл байтов.
Ожидаемый результат
Каждый показанный формат восстанавливает исходные байты при использовании парной функции.
На что обратить внимание
Base64 не шифрует и не защищает данные: любой получатель может их восстановить.
Двоичное содержимое Base64Данные — кодированное представление. Для HTTP-заголовка или JSON обычно нужна строковая функция.
При работе с чужим API не заменяйте Base64 на base64url вручную без проверки его контракта.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Асинхронно подписать свой PDF и получить реальные результаты проверки в тонком клиенте
Полный модуль собственной формы получает свои PDF-байты с сервера, использует явно подготовленный CurrentUser-ключ, ждёт подпись/запись/чтение и проверяет реальные Array/Certificate-результаты Promise. Ни Promise, ни выходные параметры синхронных overloads не подменяют готовый результат.
Где и как запускать
Полный модуль управляемой формы собственного тонкого Windows-клиента: PDF-операции с Ждать, отдельный полный supporting-серверный модуль для генерации своих байтов. В1С не запускался.
Подготовка
НОВАЯ пустая файловая учебная база УчебнаяАсинхроннаяПодписьPDF85 на8.5.1.1343, совместимость Не использовать. Только свои модуль и форма; без рабочих объектов, расширений, подписок/заданий. Запускать под ОТДЕЛЬНЫМ собственным Windows-пользователем или в отдельном учебном Windows-стенде без рабочих сертификатов. Не серверный кластер под служебной учётной записью.
Для будущей ручной подготовки отключите сеть учебного стенда. Все операции подписи локальны, TSA-массив в коде явно пуст. Команды создания ключа ниже НЕ выполнялись при подготовке справочника; они создают собственный сертификат и закрытый ключ в Личном текущего учебного Windows-пользователя.
Откройте Windows PowerShell в своём отдельном учебном профиле, не от администратора рабочего сервера. В одной и той же консоли вручную выполните последовательно только следующие четыре команды; не закрывайте её между командами. Провайдер Microsoft Enhanced RSA and AES Cryptographic Provider должен существовать и иметь Type24. CNG-провайдер по умолчанию не подставлять вместо него.
Ручная команда 1: $pdfTrainingId = [guid]::NewGuid().ToString("D")
Ручная команда 2: $pdfTrainingCert = New-SelfSignedCertificate -Type Custom -Subject ("CN=Syntax Guide PDF Own85 " + $pdfTrainingId) -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -KeySpec Signature -KeyAlgorithm RSA -KeyLength 2048 -KeyUsage DigitalSignature -HashAlgorithm SHA256 -KeyExportPolicy NonExportable -CertStoreLocation "Cert:\CurrentUser\My" -NotAfter (Get-Date).AddMonths(1)
Ручная команда 3: if (-not $pdfTrainingCert.HasPrivateKey) { throw "Own training private key was not created" }
Ручная команда 4: [pscustomobject]@{TrainingId=$pdfTrainingId;ThumbprintHex=$pdfTrainingCert.Thumbprint;OwnPrivateKey=$pdfTrainingCert.HasPrivateKey;Subject=$pdfTrainingCert.Subject}
Сохраните показанные TrainingId и ThumbprintHex для этой попытки. OwnPrivateKey должен быть True, Subject должен содержать только Syntax Guide PDF Own85 и ваш новый TrainingId. Ключ не экспортируется в PFX и не печатается. Сертификат самоподписанный и не добавляется в доверенные корневые.
Команды и различие legacy CSP/KeySpec=Signature сверены с официальной документацией Microsoft New-SelfSignedCertificate: https://learn.microsoft.com/en-us/powershell/module/pki/new-selfsignedcertificate?view=windowsserver2025-ps. Это документирование будущего учебного опыта, не выполненное создание ключа.
Учебный сертификат и ключ остаются в собственном Windows-профиле после закрытия1С; урок их автоматически не удаляет. Администратор отдельного стенда отвечает за его очистку после обучения. Не переносите опыт в рабочий профиль и не выдавайте закрытие формы за удаление ключа.
Ни PowerShell-команды, ни CryptoAPI/1С, ни AddSignature, ни GUI/сервер/ключи/подпись здесь не запускались. runtimeVerifiedScenarios=0.
Используйте именно тонкий Windows-клиент собственной файловой базы8.5.1.1343. В конфигурации разрешите синхронные вызовы расширений платформы/внешних компонент: сведения, инициализация CryptoAPI и поиск своего сертификата здесь синхронные. Асинхронны PDF-операции; это не обещание полностью неблокирующего криптографического стека.
Основной код теперь вставляется В МОДУЛЬ ФОРМЫ, не в серверный общий модуль. Своя управляемая форма: реквизиты МеткаСертификата85 Строка100, ОтпечатокHex85 Строка40, ПодтверждаюСвойСтенд Булево начально Ложь, Занято Булево начально Ложь, Отчёт Строка0. Поля с теми же путями; Занято не редактировать, Отчёт многострочный ТолькоПросмотр=Да. Команда/кнопка Выполнить, действие Выполнить. Вставьте весь основной модуль, сохранить/F7, открыть свою форму и скопировать фактические TrainingId/ThumbprintHex.
В общий серверный модуль УчебнаяАсинхроннаяПодписьPDF85 вставьте ТОЛЬКО supporting-модуль ниже. Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Он проверяет свою пустую конфигурацию и экспортирует только собственную таблицу в байты. Подписание/ключевой контейнер работают у своего текущего Windows-клиента, не у учётной записи рабочего сервера.
Во время Ждать не закрывайте форму и не меняйте поля источника ключа. Метка/отпечаток копируются в локальные переменные до ожидания, Занято запрещает повторный старт; флаг очищается и при успехе, и при ошибке. Веб-/мобильный клиент и установка расширений не входят в этот опыт.
&НаКлиенте
Функция ПодготовитьСвойМенеджер()
Информация = СредстваКриптографии.ПолучитьИнформациюМодуляКриптографии("Microsoft Enhanced RSA and AES Cryptographic Provider", "", 24);
Если Информация = Неопределено Или ТипЗнч(Информация) <> Тип("ИнформацияМодуляКриптографии") Тогда
ВызватьИсключение "На своём Windows-стенде не найден требуемый провайдер";
КонецЕсли;
Если Информация.ТипМодуляКриптографии <> 24 Тогда
ВызватьИсключение "Нужен фактический CryptoAPI-провайдер типа24";
КонецЕсли;
АлгоритмSHA256 = "";
Для Каждого Алгоритм Из Информация.АлгоритмыХеширования Цикл
Если НРег(Алгоритм) = "sha256" Или НРег(Алгоритм) = "sha-256" Или Алгоритм = "2.16.840.1.101.3.4.2.1" Тогда
АлгоритмSHA256 = Алгоритм;
КонецЕсли;
КонецЦикла;
Если АлгоритмSHA256 = "" Тогда
ВызватьИсключение "Свой провайдер не подтвердил SHA256; другое имя не подставлять наугад";
КонецЕсли;
Менеджер = Новый МенеджерКриптографии("Microsoft Enhanced RSA and AES Cryptographic Provider", "", 24, ИспользованиеИнтерактивногоРежимаКриптографии.НеИспользовать);
Менеджер.АлгоритмХеширования = АлгоритмSHA256;
Менеджер.ВключениеСертификатовВПодпись = РежимВключенияСертификатовКриптографии.ВключатьСертификатСубъекта;
Менеджер.АдресаСерверовМетокВремени = Новый Массив;
Если Менеджер.АдресаСерверовМетокВремени.Количество() <> 0 Тогда
ВызватьИсключение "Урок не должен обращаться к внешнему серверу меток времени";
КонецЕсли;
Возврат Менеджер;
КонецФункции
&НаКлиенте
Функция НайтиСвойСертификат(Менеджер, Метка, ОтпечатокHex)
Если СтрДлина(ОтпечатокHex) <> 40 Тогда
ВызватьИсключение "Скопируйте весь SHA1-отпечаток из собственного PowerShell-опыта без пробелов";
КонецЕсли;
Отпечаток = ПолучитьДвоичныеДанныеИзHexСтроки(ОтпечатокHex);
Если Отпечаток.Размер() <> 20 Тогда
ВызватьИсключение "SHA1-отпечаток должен содержать20байт";
КонецЕсли;
Хранилище = Менеджер.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты,
РасположениеХранилищаСертификатовКриптографии.ДанныеПользователяОС);
Сертификат = Хранилище.НайтиПоОтпечатку(Отпечаток);
Если Сертификат = Неопределено Или ТипЗнч(Сертификат) <> Тип("СертификатКриптографии") Тогда
ВызватьИсключение "В собственном текущем Windows-профиле не найден именно созданный учебный сертификат";
КонецЕсли;
Если Base64Строка(Сертификат.Отпечаток) <> Base64Строка(Отпечаток) Тогда
ВызватьИсключение "Найден не свой точный отпечаток";
КонецЕсли;
CN = Неопределено;
Если Не Сертификат.Субъект.Свойство("CN", CN) Тогда
ВызватьИсключение "Нет собственного CN учебного сертификата";
КонецЕсли;
Если CN <> "Syntax Guide PDF Own85 " + Метка Тогда
ВызватьИсключение "CN должен совпасть с собственной уникальной меткой подготовки ключа";
КонецЕсли;
Возврат Сертификат;
КонецФункции
&НаКлиенте
Функция ПодготовитьСвоюПодпись(Документ, Сертификат, Метка)
Если Документ.КоличествоСтраниц() = 0 Тогда
ВызватьИсключение "Нужен собственный PDF с реальной первой страницей";
КонецЕсли;
Страница = Документ.Страницы.Получить(0);
Если Страница.Ориентация <> 0 Или Страница.Ширина - Страница.ПолеСлева - Страница.ПолеСправа < 80
Или Страница.Высота - Страница.ПолеСверху - Страница.ПолеСнизу < 60 Тогда
ВызватьИсключение "Собственная неповёрнутая страница должна вместить штамп10/45/70/15мм";
КонецЕсли;
Описание = Новый ОписаниеПодписиPDF;
Описание.Имя = "СвояПодпись85_" + Метка;
Описание.Сертификат = Сертификат;
Описание.ТипПодписи = ТипПодписиPDF.Утверждающая;
Описание.БлокировкаДокумента = Ложь;
Описание.НомерСтраницы = 1;
Описание.Лево = 10;
Описание.Верх = 45;
Описание.Ширина = 70;
Описание.Высота = 15;
Возврат Описание;
КонецФункции
&НаКлиенте
Асинх Функция ПрочитатьСвоиБайтыАсинх(Данные)
Поток = Данные.ОткрытьПотокДляЧтения();
Попытка
Документ = Новый ДокументPDF;
Ждать Документ.ПрочитатьАсинх(Поток, "");
Исключение
ОшибкаОперации = ОписаниеОшибки();
Попытка
Поток.Закрыть();
Исключение
ОшибкаОперации = ОшибкаОперации + " Закрытие своего входного потока: " + ОписаниеОшибки();
КонецПопытки;
ВызватьИсключение ОшибкаОперации;
КонецПопытки;
Поток.Закрыть();
Возврат Документ;
КонецФункции
&НаКлиенте
Асинх Функция ЗаписатьСвоиБайтыАсинх(Документ)
Поток = Новый ПотокВПамяти;
Попытка
Ждать Документ.ЗаписатьАсинх(Поток, "", ТипФайлаДокументаPDF.PDF);
Данные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Исключение
ОшибкаОперации = ОписаниеОшибки();
Попытка
Поток.Закрыть();
Исключение
ОшибкаОперации = ОшибкаОперации + " Закрытие своего выходного потока: " + ОписаниеОшибки();
КонецПопытки;
ВызватьИсключение ОшибкаОперации;
КонецПопытки;
Возврат Данные;
КонецФункции
&НаКлиенте
Процедура ПроверитьСвойОтветСертификата(Результат, Сертификат)
Если ТипЗнч(Результат) <> Тип("СертификатКриптографии")
Или Base64Строка(Результат.Отпечаток) <> Base64Строка(Сертификат.Отпечаток) Тогда
ВызватьИсключение "Await должен вернуть включённый сертификат собственного субъекта";
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСвоиБайтыНаСервере()
Возврат УчебнаяАсинхроннаяПодписьPDF85.ПолучитьСвоиБайтыPDF();
КонецФункции
&НаКлиенте
Асинх Процедура Выполнить(Команда)
Если Занято Тогда
ВызватьИсключение "Дождитесь завершения своей текущей операции";
КонецЕсли;
Система = Новый СистемнаяИнформация;
Если (Система.ТипПлатформы <> ТипПлатформы.Windows_x86 И Система.ТипПлатформы <> ТипПлатформы.Windows_x86_64) Тогда
ВызватьИсключение "Нужен собственный тонкий Windows-клиент8.5.1.1343";
КонецЕсли;
Если Не ПодтверждаюСвойСтенд Тогда
ВызватьИсключение "Подтвердите только использование своего отдельного ключевого стенда";
КонецЕсли;
Метка = МеткаСертификата85;
ОтпечатокHex = ОтпечатокHex85;
UUID = Новый УникальныйИдентификатор(Метка);
Если Строка(UUID) <> Метка Тогда
ВызватьИсключение "Скопируйте фактическую метку собственного учебного сертификата";
КонецЕсли;
Занято = Истина;
Отчёт = "Собственная операция ещё не завершена";
Попытка
ДанныеPDF = ПолучитьСвоиБайтыНаСервере();
Документ = Ждать ПрочитатьСвоиБайтыАсинх(ДанныеPDF);
Менеджер = ПодготовитьСвойМенеджер();
Сертификат = НайтиСвойСертификат(Менеджер, Метка, ОтпечатокHex);
ДоПодписания = Ждать Документ.ПолучитьОписанияПодписейАсинх(Менеджер);
Если ТипЗнч(ДоПодписания) <> Тип("Массив") Или ДоПодписания.Количество() <> 0 Тогда
ВызватьИсключение "Собственный исходный PDF не должен содержать прежних подписей";
КонецЕсли;
Описание = ПодготовитьСвоюПодпись(Документ, Сертификат, Метка);
Штамп = Новый ТабличныйДокумент;
Штамп.Область(1, 1).Текст = "УЧЕБНЫЙ АСИНХРОННЫЙ САМОПОДПИСАННЫЙ ОБРАЗЕЦ";
Ждать Документ.ДобавитьПодписьАсинх(Менеджер, Описание, Штамп, Истина);
ПодписанныеБайты = Ждать ЗаписатьСвоиБайтыАсинх(Документ);
Если ПодписанныеБайты.Размер() = 0 Тогда
ВызватьИсключение "Не получены собственные подписанные PDF-байты";
КонецЕсли;
Копия = Ждать ПрочитатьСвоиБайтыАсинх(ПодписанныеБайты);
Описания = Ждать Копия.ПолучитьОписанияПодписейАсинх(Менеджер);
Если ТипЗнч(Описания) <> Тип("Массив") Или Описания.Количество() <> 1 Тогда
ВызватьИсключение "Из новых PDF-байтов должно вернуться одно описание собственной подписи";
КонецЕсли;
Подпись = Описания[0];
Если ТипЗнч(Подпись) <> Тип("ОписаниеПодписиPDF") Или Подпись.Имя <> Описание.Имя Тогда
ВызватьИсключение "Await описаний не вернул именно собственную добавленную подпись";
КонецЕсли;
ПроверитьСвойОтветСертификата(Подпись.Сертификат, Сертификат);
ДатаПодписи = Подпись.Дата;
Если ТипЗнч(ДатаПодписи) <> Тип("Дата") Или ДатаПодписи = Дата(1, 1, 1) Тогда
ВызватьИсключение "В своём описании нет заполненной native-даты; подстановка текущей даты запрещена";
КонецЕсли;
ПроверенныйСертификат = Ждать Копия.ПроверитьПодписьАсинх(Описание.Имя, Менеджер);
ПроверитьСвойОтветСертификата(ПроверенныйСертификат, Сертификат);
ВсеСертификаты = Ждать Копия.ПроверитьПодписиАсинх(Менеджер);
Если ТипЗнч(ВсеСертификаты) <> Тип("Массив") Или ВсеСертификаты.Количество() <> 1 Тогда
ВызватьИсключение "Await всех подписей должен вернуть один включённый собственный сертификат";
КонецЕсли;
ПроверитьСвойОтветСертификата(ВсеСертификаты[0], Сертификат);
Отчёт = "Все await завершены: собственная подпись и сертификаты проверены. Native-дата: " + Строка(ДатаПодписи)
+ ". Это не доверенная TSA-дата и не правовая оценка";
Исключение
Занято = Ложь;
Отчёт = "Свой асинхронный опыт не завершён: " + ОписаниеОшибки();
ВызватьИсключение Отчёт;
КонецПопытки;
Занято = Ложь;
КонецПроцедурыУчебнаяАсинхроннаяПодписьPDF85
Конфигуратор → Общие модули → УчебнаяАсинхроннаяПодписьPDF85 → Модуль
Полный серверный общий модуль: защита своего пустого стенда и создание только своих unsigned PDF-байтов в памяти. Не выполнялся.
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция СоздатьСобственныеБайтыPDF()
Таблица = Новый ТабличныйДокумент;
Таблица.КодЯзыка = "ru";
Таблица.Область(1, 1).Текст = "СОБСТВЕННЫЙ УЧЕБНЫЙ ОБРАЗЕЦ";
Таблица.Область(2, 1).Текст = "Книга";
Таблица.Область(2, 2).Текст = "3";
Таблица.Область(2, 3).Текст = "250";
Таблица.Область(2, 4).Текст = "750";
Таблица.Область(1, 1, 2, 4).ЦветФона = Новый Цвет(255, 255, 210);
Таблица.Область(, 1, , 1).ШиринаКолонки = 45;
Поток = Новый ПотокВПамяти;
Попытка
Таблица.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);
Данные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Исключение
Поток.Закрыть();
ВызватьИсключение;
КонецПопытки;
Возврат Данные;
КонецФункции
Функция ПолучитьСвоиБайтыPDF() Экспорт
ПроверитьСвойПустойСтенд();
Возврат СоздатьСобственныеБайтыPDF();
КонецФункцииРазбор по шагам
Клиент проверяет точное имя своей конфигурации, версию/Windows и подтверждение учебного стенда. Supporting-серверный модуль отдельно проверяет отсутствие рабочих объектов/расширений ДО экспорта собственных байтов. Серверная защита не скопирована в контекст тонкого клиента.
Свои байты получают полный реальный источник: собственная таблица Книга/3/250/750 → PDF в ПотокВПамяти на сервере → ДвоичныеДанные в свою форму. Клиент открывает собственный поток чтения и ждёт ПрочитатьАсинх до его закрытия.
Полные клиентские функции проверяют настоящий CryptoAPI Type24/SHA256 и собственный CurrentUser-сертификат по20байтам отпечатка и CN с UUID. ВключатьСертификатСубъекта задан явно, TSA-массив пуст. Файл/ключ с неизвестным источником не принимается.
До подписи Ждать ПолучитьОписанияПодписейАсинх возвращает настоящий Массив: требуется0. Promise без Ждать не имеет готового количества; нельзя сравнить сам Promise с пустым массивом.
Собственное описание проверяет реальную первую страницу и поля, получает свой сертификат/имя и прямоугольник. Ждать ДобавитьПодписьАсинх ждёт завершения создания подписи; никакого нового готового ДокументPDF этот результат не обещает.
Новый выходной ПотокВПамяти передаётся ЗаписатьАсинх с ЯВНЫМ ПУСТЫМ паролем и PDF-форматом. Native-контракт запрещает запись подписанного PDF с непустым паролем. Только после Ждать поток закрывается с получением новых байтов.
Подписанные байты читаются новым независимым ДокументPDF через второй awaited ПрочитатьАсинх. ПолучитьОписанияПодписейАсинх у Копия должен вернуть1 ДО индекса0; сверяются реальный тип, имя, свой отпечаток и readonly native-дата.
Ждать ПроверитьПодписьАсинх(Имя, Менеджер) возвращает СертификатКриптографии. В отличие от синхронного overload, третьего выходного параметра нет. Полученный сертификат проверяется по типу/своему отпечатку, не по непустому представлению.
Ждать ПроверитьПодписиАсинх(Менеджер) возвращает Массив сертификатов. В отличие от синхронного overload, второго выходного параметра нет. Проверяем Array/количество1 ДО индекса0 и тот же фактический отпечаток.
Потоки чтения закрываются после завершившегося await; при исключении ошибка закрытия добавляется к исходной ошибке, не превращает её в успех. Выходной поток закрывается с байтами при успехе и отдельно на ошибке. Флаг Занято восстанавливается независимо от итогового статуса.
Строка успеха появляется только ПОСЛЕ всех awaited операций и сравнений. Ошибка любого этапа формирует отчёт об ошибке и повторно выбрасывается. CA/отзыв/правовая сила и доверенная TSA-дата не обещаются.
Как проверить результат
Будущий результат на полностью подготовленном своём тонком клиенте: исходных подписей0, из новых байтов возвращается1; фактическое имя/сертификат/дата совпадают с собственным источником, оба awaited метода проверки возвращают ожидаемые реальные типы. Занято в конце Ложь.
Будущий отрицательный контроль: у ПроверитьПодписьАсинх временно передайте Описание.Имя + "_отсутствует". Promise должен завершиться ошибкой, отчёт успеха не появиться, Занято вернуться в Ложь. Не заменяйте имя другой подписью автоматически.
Будущий контроль результатов: после Ждать проверки всех подписей временно замените ВсеСертификаты на Новый Массив. Проверка количества должна отказать ДО индекса0, несмотря на ранее завершённые операции.
Будущий контроль источника: перед чтением Копия подайте ДанныеPDF вместо ПодписанныеБайты. Массив описаний будет0 и должен быть отвергнут. Верните новые подписанные байты после опыта.
Будущий контроль повторного старта: вызовите собственную кнопку повторно, пока Занято=Истина. Второй запуск должен отказать до открытия потока/использования ключа. Не закрывайте форму для имитации отмены.
runtimeVerifiedScenarios=0: BSL, тонкий клиент, ключи, подпись, PDF-потоки и GUI здесь не запускались. Успех статических проверок не удостоверяет завершение Promise на конкретном провайдере.
Ожидаемый результат
Все awaited PDF-операции завершены, из новых своих подписанных байтов получены и проверены реальные описание, дата и сертификаты; флаг занятости очищен, доверие/правовая сила не заявлены
На что обратить внимание
Это отдельный урок со своим закрытым ключом, не продолжение опыта с публичным DER Syntax Guide Training Only. Публичный DER из предыдущего урока не может заменить этот ключ.
Создание учебного ключа — осознанное будущее изменение ТОЛЬКО своего изолированного профиля. Оно не выполнялось инструментами этого чата. NonExportable не означает, что ключ исчезнет после опыта или что он доверенный.
Чтение описания/даты — не эквивалент ПроверитьПодпись, проверки CA/отзыва или доверенной TSA-метки. Никакого правового вывода по self-signed образцу не делается.
Текст штампа — визуальное представление, не сама криптографическая подпись. Не обещается, что все PDF-просмотрщики доверяют self-signed сертификату или одинаково показывают штамп.
Ключ принадлежит текущему учебному Windows-клиенту. Сервер создаёт только свои PDF-байты и ключ не использует; ошибка источника не разрешает переключиться на чужой профиль или область ДанныеКомпьютера.
Новый ОписаниеПодписиPDF — настройки до подписи, не источник фактической readonly-даты. Её читаем только из awaited описаний новых подписанных PDF-байтов.
Четыре PDF Async-метода доступны клиенту, не серверу. Синхронные методы подписания/чтения/проверки не вставлены вместо Async в основном модуле формы.
Promise надо дождаться внутри Асинх Процедура/Функция. ПолучитьОписанияПодписейАсинх возвращает Array после ожидания, ПроверитьПодписьАсинх — Certificate, ПроверитьПодписиАсинх — Array; это разные контракты.
Асинхронное ожидание — не фоновая серверная работа и не гарантия, что синхронная инициализация криптографии не блокирует интерфейс. Разрешённый синхронный режим указан явно; браузерные расширения не устанавливаются.
Пустой пароль записи обязателен для этого подписанного образца. Непустой пароль должен вызвать native-ошибку; её нельзя скрыть и вернуть старые байты как новый результат.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.