Перейти к основному содержимому

Электронная подпись

В данной статье рассматриваются примеры работы с электронной подписью: генерация сертификатов с использованием различных криптопровайдеров, подпись данных, проверка подписи и замена сертификата.

Работа с электронной подписью на сервере

дополнительно

Установите модули криптографии на сервере, чтобы использовать данные примеры в своем проекте.

Генерация сертификатов электронной подписи

Чтобы сгенерировать сертификат электронной подписи, создайте экземпляр типа ГенераторСертификата, установите необходимые атрибуты субъекта сертификата и вызовите метод СоздатьСертификат(). По умолчанию будет сгенерирован самоподписанный сертификат, в котором для подписи будет использован сформированный закрытый ключ и указанный алгоритм хеширования. Добавьте сертификат и закрытый ключ в хранилище соответствующего типа (Хранилище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")
Хранилище.ДобавитьЗакрытыйКлюч(Сотрудник, Генератор.ЗакрытыйКлюч, Пароль, Сертификат)
;

Создание запроса на выпуск подписанного сертификата (CSR)

«1С:Шина» позволяет сформировать структурированный запрос на выпуск цифрового сертификата (Certificate Signing Request, CSR) в формате PKCS #10.

Данный запрос включает в себя:

  • данные субъекта, для которого выпускается сертификат (имя, организация, адрес и т. д.);
  • открытый ключ;
  • дополнительные атрибуты сертификата;
  • электронную подпись, созданную закрытым ключом.

Чтобы сформировать запрос на выпуск сертификата, используйте методы типа ЗапросНаПодписьСертификата.

примечание

Для создания запроса необходимо установить криптопровайдер Bouncy Castle.

метод СформироватьЗапрос(Сотрудник: Строка, Пароль: Секрет): Байты
// Формирование запроса на выпуск сертификата
знч Запрос = новый ЗапросНаПодписьСертификата(АлгоритмАсимметричногоШифрования.Гост3410_2012)
Запрос.УстановитьАтрибутСубъекта(АтрибутX500.Имя, Сотрудник)
Запрос.УстановитьАтрибутСубъекта(АтрибутX500.Организация, "Название организации")
Запрос.УстановитьРасширенноеИспользованиеКлюча(["1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2"])

// Запись запроса в формате PKCS #10
возврат Запрос.ВБайты()
;

Затем вы можете отправить сформированный запрос в удостоверяющий центр, который с помощью открытого ключа проверит подлинность запроса и выпустит сертификат на основе указанных параметров. Сохраните полученный сертификат и закрытый ключ в хранилище для дальнейшего использования.

Вычисление и проверка электронной подписи

Используйте методы типа ПодписьДанных, чтобы вычислить или проверить электронную подпись для указанных данных (байтов или потока чтения) с помощью закрытого и открытого ключей шифрования. Алгоритм вычисления подписи можно задать в виде строки или с помощью перечисления АлгоритмПодписи.

Если вам требуется вычислить или проверить подпись для небольшого объема данных, используйте статический метод Подписать() или Проверить() типа ПодписьДанных.

метод ПодписатьДанные(Данные: Байты)
// Генерация ключей по алгоритму шифрования RSA
знч ПараКлючей = ГенераторПарыКлючей.СоздатьПаруКлючейRsa()
// Вычисление электронной подписи
знч Подпись = ПодписьДанных.Подписать(ПараКлючей.ЗакрытыйКлюч, АлгоритмПодписи.Sha256_Rsa, Данные)
// Проверка подписи
знч РезультатПроверки = ПодписьДанных.Проверить(ПараКлючей.ОткрытыйКлюч, АлгоритмПодписи.Sha256_Rsa,
Данные, Подпись)
;

Если вы работаете с большим объемом информации, вы можете подписывать/проверять данные частями. Для этого создайте экземпляр типа ПодписьДанных и используйте метод ДобавитьДанные() для добавления новых порций данных. Вызовите метод Подписать() / Проверить(), чтобы завершить выполнение операции.

метод ПодписатьДанныеПоЧастям()
// Генерация ключей по алгоритму шифрования RSA
знч ПараКлючей = ГенераторПарыКлючей.СоздатьПаруКлючейRsa()

// Порции данных для подписи
знч Данные1 = "Данные ".ВБайты()
знч Данные2 = "для ".ВБайты()
знч Данные3 = "подписи".ВБайты()

// Вычисление электронной подписи
знч ВычислениеПодписи = новый ПодписьДанных(ПараКлючей.ЗакрытыйКлюч, АлгоритмПодписи.Sha256_Rsa)
ВычислениеПодписи.ДобавитьДанные(Данные1)
ВычислениеПодписи.ДобавитьДанные(Данные2)
ВычислениеПодписи.ДобавитьДанные(Данные3)
знч Подпись = ВычислениеПодписи.Подписать()

// Проверка подписи
знч РезультатПроверки = новый ПодписьДанных(ПараКлючей.ОткрытыйКлюч, АлгоритмПодписи.Sha256_Rsa)
.ДобавитьДанные(Данные1)
.ДобавитьДанные(Данные2)
.ДобавитьДанные(Данные3)
.Проверить(Подпись)
;

Вычисление электронной подписи формата CAdES

Чтобы подписать данные, используя цифровой сертификат и соответствующий закрытый ключ, создайте экземпляр типа ВычислительПодписи и вызовите метод Подписать(). В примере ниже показано вычисление электронной подписи для указанных данных с использованием криптопровайдера КриптоПро JCP.

метод ВычислитьПодпись(Данные: Байты, Хранилище: ХранилищеКриптоПро): Байты?
знч Криптопровайдер = Криптография.ПолучитьКриптоПро()

знч Ключ = Хранилище.НайтиЗакрытыйКлюч("Тест", "12345")
знч Сертификат = Хранилище.НайтиСертификат("Тест")

попытка
знч Вычислитель = новый ВычислительПодписи(Криптопровайдер, Сертификат, Ключ)
Вычислитель.УстановитьСлужбуШтамповВремени("http://qs.cryptopro.ru/tsp/tsp.srf")
возврат Вычислитель.Подписать(Данные)
поймать ОшибкаЗапросаКСервисуШтамповВремени: ИсключениеЗапросаШтампаВремениПодписи
возврат Неопределено
;
;

Если при обращении к сервису штампов времени при создании подписи или при добавлении к ней штампа времени произошла ошибка, выбрасывается исключение ИсключениеЗапросаШтампаВремениПодписи. В его свойстве ПодписьБезШтампа содержится электронная подпись без штампа времени. В дальнейшем его можно проставить с помощью метода ВычислительПодписи.ДобавитьШтампВремени().

Замена сертификата

Тип ВычислительПодписи содержит метод ЗаменитьСертификат, который позволяет вам заменить сертификат или цепочку сертификатов в уже сформированной подписи формата CMS/PKCS#7. Например, если вы не хотите включать всю цепочку сертификатов в подпись, а хотите использовать только сертификат субъекта (например, сотрудника организации) при вычислении подписи, вы можете удалить корневой сертификат из подписи, как показано в примере ниже. Пример использует метод РазорватьЦепочку() типа ЦифровойСертификат, чтобы разорвать цепочку сертификатов. Данный метод возвращает копию текущего сертификата, у которой свойство СертификатИздателя установлено в Неопределено.

метод УдалитьКорневойСертификат(Подпись: Байты): Байты
знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
знч Сертификат = Верификатор.ПолучитьСертификаты().ПервыйИлиНеопределено()
если Сертификат?.СертификатИздателя == Неопределено
возврат Подпись
;
возврат ВычислительПодписи.ЗаменитьСертификат(Подпись, Сертификат.РазорватьЦепочку())
;

Проверка электронной подписи формата CMS/CAdES

Чтобы проверить подлинность электронной подписи формата CMS/CAdES, используйте метод Проверить() типа ВерификаторПодписи. Пример ниже показывает, как проверить подпись, используя алгоритмы криптопровайдера Bouncy Castle. Если подпись не является валидной, возвращается Ложь.

метод ПроверитьПодпись(Данные: ПотокЧтения, Подпись: Байты): Булево
знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
возврат Верификатор.Проверить(Данные)
;

Если вам необходимо получить дату формирования электронной подписи, используйте свойство МоментПодписи типа ВерификаторПодписи, как показано ниже.

метод ПолучитьМоментПодписи(Подпись: Байты): Момент?
знч Верификатор = новый ВерификаторПодписи(Криптография.ПолучитьBouncyCastle(), Подпись)
возврат Верификатор.МоментПодписи
;

Получение отпечатка цифрового сертификата

Используйте метод ПолучитьОтпечаток() типа ЦифровойСертификат, чтобы вычислить хеш-значение (дайджест) сертификата:

метод ВычислитьОтпечаток(БайтыСертификата: Байты): Байты
знч Алгоритм = АлгоритмХеширования.Sha1
знч Криптопровайдер = Криптография.ПолучитьBouncyCastle()

знч Сертификат = новый ЦифровойСертификат(БайтыСертификата)
возврат Сертификат.ПолучитьОтпечаток(Алгоритм, Криптопровайдер)
;

Работа с электронной подписью на клиенте

«1С:Шина» предоставляет возможность вычислять и проверять электронную подпись на клиенте с использованием отечественных криптопровайдеров, таких как КриптоПро CSP и ViPNet CSP.

На клиенте используются те же типы и методы из пространства имен Стд::Криптография, что и на сервере. Для их работы требуется установить расширение для браузера и модуль для работы с электронными подписями. Если они не установлены, пользователю будет предложено их скачать и установить:

Форма загрузки модулей для работы с электронной подписью на клиенте

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

См. также