Электронная подпись
В данной статье рассматриваются примеры работы с электронной подписью: генерация сертификатов с использованием различных криптопровайдеров, подпись данных, проверка подписи и замена сертификата.
Работа с электронной подписью на сервере
Установите модули криптографии на сервере, чтобы использовать данные примеры в своем проекте.
Генерация сертификатов электронной подписи
Чтобы сгенерировать серти фикат электронной подписи, создайте экземпляр типа ГенераторСертификата, установите необходимые атрибуты субъекта сертификата и вызовите метод СоздатьСертификат(). По умолчанию будет сгенерирован самоподписанный сертификат, в котором для подписи будет использован сформированный закрытый ключ и указанный алгоритм хеширования. Добавьте сертификат и закрытый ключ в хранилище соответствующего типа (ХранилищеPkcs12, ХранилищеКриптоПро или ХранилищеJks), используя метод ДобавитьЗакрытыйКлюч().
В примере ниже показано использование Bouncy Castle (криптопровайдера по умолчанию) для создания сертификата электронной подписи с ключами ГОСТ.
метод СоздатьСертификат(Сотрудник: Сотрудник, Пароль: Строка): ХранилищеPkcs12
    знч Генератор = новый ГенераторСертификата(АлгоритмАсимметричногоШифрования.Гост3410_2012)
    Генератор.УстановитьАтрибутСубъекта(АтрибутX500.Имя, Сотрудник.Имя)
    Генератор.УстановитьАтрибутСубъекта(АтрибутX500.Должность, Сотрудник.Должность)
    Генератор.УстановитьАтрибутСубъекта(АтрибутX500.Снилс, Сотрудник.Снилс)
    Генератор.УстановитьАтрибутСубъекта(АтрибутX500.Инн, Сотрудник.Инн)
    Генератор.УстановитьАтрибутСубъекта(АтрибутX500.Организация, "Название организации")
    Генератор.ДействителенПо = Момент.Сейчас() + 730д
    знч Сертификат = Генератор.СоздатьСертификат()
    знч Хранилище = новый ХранилищеPkcs12()
    Хранилище.ДобавитьЗакрытыйКлюч(Сотрудник.Имя, Генератор.ЗакрытыйКлюч, Пароль, Сертификат)
    возврат Хранилище
;
// Структура, содержащая информацию о сотруднике организации.
структура Сотрудник
    пер Имя: Строка
    пер Должность: Строка
    пер Снилс: Строка
    пер Инн: Строка
    // ...
;
В следующем примере используется криптопровайдер КриптоПро Java CSP, чтобы сгенерировать сертификат электронной подписи с ключами ГОСТ:
метод СоздатьСертификат(Сотрудник: Строка, Пароль: Строка)
    знч КриптоПро = Криптография.ПолучитьКриптоПроJcsp()
 
    знч ДействителенС = ДатаВремя.Сейчас().НачалоДня().ВМомент(ЧасовойПояс{UTC})
    знч ДействителенПо = ДействителенС + 365д
 
    знч Генератор = новый ГенераторСертификата(АлгоритмАсимметричногоШифрования.Гост3410_2012, Криптопровайдер = КриптоПро)
    Генератор.СерийныйНомер = Байты{90123456789012345678901234567890}
    Генератор.Субъект = "CN=Имя Издателя,O=Организация,OU=Отдел 1"
    Генератор.ДействителенС = ДействителенС
    Генератор.ДействителенПо = ДействителенПо
    знч Сертификат = Генератор.СоздатьСертификат()
    
    знч Хранилище = новый ХранилищеКриптоПро("HDIMAGE")
    Хранилище.ДобавитьЗакрытыйКлюч(Сотрудник, Генератор.ЗакрытыйКлюч, Пароль, Сертификат)
