Глава 23. Механизм криптографии
страницаГлава 23. Механизм криптографии
23.1. Общая информация
При использовании системы «1С:Предприятие» в системах автоматизации может быть необходимо обеспечить проверку, что тот или иной документ, хранящийся в системе, не был изменен (например, к объекту базы данных Договор прикладывается документ, содержащий текст самого договора). Также может возникать необходимость обеспечить передачу какой-либо подписанной информации или организовать утверждение какого-либо документа в рамках системы. Возможны ситуации, когда требуется обеспечить передачу информации по открытым каналам так, чтобы с ней было невозможно ознакомиться, перехватив передачу (зашифровать данные).
Для подобных ситуаций в системе «1С:Предприятие» реализован механизм криптографии, базирующийся на асимметричном шифровании (используется пара ключей ‑ открытый и закрытый).
Внимание! Механизм криптографии «1С:Предприятия» не содержит реализации собственно алгоритмов криптографии. Он обеспечивает набор объектов, позволяющих взаимодействовать с внешними модулями криптографии сторонних производителей.
Открытый ключ предназначен для передачи по открытым каналам. Закрытый ключ для распространения не предназначен и должен быть максимально защищен (секретный ключ).
Чтобы зашифровать данные, необходимо знать открытые ключи получателей. Для расшифровки нужно иметь закрытый ключ, являющийся парой для открытого, указанного при осуществлении шифрования. Для генерации цифровой подписи нужен закрытый ключ, а для проверки подписи ‑ открытый ключ подписавшего (чаще всего открытый ключ включен в саму подпись).
При шифровании данных, кроме асимметричного шифрования, используется симметричное шифрование. Симметричное шифрование ‑ это способ шифрования, когда для шифрования и расшифровки используется один и тот же ключ. Особенности применения симметричного шифрования будут описаны далее в разделе.
При работе с механизмом криптографии следует учитывать, где выполняется эта работа. Причина заключается в том, что схемы работы с криптографией на стороне клиентского приложения и на стороне сервера существенно отличаются. На стороне сервера используются так называемые синхронные методы работы с криптографией, в то время как на стороне клиентского приложения используются асинхронные методы работы.
Для работы в веб-клиенте должно быть установлено расширение работы с криптографией. Особенностью веб-клиента является выполнение запроса разрешения пользователя на выполнение некоторых операций: доступ к файловой системе и к закрытому ключу.
23.2. Основные понятия
При описании механизмов будут использоваться некоторые термины.
Электронная цифровая подпись (далее ‑ ЭЦП) ‑ последовательность данных, полученная в результате криптографического преобразования исходной информации с использованием закрытого ключа ЭЦП. Позволяет подтверждать целостность и неизменность этой информации, а также ее авторство при условии использования открытого ключа ЭЦП и его сертификата. ЭЦП может быть присоединенная (прикрепленная) и отсоединенная (открепленная). В случае присоединенной ЭЦП и подпись и подписанные данные располагаются в одном файле. В случае отсоединенной ЭЦП файл данных остается неизменным, а ЭЦП располагается в отдельном файле.
Центр по удостоверению подлинности электронной цифровой подписи (далее ‑ Удостоверяющий центр или УЦ) ‑ юридическое лицо или выделенное подразделение юридического лица, обладающее правомочиями на удостоверение принадлежности конкретного открытого ключа ЭЦП определенному пользователю. Сертификаты, необходимые для выполнения криптографических операций, выпускаются УЦ.
Сертификат открытого ключа (или сертификат) ‑ электронный документ, включающий открытый ключ и информацию о владельце данного ключа, заверенную с помощью ЭЦП удостоверяющим центром.
Контейнер ключа ‑ хранилище, в котором содержится закрытый ключ, а также может находиться и открытый ключ (парный к этому закрытому). Доступ к содержимому контейнера защищается паролем или каким-либо другим средством.
Владелец сертификата ключа ‑ физическое лицо, на имя которого удостоверяющим центром изготовлен сертификат открытого ключа и которое владеет соответствующим закрытым (секретным) ключом.
Модуль криптографии ‑ библиотека функций, в которой реализованы непосредственно криптографические алгоритмы или через которую осуществляется доступ к механизмам шифрования.
Метка доверенного времени ‑ достоверная информация в электронной форме о дате и времени подписания электронного документа электронной подписью. Метка доверенного времени создается и проверяется доверенной третьей стороной, удостоверяющим центром или оператором информационной системы. Эта метка получается в момент подписания электронного документа электронной подписью в установленном порядке с использованием программных и/или аппаратных средств.
23.3. Общая схема использования механизмов криптографии
23.3.1. Общая информация
При работе с криптографическими механизмами можно выделить два основных варианта использования:
● шифрование/расшифровка данных;
● подпись/проверка подписи данных.
При работе с объектом МенеджерКриптографии не рекомендуется получать несколько хранилищ сертификатов с одинаковыми характеристиками, поскольку модификация одного хранилища может привести к разному поведению другого, в зависимости от используемых модулей криптографии.
Если при использовании механизмов криптографии необходимо явно указать алгоритм, который будет использоваться при шифровании, хешировании или формировании подписи, то рекомендуется указывать эти алгоритмы не в мнемонической (аббревиатурной) нотации, а в виде идентификатора объекта (OID). Это связано с тем, что один и тот же алгоритм может по-разному описываться разными провайдерами, но при этом это все равно будет алгоритм с конкретным, уникальным OID. Так, алгоритм формирования подписи SHA-256 имеет OID 2.16.840.1.101.3.4.2.1, а криптографический алгоритм с открытым ключом RSA имеет OID 1.2.840.113549.1.1.1. Получить информацию по OID можно на сайте https://oidref.com/ (на английском языке).
В следующих разделах будут более подробно рассмотрены различные варианты использования механизма криптографии.
23.3.2. Шифрование/расшифровка
Общая схема работы при шифровании/расшифровке выглядит следующим образом:
1. Создается необходимый объект доступа к криптографической функциональности (объект МенеджерКриптографии).
2. Выбирается необходимый сертификат, который является открытым ключом принимающей стороны (объект СертификатКриптографии). С помощью этого сертификата будет выполняться шифрование данных.
3. Выполняется шифрование необходимого файла или двоичных данных с помощью методов Зашифровать() созданного объекта типа МенеджерКриптографии.
В процессе шифрования используется комбинация симметричного и асимметричного шифрования. Вначале система формирует ключ для симметричного шифрования, затем этим ключом выполняется шифрование требуемых данных. Затем ключ симметричного шифрования шифруется асимметричным ключом. Пакет данных, пригодный для передачи по открытым каналам, формируется из трех составляющих: зашифрованные данные, зашифрованный ключ для симметричного шифрования и список получателей. Пакет данных формируется по спецификации CMS (базируется на PKCS#7).
4. Зашифрованные данные готовы для передачи по открытым каналам.
5. При получении зашифрованных данных выполняется обратная операция.
6. Создается необходимый объект доступа к криптографической функциональности. Модуль криптографии, связанный с объектом, должен поддерживает работу с алгоритмами, которые использованы для шифрования данных.
7. Выполняется расшифровка полученных данных с помощью метода Расшифровать() созданного объекта доступа к криптографической функциональности.
При расшифровке из пришедшего пакета извлекается зашифрованный ключ для симметричного шифрования и расшифровывается с использованием закрытого ключа (парный к открытому ключу, который использовался для шифрования). Затем полученный ключ используется в симметричном алгоритме для расшифровки массива полученных данных. Таким образом, если принимающая сторона («из» асимметричного шифрования) не имеет закрытого ключа, будет невозможно расшифровать данные симметричным алгоритмом.
23.3.3. Подпись/проверка подписи
Общая схема работы при подписи/проверке подписи выглядит следующим образом:
1. Создается необходимый объект доступа к криптографической функциональности (объект МенеджерКриптографии).
2. Выбирается необходимый сертификат, связанный с закрытым ключом подписывающей стороны (объект СертификатКриптографии). С помощью этого сертификата будет выполняться формирование ЭЦП.
3. Выбирается используемый вариант ЭЦП с помощью свойства ВключениеДанныхВПодпись созданного объекта МенеджерКриптографии:
● Истина ‑ будет формироваться присоединенная ЭЦП.
● Ложь ‑ будет формироваться отсоединенная ЭЦП (значение по умолчанию).
Действия при работе с ЭЦП будут несколько различаться в зависимости от выбранного варианта ЭЦП.
4. Выполняется формирование ЭЦП необходимого файла или двоичных данных с помощью методов Подписать() созданного объекта типа МенеджерКриптографии.
При формировании подписи следует учитывать следующие особенности: вначале формируется хеш-сумма подписываемых данных и затем выполняется подпись полученной хеш-суммы. Это сделано для того, чтобы уменьшить время, необходимое для выполнения операции подписи данных.
В силу этого рекомендуется явным образом указывать алгоритмы, которые будут использоваться как для вычисления хеш-суммы (свойство АлгоритмХеширования), так и для выполнения подписи (свойство АлгоритмПодписи). Если принимающая сторона не будет поддерживать используемые алгоритмы (хеширования и подписи), то проверить подпись будет невозможно.
Для того чтобы явным образом указать используемые алгоритмы, следует воспользоваться методом ПолучитьИнформациюМодуляКриптографии() менеджера криптографии. В результате использования метода будет получен объект ИнформацияМодуляКриптографии, в котором свойства АлгоритмыПодписи и АлгоритмыХеширования будут содержать список алгоритмов, которые поддерживает используемый модуль криптографии. В свойства менеджера криптографии следует указывать те данные, которые содержатся в свойствах объекта ИнформацияМодуляКриптографии.
Информация об используемых алгоритмах будет содержаться в подписи, поэтому нет необходимости дополнительно передавать ее вместе с подписанными данными.
5. Подписанные данные передаются принимаемой стороне. В зависимости от выбранного варианта ЭЦП это будет один файл (присоединенная ЭЦП) или два файла (отсоединенная ЭЦП: сами данные и файл ЭЦП).
6. После получения подписанных данных выполняется обратная операция.
7. Создается необходимый объект доступа к криптографической функциональности. Модуль криптографии, связанный с объектом, должен поддерживает работу с алгоритмами, которые использованы для формирования ЭЦП.
8. Выполняется проверка электронной подписи с помощью метода ПроверитьПодпись() созданного объекта доступа к криптографическому функционалу. Если модуль криптографии, используемый для проверки подписи, не поддерживает алгоритм, используемые для вычисления хеш-суммы и подписи данных, то проверить подпись будет невозможно и будет выдана ошибка.
Система «1С:Предприятие» позволяет формировать электронную подпись в форматах CAdES (с различными вариантами) и CMS (устаревший вариант). Для указания типа электронной подписи служит параметр ТипПодписи метода Подписать(). По умолчанию подпись выполняется в формате CAdES-BES. Каждый следующий формат (кроме CMS) является расширением предыдущего формата, т. е. CAdES-T является расширением формата CAdES-BES, CAdES-C является расширением CAdES-T и т. д. Допустимы следующие варианты подписи:
● CAdES-BES (CAdESBES) ‑ основной формат электронной подписи стандарта CAdES (значение по умолчанию).
● CAdES-T (CAdEST) ‑ формат электронной подписи с доверенным временем.
● CAdES-C (CAdESC) ‑ формат электронной подписи с полным набором проверочных данных.
● CAdES-X Long Type 2 (CAdESXLongType2) ‑ формат долгосрочной расширенной подписи с несколькими расширениями.
● CAdES-A v3 (CAdESAv3) ‑ формат электронной подписи для архивного хранения.
● CMS (CMS) ‑ устаревший формат электронной подписи.
Если необходимо передать подписанный документ на архивное хранение, то для этого необходимо выполнить следующие действия:
● Подписать документ с помощью электронной подписи формата CAdES-A, который предназначен для архивного хранения. Если этого не было выполнено, то необходимо усовершенствовать существующую подпись с помощью метода УсовершенствоватьПодпись().
● Если документ подписан подписью в формате CMS, то усовершенствовать такую подпись невозможно. Документ надо переподписать подписью формата CAdES-A.
● После помещения документа в архив, необходимо с некоторой периодичностью (рекомендуется 1 раз в год) выполнять добавление в существующую подпись архивной метки времени с помощью метода ДобавитьАрхивнуюМеткуВремени(). Для того, чтобы платформа могла получить доверенную метку времени, необходимо задать сервера меток времени. Для этого служит свойство АдресаСерверовМетокВремени менеджера криптографии. Например, в качестве сервера меток времени может выступать сервер фирмы «1С» https://1stdss.1c.ru/TSP/tsp.srf или любой другой доступный сервер.
При проверке электронной подписи может потребоваться выполнять проверку установленных меток времени. Для этого следует использовать метод ПроверитьМеткуВремени().
23.4. Сертификат открытого ключа
Как было сказано выше, сертификат открытого ключа (или просто сертификат) ‑ это электронный документ определенного формата, который содержит открытый ключ, идентификационную информацию владельца ключа и некоторую служебную информацию, которая заверена электронной подписью удостоверяющего центра. В системе «1С:Предприятие» сертификат отображается в виде объекта СертификатКриптографии. В рамках данного раздела термин «сертификат» и имя объекта СертификатКриптографии будут использоваться как синонимы, если из контекста (или явно) не будет понятно другое использование терминов. Рассмотрим устройство этого объекта.
Сертификат может быть создан из файла, из двоичных данных или получен из хранилища сертификатов. В зависимости от того, где создается сертификат (на клиенте или сервере), несколько отличается набор конструкторов и методов, которые используются для создания сертификатов. Если код работает на сервере, то используется конструктор сертификата из файла Новый СертификатКриптографии(<Имя файла>) или Новый СертификатКриптографии(ОбъектДвоичныхДанных), если сертификат создается из двоичных данных. Если работа выполняется на клиенте, то вначале создается «пустой» объект Новый СертификатКриптографии(), а потом этот объект «наполняется» данными с помощью методов НачатьИнициализацию() или ИнициализироватьАсинх(). В качестве параметров метода может быть имя файла, двоичные данные или поток (в любом варианте). Для получения сертификата из хранилища сертификатов, существует объект ХранилищеСертификатовКриптографии и богатый набор методов этого объекта для получения одного или нескольких сертификатов.
Сертификат также можно выгрузить на дисковый накопитель с помощью методов Выгрузить()/ВыгрузитьАсинх()/НачатьВыгрузку() объекта СертификатКриптографии.
Теперь рассмотрим, какую информацию о сертификате открытого ключа позволяет получить объект СертификатКриптографии. Вся информацию отображается в виде свойств объекта. Для понимания значений свойств крайне желательно представлять себе, что такое идентификаторы объектов (OID) и какие значения идентификаторов чему соответствуют. Источник информации по OID см. здесь. Некоторый список идентификаторов и их описаний приведен в синтакс-помощнике, в описании свойства ДополненияСертификата.
Свойство Версия определяет версию стандарт X.509, описывающего инфраструктуру открытого ключа и определяющего формат и содержимое свойств сертификата открытого ключа. Подробнее о формате сертификата можно прочитать в RFC 2459 (https://datatracker.ietf.org/doc/html/rfc2459) и RFC 5280 (https://datatracker.ietf.org/doc/html/rfc5280). Свойства ДатаНачала и ДатаОкончания определяют период действия сертификата. Свойство СерийныйНомер содержит уникальный номер сертификата в рамках УЦ, который выдал данный сертификат. Этот УЦ указан в свойстве Издатель. Владелец сертификата описывается свойством Субъект. Описание УЦ и владельца сертификата построено по одинаковой схеме параметры, описывающие УЦ и субъекта, содержатся в свойствах фиксированной структуры, причем одновременно присутствуют и мнемонические идентификаторы свойств (C, N, OU и т. д.) и идентификаторы объектов (OID2_5_4_10 и т. д.).
Свойства ИспользоватьДляПодписи и ИспользоватьДляШифрования описывают, для чего может использоваться данный сертификат. Сам сертификат содержит значение открытого ключа (свойство ОткрытыйКлюч) и описание алгоритма открытого ключа в данном сертификате (свойство АлгоритмОткрытогоКлюча). Алгоритм определяется в терминах идентификаторов объектов (OID). Само значение открытого ключа хранится в свойстве ОткрытыйКлюч в виде двоичных данных. Т. к. сертификат подписывается УЦ, то информация о подписи также содержится в сертификате: свойство ЗначениеПодписи содержит электронную подпись сертификата в формате двоичных данных, а свойство АлгоритмПодписи содержит описание алгоритма электронной подписи в терминах идентификаторов объектов (OID). Свойство Отпечаток содержит хеш SHA-1 всего сертификата (в виде двоичных данных). Свойство ДополненияСертификата содержит Соответствие, в котором содержатся расширения сертификата. Каждое расширение идентифицируется своим идентификатором объекта (поле Ключ элемента соответствия), а значение расширения в пригодном для использования виде находится в поле Значение элемента соответствия. Свойство сертификата ДополненияСертификатаКакИсходныеДанные содержит ту же самую информацию, что и свойство ДополненияСертификата, только значения расширений представлены в «грязном» виде, как они находятся в самом сертификате, без расшифровки.
Свойства УниверсальнаяДатаНачалаОткрытогоКлюча и УниверсальнаяДатаОкончанияЗакрытогоКлюча содержат информацию о периоде действия закрытого ключа, связанного с данным сертификатом. Отдельно отметим, что закрытый ключ никак не представлен в объектной модели системы «1С:Предприятие». Закрытый ключ должен находится только у субъекта (для которого этот ключ сформирован УЦ). Как правило, закрытый ключ хранится в контейнере специального формата. Этот контейнер может хранить в себе не только закрытый ключ, но и парный сертификат открытого ключа. Контейнер защищается паролем, который известен только ответственному лицу субъекта закрытого ключа.
Если требуется проверить сертификат на применимость и корректность, то для этого предназначен методы ПроверитьСертификат()/НачатьПроверкуСертификата()/ПроверитьСертификатАсинх() менеджера криптографии. Методу передается проверяемый сертификат, режим (или режимы) проверки и дата проверки. Дата проверки ‑ это опциональный параметр, который позволяит проверить сертификат не на текущий момент времени, а на какой-то другой момент времени. Если дата проверки указана, проверка сертификата, построение цепочки сертификатов, поиск списков отозванных сертификатов и определение статуса сертификата будут выполняться с учетом этой даты. Дата указывается в формате UTC, а не в локальном времени! Режим проверки сертификата передает или одиночным значением, или набором значений (в виде массива):
● ИгнорироватьВремяДействия ‑ не проверять период действия сертифката.
● ИгнорироватьДействительностьПодписи ‑ не проверять действительность электронной подписи сертифката (подпись УЦ).
● ИгнорироватьПроверкуВСпискеОтозванныхСертификатов ‑ не проверять сертификат на отозванность (проверка по списку отозванных сертифкатов).
● РазрешитьТестовыеСертифкаты ‑ проверяемый сертификат может быть тестовым сертификатом (самозаверяющий корневой сертификат, который можно использовать для проверки и подписывания пакета драйверов или для тестовой подписи драйвера путем при работе в ОС Windows).
Если в процессе проверки будет выявлено какое-то «нарушение» (несоответствие) ‑ будет сформировано исключение. Если сертификат пригоден для использования ‑ метод завершит свою работу штатно (но без кодов возврата).
В заключении приведем пример отображения некоторой информации обо всех сертификатах корневых удостоверяющих центров на компьютере кластера серверов системы «1С:Предприятие»:
МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); Хранилище = МенеджерКриптографии.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.КорневыеСертификаты); СертификатыХранилища = Хранилище.ПолучитьВсе(); Для Каждого Сертификат Из СертификатыХранилища Цикл Сообщение = ""; ИмяСубъекта = ""; Если Не Сертификат.Субъект.Свойство("CN", ИмяСубъекта) Тогда Если Не Сертификат.Субъект.Свойство("O", ИмяСубъекта) Тогда ИмяСубъекта = "??"; КонецЕсли; КонецЕсли; Действителен = ""; Если ТекущаяДатаСеанса() > Сертификат.ДатаОкончания Тогда Действителен = "просрочен (" + Формат(Сертификат.ДатаОкончания, "ДФ=dd.MM.yyyy") + ")"; Иначе Действителен = Формат(Сертификат.ДатаНачала, "ДФ=dd.MM.yyyy") + " - " + Формат(Сертификат.ДатаОкончания, "ДФ=dd.MM.yyyy") КонецЕсли; Сообщение = Сообщение + "Сертификат """ + ИмяСубъекта + """ - "; Сообщение = Сообщение + " алгоритм ключа: " + Сертификат.АлгоритмОткрытогоКлюча; Сообщение = Сообщение + " алгоритм подписи: " + Сертификат.АлгоритмПодписи; Сообщение = Сообщение + " действителен: " + Действителен; Сообщить(Сообщение); КонецЦикла;
23.5. Работа с модулями криптографии
Для взаимодействия с модулями криптографии в ОС Windows используется Microsoft CryptoAPI, а при работе в ОС Linux или macOS ‑ интерфейс КриптоПРО CSP.
Список поддерживаемых компонент:
● Средство криптографической защиты информации КриптоПро. Для использования данного средства следует в качестве параметра ТипМодуляКриптографии конструктора объекта МенеджерКриптографии указать значение 80.
23.6. Примеры использования
23.6.1. Общая информация
В данном разделе приводятся примеры реализация некоторых типовых задач при использовании механизма криптографии.
23.6.2. Создание объекта доступа к криптографическому функционалу
Создание объекта доступа к криптографическому функционалу является базовой операцией, без выполнения которой невозможны дальнейшие операции с механизмом криптографии.
МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80);
В данном примере создается модуль для работы с российскими модулями криптографии (значение параметра ТипМодуляКриптографии равен 80).
При работе под управлением ОС Linux или macOS используется следующий алгоритм для определения расположения модуля КриптоПРО CSP:
● Если в конструкторе менеджера криптографии указан параметр ПутьМодуляКриптографии ‑ выполняется попытка использования модуля, указанного в качестве значения параметра.
● Если в конструкторе менеджера криптографии не указан параметр ПутьМодуляКриптографии, то выполняется попытка найти модуль криптографии в тех каталогах компьютера, которые указаны с помощью параметра CryptoAPILibraryLocation файла conf.cfg.
● Если параметр CryptoAPILibraryLocation отсутствует в файле conf.cfg ‑ выполняется попытка поиска модуля КриптоПРО по стандартным путям расположения модуля.
Если параметры модуля криптографии неизвестны, то можно воспользоваться простым вариантом создания менеджера криптографии:
ДляИнициализации = Новый МенеджерКриптографии(); Обещание = ДляИнициализации.ИнициализироватьАсинх(ИспользованиеИнтерактивногоРежимаКриптографии.Использовать); МенеджерКриптографии = Ждать Обещание;
23.6.3. Получение списка сертификатов
Формируется список сертификатов из выбранных хранилищ сертификатов для дальнейшей работы с этим списком.
Асинх Функция ПолучитьСписокСертификатов(ТипМенеджераКриптографии, МассивТипов, ПроверятьДатуОкончания) СписокСертификатов = Новый Массив; МенеджерКриптографии = Новый МенеджерКриптографии("", "", ТипМенеджераКриптографии); Для Каждого ТипХранилища Из МассивТипов Цикл // Получаем сертификаты для каждого типа хранилища сертификатов Хранилище = Ждать МенеджерКриптографии.ПолучитьХранилищеСертификатовАсинх(ТипХранилища); // Выбираем все сертификаты СертификатыХранилища = Ждать Хранилище.ПолучитьВсеАсинх(); ТекущаяДата = ТекущаяДата(); Для Каждого Сертификат Из СертификатыХранилища Цикл // Проверим, что дата окончания сертификата еще не наступила Если ПроверятьДатуОкончания И Сертификат.ДатаОкончания < ТекущаяДата Тогда Продолжить; КонецЕсли; СписокСертификатов.Добавить(Сертификат); КонецЦикла; КонецЦикла; Возврат СписокСертификатов; КонецФункции &НаКлиенте Асинх Процедура ВыполнитьКоманду(Команда) ТипыХранилищ = Новый Массив; ТипыХранилищ.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); ТипыХранилищ.Добавить(ТипХранилищаСертификатовКриптографии.СертификатыПолучателей); Список = Ждать ПолучитьСписокСертификатов(80, ТипыХранилищ, Истина); // … КонецПроцедуры
23.6.4. Шифрование файла
Выполняется шифрование интерактивно выбранного файла и интерактивная запись зашифрованного файла на диск клиентского компьютера.
В целях демонстрации для операции шифрования всегда используется первый по списку сертификат из всех сертификатов, установленных на компьютере.
&НаСервере Функция ЗашифроватьНаСервере(АдресДанных, ДанныеСертификатов) // Создадим сертификаты на основании двоичных данных сертификатов с клиента Сертификаты = Новый Массив(); Для Каждого ДанныеСертификата Из ДанныеСертификатов Цикл Сертификаты.Добавить(Новый СертификатКриптографии(ДанныеСертификата)); КонецЦикла; МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); // Получим файл для шифрования из временного хранилища Данные = ПолучитьИзВременногоХранилища(АдресДанных); Если ТипЗнч(Данные) <> Тип("ДвоичныеДанные") Тогда Возврат Ложь; КонецЕсли; // Шифруем двоичные данные ЗашифрованныеДвоичныеДанные = МенеджерКриптографии.Зашифровать(Данные, Сертификаты); // Сохраняем во временное хранилище АдресДанных = ПоместитьВоВременноеХранилище(ЗашифрованныеДвоичныеДанные); Возврат Истина; КонецФункции &НаКлиенте Асинх Процедура ВыполнитьКоманду(Команда) ПомещенныйФайл = Ждать ПоместитьФайлНаСерверАсинх(, , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПомещенныйФайл = Неопределено Тогда Возврат; КонецЕсли; Адрес = ПомещенныйФайл.Адрес; ТипыСертификатов = Новый Массив; ТипыСертификатов.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); Список = Ждать ПолучитьСписокСертификатов(80, ТипыСертификатов, Истина); // В примере всегда шифруем с помощью первого по порядку сертификата // В реальной жизни это может не сработать и // надо выбирать сертификат по другим критериям Сертификаты = Новый Массив; Сертификаты.Добавить(Ждать Список[0].ВыгрузитьАсинх()); // Шифруем файл РезультатШифрования = ЗашифроватьНаСервере(Адрес, Сертификаты); Если Не РезультатШифрования Тогда Возврат; КонецЕсли; // Интерактивно сохраняем зашифрованный файл на диск ПолучитьФайлССервераАсинх(Адрес, ПомещенныйФайл.СсылкаНаФайл.Файл.ПолноеИмя + ".signed", Новый ПараметрыДиалогаПолученияФайлов); КонецПроцедуры
23.6.5. Расшифровка файла
Выполняется попытка расшифровки выбранного файла. Необходима реализация функции ПолучитьПарольДоступа(), которая возвращает значение пароля доступа к закрытому ключу.
Примечание. При использовании метода Расшифровать() исключение будет вызвано только после того, как неудачно завершились попытки расшифровки с помощью всех доступных сертификатов, а не после первой ошибки.
&НаКлиенте Асинх Процедура РасшифровкаФайла() // Выбрать зашифрованный файл ПомещенныйФайл = Ждать ПоместитьФайлНаСерверАсинх(, , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПомещенныйФайл = Неопределено Тогда Возврат; КонецЕсли; Данные = ПолучитьИзВременногоХранилища(ПомещенныйФайл.Адрес); // Расшифровать файл МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); МенеджерКриптографии.ПарольДоступаКЗакрытомуКлючу = ПолучитьПарольДоступа(); РасшифрованныеДанные = Ждать МенеджерКриптографии.РасшифроватьАсинх(Данные); Адрес = ПоместитьВоВременноеХранилище(РасшифрованныеДанные); ПолучитьФайлССервераАсинх(Адрес, , Новый ПараметрыДиалогаПолученияФайлов); КонецПроцедуры
23.6.6. Формирование ЭЦП
Подписывается ЭЦП выбранный файл. Вариант подписи определяется параметром ПрисоединеннаяПодпись метода ПодписатьФайл(). Если параметр ПрисоединеннаяПодпись установлен в значение Истина, то будет формироваться присоединенная ЭЦП и в этом случае ЭЦП с включенными данными будет записана в файл, имя которого совпадает с именем выбранного файла, а расширение ‑ .sign. Если параметр ПрисоединеннаяПодпись установлен в значение Ложь, то будет сформирована отсоединенная ЭЦП. ЭЦП всегда сохраняется в файл signature.sign. Необходима реализация функций:
● ПолучитьПарольДоступа() ‑ возвращает значение пароля доступа к закрытому ключу.
● ПолучитьСписокСертификатов() ‑ возвращает массив сертификатов, которые могут использоваться для формирования ЭЦП.
&НаКлиенте Асинх Функция ПодписатьФайл(ПрисоединеннаяПодпись) // Выбрать подписываемый файл ПомещенныйФайл = Ждать ПоместитьФайлНаСерверАсинх(, , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПомещенныйФайл = Неопределено Тогда Возврат Неопределено; КонецЕсли; Данные = ПолучитьИзВременногоХранилища(ПомещенныйФайл.Адрес); // Сформировать файл подписи ТипыСертификатов = Новый Массив; ТипыСертификатов.Добавить(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); Список = Ждать ПолучитьСписокСертификатов(80, ТипыСертификатов, Истина); // В примере всегда шифруем с помощью первого по порядку сертификата // В реальной жизни это может не сработать и // надо выбирать сертификат по другим критериям Сертификат = Список[0]; Данные = ПолучитьИзВременногоХранилища(ПомещенныйФайл.Адрес); МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); МенеджерКриптографии.ПарольДоступаКЗакрытомуКлючу = ПолучитьПарольДоступа(); ФайлДляПодписи = ПомещенныйФайл.СсылкаНаФайл.Файл; МенеджерКриптографии.ВключениеДанныхВПодпись = ПрисоединеннаяПодпись; Если ПрисоединеннаяПодпись Тогда ИмяФайла = Ждать МенеджерКриптографии.ПодписатьАсинх(Данные, ФайлДляПодписи.Путь + ФайлДляПодписи.ИмяБезРасширения + ".sign", Сертификат); Иначе ИмяФайла = Ждать МенеджерКриптографии.ПодписатьАсинх(Данные, ФайлДляПодписи.Путь + "signature.sign", Сертификат); КонецЕсли; КонецФункции
23.6.7. Проверка ЭЦП
Функция выполняет проверку действительности ЭЦП для некоторого файла. Вначале выполняется проверка, что файл является файлом ЭЦП с включенными данными. Если на вход передан файл без присоединенной ЭЦП, то ожидается, что отсоединенная ЭЦП находится в файле с именем signature.sign. В этом случае предполагается, что файл ЭЦП находится в том же каталоге, что и подписанный файл. В переменную ПодписанныеДанные получается файл, который был подписан присоединенной ЭЦП. В примере эти данные никак не используются.
&НаКлиенте Асинх Функция ПроверитьПодписьФайла() // Выбрать подписанный файл ПроверяемыйФайл = Ждать ПоместитьФайлНаСерверАсинх( , , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПроверяемыйФайл = Неопределено Тогда Возврат Неопределено; КонецЕсли; ДанныеФайла = ПолучитьИзВременногоХранилища(ПроверяемыйФайл.Адрес); МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); ЭтоПрисоединеннаяПодпись = Ждать МенеджерКриптографии.ПроверитьНаличиеДанныхВПодписиАсинх(ДанныеФайла); Если ЭтоПрисоединеннаяПодпись Тогда Сертификат = Ждать МенеджерКриптографии.ПроверитьПодписьАсинх(ДанныеФайла); ПодписанныеДанные = Ждать МенеджерКриптографии.ПолучитьДанныеИзПодписиАсинх(ДанныеФайла); Иначе ПроверяемаяПодпись = Ждать ПоместитьФайлНаСерверАсинх( , , , ПроверяемыйФайл.СсылкаНаФайл.Файл.Путь + "signature.sign"); Если ПроверяемаяПодпись = Неопределено Тогда Возврат Неопределено; КонецЕсли; Подпись = ПолучитьИзВременногоХранилища(ПроверяемаяПодпись.Адрес); Сертификат = Ждать МенеджерКриптографии.ПроверитьПодписьАсинх(ДанныеФайла, Подпись); КонецЕсли; КонецФункции
23.6.8. Усовершенствование ЭЦП
Функция выполняет усовершенствование отсоединенной ЭЦП, т. е. изменяет тип электронной подписи до типа, который содержит отметку доверенного времени. Считается, что подпись хранится в файле с тем же именем и расширением .sign. Усовершенствованная подпись будет сохраняться в файле с расширением .extsign. В данном примере предлагается выбрать не файл подписи, а подписанный файл. Имена файл подписи и файла усовершенствованной подписи функция сформирует самостоятельно.
&НаКлиенте Асинх Процедура ВыполнитьКоманду(Команда) // Выбрать подписанный файл ПомещенныйФайл = Ждать ПоместитьФайлНаСерверАсинх( , , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПомещенныйФайл = Неопределено Тогда Возврат; КонецЕсли; ИмяФайлаПодписи = СтрЗаменить(ПомещенныйФайл.СсылкаНаФайл.Файл.ПолноеИмя, ПомещенныйФайл.СсылкаНаФайл.Расширение, ".sign"); ИмяФайлаУсовершенствованнойПодписи = СтрЗаменить(ПомещенныйФайл.СсылкаНаФайл.Файл.ПолноеИмя, ПомещенныйФайл.СсылкаНаФайл.Расширение, ".extsign"); ПомещеннаяПодпись = Ждать ПоместитьФайлНаСерверАсинх( , , , ИмяФайлаПодписи); Если ПомещеннаяПодпись = Неопределено Тогда Возврат; КонецЕсли; Подпись = ПолучитьИзВременногоХранилища(ПомещеннаяПодпись.Адрес); МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); // Установим адреса серверов меток доверенного времени Адреса = Новый Массив; Адреса.Добавить("http://testca2012.cryptopro.ru/tsp/tsp.srf"); МенеджерКриптографии.АдресаСерверовМетокВремени = Адреса; // Усовершенствуем подпись файла Ждать МенеджерКриптографии.УсовершенствоватьПодписьАсинх(Подпись, ИмяФайлаУсовершенствованнойПодписи, ТипПодписиКриптографии.CAdESAv3); КонецПроцедуры
23.6.9. Добавление архивной метки времени
В том случае, если подписанный документ находится в архиве, требуется периодически добавлять в подпись данного документа архивные метки времени. Функция демонстрирует данную операцию для всех файлов отсоединенной ЭЦП, расположенных в некоторой директории. Считаем, что файл ЭЦП ‑ это файл с произвольным именем и расширением .sign. Файл ЭЦП с добавленной архивной меткой времени сохранятся в тот же самый файл.
&НаКлиенте Асинх Процедура ВыполнитьКоманду(Команда) МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); // Установим адреса серверов меток доверенного времени Адреса = Новый Массив; Адреса.Добавить("https://1stdss.1c.ru/TSP/tsp.srf"); МенеджерКриптографии.АдресаСерверовМетокВремени = Адреса; // Выберем все файлы подписи ИсходныйКаталог = "c:\temp"; ФайлыПодписей = Ждать НайтиФайлыАсинх(ИсходныйКаталог, "*.sign", Ложь); Для каждого ФайлПодписи Из ФайлыПодписей Цикл НоваяПодпись = Ждать МенеджерКриптографии.ДобавитьАрхивнуюМеткуВремениАсинх(ФайлПодписи.ПолноеИмя); // запишем подпись обратно в файл Ждать НоваяПодпись.ЗаписатьАсинх(ФайлПодписи.ПолноеИмя); КонецЦикла; КонецПроцедуры
23.6.10. Получение информации о подписях
В данном примере рассматривается получение информации о подписях, которыми подписан файл. В примере происходит автоматическое определение типа подписи. Для отсоединенной подписи используется алгоритм хранения подписи, который описан в примере формирования (и проверки) ЭЦП.
&НаКлиенте Асинх Процедура ПолучитьИнформациюОПодписях(Команда) // Выбрать подписанный файл ПроверяемыйФайл = Ждать ПоместитьФайлНаСерверАсинх( , , , Новый ПараметрыДиалогаПомещенияФайлов); Если ПроверяемыйФайл = Неопределено Тогда Возврат; КонецЕсли; ДанныеФайла = ПолучитьИзВременногоХранилища(ПроверяемыйФайл.Адрес); МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); ЭтоПрисоединеннаяПодпись = Ждать МенеджерКриптографии.ПроверитьНаличиеДанныхВПодписиАсинх(ДанныеФайла); Если ЭтоПрисоединеннаяПодпись Тогда КонтейнерПодписей = Ждать МенеджерКриптографии.ПолучитьКонтейнерПодписейКриптографииАсинх(ДанныеФайла); Иначе ПроверяемаяПодпись = Ждать ПоместитьФайлНаСерверАсинх( , , , ПроверяемыйФайл.СсылкаНаФайл.Файл.Путь + "signature.sign"); Если ПроверяемаяПодпись = Неопределено Тогда Возврат; КонецЕсли; ДанныеПодписи = ПолучитьИзВременногоХранилища(ПроверяемаяПодпись.Адрес); КонтейнерПодписей = Ждать МенеджерКриптографии.ПолучитьКонтейнерПодписейКриптографииАсинх(ДанныеПодписи); КонецЕсли; Для каждого Подпись Из КонтейнерПодписей.Подписи Цикл Строка = ""; Строка = "Индекс: " + Подпись.Индекс; Строка = Строка + " Данные: " + ?(Подпись.Данные = Неопределено, "отсутствуют", "присутствуют"); Строка = Строка + " ТипПодписи: " + Подпись.ТипПодписи; Строка = Строка + " АлгоритмХеширования: " + Подпись.АлгоритмХеширования; Строка = Строка + " АлгоритмПодписи: " + Подпись.АлгоритмПодписи; Сообщить(Строка); КонецЦикла; КонецПроцедуры
23.7. Асинхронная работа с механизмом криптографии
Использование асинхронной схемы работы с криптографией имеет ряд особенностей:
● Она доступна только на стороне клиентского приложения. На стороне сервера следует использовать синхронный способ работы.
● Для использования криптографии в веб-клиенте необходимо предварительно установить расширение работы с криптографией.
Рассмотрим пример работы с криптографической функциональностью в асинхронном режиме. В качестве примера будет рассмотрен процесс получения списка сертификатов из определенного типа хранилища сертификатов.
Примечание. Пример, приведенный ниже, не является законченным. Он предназначен для демонстрации асинхронной работы со средствами криптографии.
&НаКлиенте Асинх Процедура ПолучитьСписок(Команда) Криптография = Новый МенеджерКриптографии; Ждать Криптография.ИнициализироватьАсинх("", "", 80); ХранилищеСертификатов = Ждать Криптография.ПолучитьХранилищеСертификатовАсинх(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты); МассивСертификатов = Ждать ХранилищеСертификатов.ПолучитьВсеАсинх(); Для Каждого Сертификат Из МассивСертификатов Цикл Сообщить("Серийный номер сертификата = " + Сертификат.СерийныйНомер); КонецЦикла; КонецПроцедуры
Данный пример полностью иллюстрирует особенности работы с криптографией в асинхронном режиме. В примере видно, что собственно код на встроенном языке практически не отличается от аналогичного кода, который использовался в синхронной схеме работы.