Глобальный контекст.ПолучитьДвоичныеДанныеИзHexСтроки

Методы · GetBinaryDataFromHexString

Преобразует строку в формате 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. Отдельно демонстрируем варианты, где результат хранится буфером или двоичными данными.

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

Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.

Подготовка

  1. Серверный контекст. Учебная строка abc кодируется в UTF-8 без BOM.

  2. В примере стандартное 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));

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

  1. Получаем три байта abc и показываем строковые Base64 и Hex.

  2. Декодируем строковые представления и проверяем исходный текст.

  3. Буферные и двоичные варианты кодирования содержат символы кодированного представления, а не исходные три байта.

  4. Декодируем каждый вариант; Base64Строка и Base64Значение показывают старые краткие функции для двоичных данных.

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

  1. Base64 равно YWJj, Hex равно 616263.

  2. Все обратные преобразования выводят abc, сравнения представлений дают Истина.

  3. Не передавайте Hex-строку декодировщику Base64: это другой формат и другой смысл байтов.

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

Каждый показанный формат восстанавливает исходные байты при использовании парной функции.

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

  1. Base64 не шифрует и не защищает данные: любой получатель может их восстановить.

  2. Двоичное содержимое Base64Данные — кодированное представление. Для HTTP-заголовка или JSON обычно нужна строковая функция.

  3. При работе с чужим API не заменяйте Base64 на base64url вручную без проверки его контракта.

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

Асинхронно подписать свой PDF и получить реальные результаты проверки в тонком клиенте

Полный модуль собственной формы получает свои PDF-байты с сервера, использует явно подготовленный CurrentUser-ключ, ждёт подпись/запись/чтение и проверяет реальные Array/Certificate-результаты Promise. Ни Promise, ни выходные параметры синхронных overloads не подменяют готовый результат.

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

Полный модуль управляемой формы собственного тонкого Windows-клиента: PDF-операции с Ждать, отдельный полный supporting-серверный модуль для генерации своих байтов. В1С не запускался.

Подготовка

  1. НОВАЯ пустая файловая учебная база УчебнаяАсинхроннаяПодписьPDF85 на8.5.1.1343, совместимость Не использовать. Только свои модуль и форма; без рабочих объектов, расширений, подписок/заданий. Запускать под ОТДЕЛЬНЫМ собственным Windows-пользователем или в отдельном учебном Windows-стенде без рабочих сертификатов. Не серверный кластер под служебной учётной записью.

  2. Для будущей ручной подготовки отключите сеть учебного стенда. Все операции подписи локальны, TSA-массив в коде явно пуст. Команды создания ключа ниже НЕ выполнялись при подготовке справочника; они создают собственный сертификат и закрытый ключ в Личном текущего учебного Windows-пользователя.

  3. Откройте Windows PowerShell в своём отдельном учебном профиле, не от администратора рабочего сервера. В одной и той же консоли вручную выполните последовательно только следующие четыре команды; не закрывайте её между командами. Провайдер Microsoft Enhanced RSA and AES Cryptographic Provider должен существовать и иметь Type24. CNG-провайдер по умолчанию не подставлять вместо него.

  4. Ручная команда 1: $pdfTrainingId = [guid]::NewGuid().ToString("D")

  5. Ручная команда 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)

  6. Ручная команда 3: if (-not $pdfTrainingCert.HasPrivateKey) { throw "Own training private key was not created" }

  7. Ручная команда 4: [pscustomobject]@{TrainingId=$pdfTrainingId;ThumbprintHex=$pdfTrainingCert.Thumbprint;OwnPrivateKey=$pdfTrainingCert.HasPrivateKey;Subject=$pdfTrainingCert.Subject}

  8. Сохраните показанные TrainingId и ThumbprintHex для этой попытки. OwnPrivateKey должен быть True, Subject должен содержать только Syntax Guide PDF Own85 и ваш новый TrainingId. Ключ не экспортируется в PFX и не печатается. Сертификат самоподписанный и не добавляется в доверенные корневые.

  9. Команды и различие legacy CSP/KeySpec=Signature сверены с официальной документацией Microsoft New-SelfSignedCertificate: https://learn.microsoft.com/en-us/powershell/module/pki/new-selfsignedcertificate?view=windowsserver2025-ps. Это документирование будущего учебного опыта, не выполненное создание ключа.

  10. Учебный сертификат и ключ остаются в собственном Windows-профиле после закрытия1С; урок их автоматически не удаляет. Администратор отдельного стенда отвечает за его очистку после обучения. Не переносите опыт в рабочий профиль и не выдавайте закрытие формы за удаление ключа.

  11. Ни PowerShell-команды, ни CryptoAPI/1С, ни AddSignature, ни GUI/сервер/ключи/подпись здесь не запускались. runtimeVerifiedScenarios=0.

  12. Используйте именно тонкий Windows-клиент собственной файловой базы8.5.1.1343. В конфигурации разрешите синхронные вызовы расширений платформы/внешних компонент: сведения, инициализация CryptoAPI и поиск своего сертификата здесь синхронные. Асинхронны PDF-операции; это не обещание полностью неблокирующего криптографического стека.

  13. Основной код теперь вставляется В МОДУЛЬ ФОРМЫ, не в серверный общий модуль. Своя управляемая форма: реквизиты МеткаСертификата85 Строка100, ОтпечатокHex85 Строка40, ПодтверждаюСвойСтенд Булево начально Ложь, Занято Булево начально Ложь, Отчёт Строка0. Поля с теми же путями; Занято не редактировать, Отчёт многострочный ТолькоПросмотр=Да. Команда/кнопка Выполнить, действие Выполнить. Вставьте весь основной модуль, сохранить/F7, открыть свою форму и скопировать фактические TrainingId/ThumbprintHex.

  14. В общий серверный модуль УчебнаяАсинхроннаяПодписьPDF85 вставьте ТОЛЬКО supporting-модуль ниже. Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Он проверяет свою пустую конфигурацию и экспортирует только собственную таблицу в байты. Подписание/ключевой контейнер работают у своего текущего Windows-клиента, не у учётной записи рабочего сервера.

  15. Во время Ждать не закрывайте форму и не меняйте поля источника ключа. Метка/отпечаток копируются в локальные переменные до ожидания, Занято запрещает повторный старт; флаг очищается и при успехе, и при ошибке. Веб-/мобильный клиент и установка расширений не входят в этот опыт.