;
Вычисление электронной подписи
Чтобы подписать данные, используя сгенерированный сертификат и соответс твующий закрытый ключ, создайте экземпляр типа ВычислительПодписи и вызовите метод Подписать(). В примере ниже показано вычисление электронной подписи для указанных данных с использованием криптопровайдера КриптоПро JCP.
метод ВычислитьПодпись(Данные: Байты, Хранилище: ХранилищеКриптоПро): Байты
    знч Криптопровайдер = Криптография.ПолучитьКриптоПро()
    знч Ключ = Хранилище.НайтиЗакрытыйКлюч("Тест", "12345")
    знч Сертификат = Хранилище.НайтиСертификат("Тест")
    попытка
        знч Вычислитель = новый ВычислительПодпи си(Криптопровайдер, Сертификат, Ключ)
        Вычислитель.УстановитьСлужбуШтамповВремени("http://qs.cryptopro.ru/tsp/tsp.srf")
        возврат Вычислитель.Подписать(Данные)
    поймать ОшибкаЗапросаКСервисуШтамповВремени: ИсключениеЗапросаШтампаВремениПодписи
        // обработка исключения
    ;
;
Если при обращении к сервису штампов времени при создании подписи или при добавлении к ней штампа времени произошла ошибка, выбрасывается исключение ИсключениеЗапросаШтампаВремениПодписи. В его свойстве ПодписьБезШтампа содержится электронная подпись без штампа времени. В дальнейшем его можно проставить с помощью метода ВычислительПодписи.ДобавитьШтампВремени().
Замена сертификата
Тип ВычислительПодписи содержит метод ЗаменитьСертификат, который позволяет вам заменить сертификат или цепочку сертификатов в уже сформированной подписи формата CMS/PKCS#7. Например, если вы не хотите включать всю цепочку сертификатов в подпись, а хотите использовать только сертификат субъекта (например, сотрудника организации) при вычислении подписи, вы можете удалить корневой сертификат из подписи, как показано в примере ниже. Пример использует метод РазорватьЦепочку() типа ЦифровойСертификат, чтобы разорвать цепочку сертификатов. Данный метод возвращает копию текущего сертификата, у которой свойство СертификатИздателя установлено в Неопределено.
метод УдалитьКорневойСертификат(По дпись: Байты): Байты
    знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
    знч Сертификат = Верификатор.ПолучитьСертификаты().ПервыйИлиНеопределено()
    если Сертификат?.СертификатИздателя == Неопределено
        возврат Подпись
    ;
    возврат ВычислительПодписи.ЗаменитьСертификат(Подпись, Сертификат.РазорватьЦепочку())
;
Проверка электронной подписи
Чтобы проверить подлинность электронной подписи формата PKCS#7, используйте метод Проверить() типа ВерификаторПодпи си. Пример ниже показывает, как проверить подпись, используя алгоритмы криптопровайдера Bouncy Castle. Если подпись не является валидной, возвращается Ложь.
метод ПроверитьПодпись(Данные: ПотокЧтения, Подпись: Байты): Булево
    знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
    возврат Верификатор.Проверить(Данные)
;
Если вам необходимо получить дату формирования электронной подписи, используйте свойство МоментПодписи типа ВерификаторПодписи, как показано ниже.
метод ПолучитьМоментПодписи(Подпись: Байты): Момент?
    знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
    возврат Верификатор.МоментПодписи
;
Получение отпечатка цифрового сертификата
Используйте метод ПолучитьОтпечаток() типа ЦифровойСертификат, чтобы вычислить хеш-значение (дайджест) сертификата:
метод ВычислитьОтпечаток(БайтыСертификата: Байты): Байты
    знч Алгоритм = АлгоритмХеширования.Sha1
    знч Криптопровайдер = Криптография.ПолучитьBouncyCastle()
    
    знч Сертификат = новый ЦифровойСертификат(БайтыСертификата)
    возврат Сертификат.ПолучитьОтпечаток(Алгоритм, Криптопровайдер)
;
Работа с электронной подписью на клиенте
«1С:Шина» предоставляет возможность вычислять и проверять электронную подпись на клиенте с использованием отечественных криптопровайдеров, таких как КриптоПро CSP и ViPNet CSP.
На клиенте используются те же типы и методы из пространства имен Стд::Криптография, что и на сервере. Для их работы требуется установить расширение для браузера и модуль для работы с электронными подписями. Если они не установлены, пользователю будет предложено их скачать и установить:

Эту форму можно вызвать явно с помощью метода Криптография.УстановитьРасширение().