&НаКлиенте
Функция ПодготовитьСвойМенеджер()
    Информация = СредстваКриптографии.ПолучитьИнформациюМодуляКриптографии("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();
КонецФункции

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

  1. Клиент проверяет точное имя своей конфигурации, версию/Windows и подтверждение учебного стенда. Supporting-серверный модуль отдельно проверяет отсутствие рабочих объектов/расширений ДО экспорта собственных байтов. Серверная защита не скопирована в контекст тонкого клиента.

  2. Свои байты получают полный реальный источник: собственная таблица Книга/3/250/750 → PDF в ПотокВПамяти на сервере → ДвоичныеДанные в свою форму. Клиент открывает собственный поток чтения и ждёт ПрочитатьАсинх до его закрытия.

  3. Полные клиентские функции проверяют настоящий CryptoAPI Type24/SHA256 и собственный CurrentUser-сертификат по20байтам отпечатка и CN с UUID. ВключатьСертификатСубъекта задан явно, TSA-массив пуст. Файл/ключ с неизвестным источником не принимается.

  4. До подписи Ждать ПолучитьОписанияПодписейАсинх возвращает настоящий Массив: требуется0. Promise без Ждать не имеет готового количества; нельзя сравнить сам Promise с пустым массивом.

  5. Собственное описание проверяет реальную первую страницу и поля, получает свой сертификат/имя и прямоугольник. Ждать ДобавитьПодписьАсинх ждёт завершения создания подписи; никакого нового готового ДокументPDF этот результат не обещает.

  6. Новый выходной ПотокВПамяти передаётся ЗаписатьАсинх с ЯВНЫМ ПУСТЫМ паролем и PDF-форматом. Native-контракт запрещает запись подписанного PDF с непустым паролем. Только после Ждать поток закрывается с получением новых байтов.

  7. Подписанные байты читаются новым независимым ДокументPDF через второй awaited ПрочитатьАсинх. ПолучитьОписанияПодписейАсинх у Копия должен вернуть1 ДО индекса0; сверяются реальный тип, имя, свой отпечаток и readonly native-дата.

  8. Ждать ПроверитьПодписьАсинх(Имя, Менеджер) возвращает СертификатКриптографии. В отличие от синхронного overload, третьего выходного параметра нет. Полученный сертификат проверяется по типу/своему отпечатку, не по непустому представлению.

  9. Ждать ПроверитьПодписиАсинх(Менеджер) возвращает Массив сертификатов. В отличие от синхронного overload, второго выходного параметра нет. Проверяем Array/количество1 ДО индекса0 и тот же фактический отпечаток.

  10. Потоки чтения закрываются после завершившегося await; при исключении ошибка закрытия добавляется к исходной ошибке, не превращает её в успех. Выходной поток закрывается с байтами при успехе и отдельно на ошибке. Флаг Занято восстанавливается независимо от итогового статуса.

  11. Строка успеха появляется только ПОСЛЕ всех awaited операций и сравнений. Ошибка любого этапа формирует отчёт об ошибке и повторно выбрасывается. CA/отзыв/правовая сила и доверенная TSA-дата не обещаются.

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

  1. Будущий результат на полностью подготовленном своём тонком клиенте: исходных подписей0, из новых байтов возвращается1; фактическое имя/сертификат/дата совпадают с собственным источником, оба awaited метода проверки возвращают ожидаемые реальные типы. Занято в конце Ложь.

  2. Будущий отрицательный контроль: у ПроверитьПодписьАсинх временно передайте Описание.Имя + "_отсутствует". Promise должен завершиться ошибкой, отчёт успеха не появиться, Занято вернуться в Ложь. Не заменяйте имя другой подписью автоматически.

  3. Будущий контроль результатов: после Ждать проверки всех подписей временно замените ВсеСертификаты на Новый Массив. Проверка количества должна отказать ДО индекса0, несмотря на ранее завершённые операции.

  4. Будущий контроль источника: перед чтением Копия подайте ДанныеPDF вместо ПодписанныеБайты. Массив описаний будет0 и должен быть отвергнут. Верните новые подписанные байты после опыта.

  5. Будущий контроль повторного старта: вызовите собственную кнопку повторно, пока Занято=Истина. Второй запуск должен отказать до открытия потока/использования ключа. Не закрывайте форму для имитации отмены.

  6. runtimeVerifiedScenarios=0: BSL, тонкий клиент, ключи, подпись, PDF-потоки и GUI здесь не запускались. Успех статических проверок не удостоверяет завершение Promise на конкретном провайдере.

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

Все awaited PDF-операции завершены, из новых своих подписанных байтов получены и проверены реальные описание, дата и сертификаты; флаг занятости очищен, доверие/правовая сила не заявлены

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

  1. Это отдельный урок со своим закрытым ключом, не продолжение опыта с публичным DER Syntax Guide Training Only. Публичный DER из предыдущего урока не может заменить этот ключ.

  2. Создание учебного ключа — осознанное будущее изменение ТОЛЬКО своего изолированного профиля. Оно не выполнялось инструментами этого чата. NonExportable не означает, что ключ исчезнет после опыта или что он доверенный.

  3. Чтение описания/даты — не эквивалент ПроверитьПодпись, проверки CA/отзыва или доверенной TSA-метки. Никакого правового вывода по self-signed образцу не делается.

  4. Текст штампа — визуальное представление, не сама криптографическая подпись. Не обещается, что все PDF-просмотрщики доверяют self-signed сертификату или одинаково показывают штамп.

  5. Ключ принадлежит текущему учебному Windows-клиенту. Сервер создаёт только свои PDF-байты и ключ не использует; ошибка источника не разрешает переключиться на чужой профиль или область ДанныеКомпьютера.

  6. Новый ОписаниеПодписиPDF — настройки до подписи, не источник фактической readonly-даты. Её читаем только из awaited описаний новых подписанных PDF-байтов.

  7. Четыре PDF Async-метода доступны клиенту, не серверу. Синхронные методы подписания/чтения/проверки не вставлены вместо Async в основном модуле формы.

  8. Promise надо дождаться внутри Асинх Процедура/Функция. ПолучитьОписанияПодписейАсинх возвращает Array после ожидания, ПроверитьПодписьАсинх — Certificate, ПроверитьПодписиАсинх — Array; это разные контракты.

  9. Асинхронное ожидание — не фоновая серверная работа и не гарантия, что синхронная инициализация криптографии не блокирует интерфейс. Разрешённый синхронный режим указан явно; браузерные расширения не устанавливаются.

  10. Пустой пароль записи обязателен для этого подписанного образца. Непустой пароль должен вызвать native-ошибку; её нельзя скрыть и вернуть старые байты как новый результат.

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

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

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

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

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