Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


Openssl поддерживает российские криптоалгоритмы, начиная с версии 1.0. Для того, чтобы их использовать, в openssl требуется подгружать engine gost. В большинстве дистрибутивов openssl эта библиотека присутствует. Чтобы engine подгружалась, можно прописать ее в конфигурационном файле openssl:

Code Block
[openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
engine_id = gost
default_algorithms = ALL

Если конфигурационный файл openssl не расположен в стандартном месте, то путь к нему можно задать через переменную окружения OPENSSL_CONF. 

...


Последовательность вызовов в клиентском скрипте будет следующей:

 Image Added

Далее запрос отправляется на сервер, где на его основе выдается сертификат.
Для этого на сервере должен быть установлен и правильно сконфигурирован openssl версии от 1.0 и развернут функционал УЦ.

1. Генерация улюча УЦ:

Code Block
languagebash
openssl genpkey -engine gost -algorithm GOST2001 -pkeyopt paramset:A -out ca.key

После этого в файле ca.key будет создан закрытый ключ

2. Создание самоподписанного сертификата УЦ:

Code Block
languagebash
openssl req -engine gost -x509 -new -key ca.key -out ca.crt

После ввода необходимой информации об издателе в файле ca.crt будет создан сертификат УЦ.

Полученный от клиента запрос сохраняем в файл user.csr и выдаем на его основе сертификат (без модификации данных из запроса):

Code Block
languagebash
openssl ca -engine gost -keyfile ca.key -cert ca.crt -in user.csr -out user.crt -outform PEM -batch

После этого в файле user.crt создается сертификат пользователя в PEM формате. Его следует отправить на клиент.
 

Дальнейшая последовательность вызовов на клиенте:

 Image Added

 

Сертификат уже имеется на токене, выдан внешним УЦ

Ключевая пара при этом должна быть создана в формате, совместимом с библиотекой rtPKCS11ECP для Рутокен ЭЦП.

  • Получаем список подключенных к компьютеру устройств Рутокен ЭЦП
  • Получаем список всех имеющихся пользовательских сертификатов на выбранном Рутокен ЭЦП
  • Визуализируем каждый сертификат
  • Пользователь выбирает нужный сертификат
  • Сервер формирует начальную последовательность случайных данных (строку salt) и отправляет ее на клиент
  • Вызываем на клиенте authenticate. При передаче salt в функцию плагина authenticate данная последовательность дополняется дополнительными случайными данными размером в 32 символа, и происходит подпись итоговой последовательности на выбранном пользователем сертификате в формате CMS attached
  • Подпись отправляется на сервер
  • На сервере происходит проверка CMS attached подписи с использованием корневого сертификата
  • Из CMS attached сообщения извлекается итоговая случайная последовательность, “отсоединяется” salt и происходит сравнение
  • Если сравнение успешно, то регистрируем пользователя по сертификату, который содержится в CMS attached сообщении


Последовательность вызовов на клиенте:

 Image Added

Подпись получается в base64-формате. При проверке ее на сервере с помощью openssl подпись следует обрамить заголовками, чтобы сделать из нее PEM. Выглядеть подобная подпись будет примерно так:

Code Block
-----BEGIN CMS-----
MIIDUQYJKoZIhvcNAQcCoIIDQjCCAz4CAQExDDAKBgYqhQMCAgkFADCBygYJKoZI
hvcNAQcBoIG8BIG5PCFQSU5QQURGSUxFIFVURjg+PFY+0JLRi9C/0L7Qu9C90LjR
gtGMINCw0YPRgtC10L3RgtC40YTQuNC60LDRhtC40Y4/PCE+c2VydmVyLXJhbmRv
bS1kYXRhZTI6ZGE6MmM6MDU6MGI6MzY6MjU6MzQ6YzM6NDk6Nzk6Mzk6YmI6MmY6
YzU6Mzc6ZGI6MzA6MTQ6NDQ6ODM6NjY6Njk6NmI6OWY6YTU6MDk6MzQ6YmY6YzQ6
NzY6YzmgggGeMIIBmjCCAUegAwIBAgIBATAKBgYqhQMCAgMFADBUMQswCQYDVQQG
EwJSVTEPMA0GA1UEBxMGTW9zY293MSIwIAYDVQQKFBlPT08gIkdhcmFudC1QYXJr
LVRlbGVjb20iMRAwDgYDVQQDEwdUZXN0IENBMB4XDTE0MTIyMjE2NTEyNVoXDTE1
MTIyMjE2NTEyNVowEDEOMAwGA1UEAxMFZmZmZmYwYzAcBgYqhQMCAhMwEgYHKoUD
AgIjAQYHKoUDAgIeAQNDAARADKA/O1Zw50PzMpcNkWnW39mAJcTehAhkQ2Vg7bHk
IwIdf7zPe2PxHyAr6lH+stqdACK6sFYmkZ58cBjzL0WBwaNEMEIwJQYDVR0lBB4w
HAYIKwYBBQUHAwIGCCsGAQUFBwMEBgYpAQEBAQIwCwYDVR0PBAQDAgKkMAwGA1Ud
EwEB/wQCMAAwCgYGKoUDAgIDBQADQQD5TY55KbwADGKJRK+bwCGZw24sdIyayIX5
dn9hrKkNrZsWdetWY3KJFylSulykS/dfJ871IT+8dXPU5A7WqG4+MYG7MIG4AgEB
MFkwVDELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2NvdzEiMCAGA1UEChQZT09P
ICJHYXJhbnQtUGFyay1UZWxlY29tIjEQMA4GA1UEAxMHVGVzdCBDQQIBATAKBgYq
hQMCAgkFADAKBgYqhQMCAhMFAARAco5PumEfUYVcLMb1cnzETNOuWC8Goda8pdUL
W5ASK+tztCwM7wpXgAy+Y6/sLtClO9sh8dKnAaEY2Yavg3altQ==
-----END CMS-----
Code Block
languagebash
titleПроверка подписи на сервере:
openssl cms -engine gost -verify -in sign.cms -inform PEM -CAfile ca.crt -out data.file -certsout user.cr

Здесь sign.cms — файл, в котором находится подпись, ca.crt — файл с корневыми сертификатами, до одного из которых должна выстроиться цепочка, data.file — файл, в который будет сохранены подписанные данные, user.crt — файл, в который будет сохранен пользовательский сертификат. Именно из data.file нужно извлечь данные отсоединить последние 32 символа и сравнить salt.

Если на сервере нужно получить информацию из сертификата, то парсить его можно так:

Code Block
languagebash
titleПоказать содержимое сертификата в текстовом представлении:
 openssl x509 -in cert.pem -noout -text
Code Block
languagebash
titleПоказать серийный номер сертификата:
 openssl x509 -in cert.pem -noout -serial
Code Block
languagebash
titleПоказать DN субъекта (subject):
openssl x509 -in cert.pem -noout -subject

 

 

Code Block
languagebash
titleПоказать DN издателя (issuer):
openssl x509 -in cert.pem -noout -issuer

 

 

Code Block
languagebash
titleПоказать почтовый адрес субъекта:
openssl x509 -in cert.pem -noout -email


 

Code Block
languagebash
titleПоказать время начала действия сертификата:
openssl x509 -in cert.pem -noout -startdate


 

Code Block
languagebash
titleПоказать время окончания действия сертификата:
openssl x509 -in cert.pem -noout -enddate

Строгая аутентификация на портале

Общая схема аутентификации, используемая в Рутокен Плагин, выглядит следующим образом: 

  • сервер формирует начальную последовательность случайных данных (строку salt) и отправляет ее на клиент
  • при передаче salt в функцию плагина authenticate данная последовательность дополняется случайными данными размером в 32 символа, и происходит подпись итоговой последовательности на выбранном пользователем сертификате в формате CMS attached
  • подпись отправляется на сервер
  • на сервере происходит проверка подписи
  • из CMS attached сообщения извлекается итоговая случайная последовательность, “отсоединяется” salt и происходит сравнение
  • в случае успешной проверки пользователь аутентифицируется на основе сертификата, извлеченного из сообщения CMS


Реализация данной схемы ничем принципиально не отличается от «Регистрация, сертификат уже имеется, выдан внешним УЦ».

Электронная подпись данных и/или файлов в формате CMS

  • формируется текстовое сообщение (строка), формирование сообщения может происходить как на сервере, так и на клиенте
  • если требуется подписать документ произвольного формата (например, PDF), то требуется перекодировать его в формат base64
  • строка, содержащая данные для подписи, передается в функцию sign
  • если строка представляет собой закодированные в base64 данные, то параметр функции isBase64 должен быть установлен в true, при этом перед подписью произойдет декодирование данных из base64
  • если требуется использовать аппаратное вычисление хэш-функции ГОСТ Р 34.11-94 (сертифицированная реализация, скорость 60-70 Кб/c), то в options нужно установить опцию useHardwareHash в true. Если данная опция установлена в false, то будет использована быстрая программная реализация хэш-функции ГОСТ Р 34.11-94
  • если требуется сформировать “отсоединенную” (detached) подпись CMS, то нужно установить опцию detached в true, иначе будет сформирована “присоединенная” (attached) подпись
  • для того, чтобы включить/не включить пользовательский сертификат в подписанное CMS-сообщение существует опция addUserCertificate
  • Установка опции addSignTime в true приведет к тому, что в подписанное CMS-сообщение будет добавлено системное время в качестве подписанного атрибута

Проверка подписи на сервере описана выше.

Шифрование/расшифрование данных и/или файлов в формате CMS

Шифрование данных на клиенте для сервера

Для того, чтобы обеспечить конфиденциальность обмена данными между клиентом и сервером в плагине предусмотрено шифрование/расшифрование данных. Данные шифруются в формате CMS. Для того, чтобы зашифровать данные в формате CMS, требуется сертификат открытого ключа «адресата». При этом расшифровать такое сообщение сможет только владелец закрытого ключа. При шифровании данных для сервера рекомендуется хранить сертификат сервера на Рутокен ЭЦП. Этот сертификат может быть записан на устройство при регистрации пользователя на портале. Для этого следует использовать функцию importCertificate, при этом в качестве параметра category следует передать CERT_CATEGORY_OTHER. Для использования в функции cmsEncrypt нужно получить тело сертификата по его дескриптору с помощью функции getCertificate. При этом дескриптор является уникальным и неизменным и может быть сохранен в учетной записи пользователя на сервере при импорте сертификата сервера. Для того, чтобы использовалось аппаратное шифрование по ГОСТ 28147-89, требуется установить опцию useHardwareEncryption в true. В противном случае будет использована быстрая программная реализация ГОСТ 28147-89. 

Последовательность вызовов приведена на картинке:

 Image Added

Code Block
languagejs
titleШифрование данных на клиенте:
try
{
    var recipientCert = plugin.getCertificate(deviceId, certRecId);        
}
catch (error) 
{
    console.log(error);
}

var options = {};
options.useHardwareEncryption = true;
var cms;

try
{
    cms = plugin.cmsEncrypt(deviceId, certSenderId, recipientCert, data, options);
}
catch (error) 
{
    console.log(error);
}

Перед расшифрованием сообщение нужно обрамить PEM-заголовками "-----BEGIN PKCS7-----" и "-----END PKCS7-----":

Code Block
languagebash
titleРасшифрование данных на сервере
openssl smime -engine gost -decrypt -in message.cms -inform PEM -recip recipient.crt -inkey recipient.key

recipient.crt — сертификат того, для кого зашифровано сообщение, recipient.key — ключ того, для кого зашифровано сообщение.

Расшифрование данных, полученных с сервера, на клиенте

Для расшифрования данных, полученных с сервера, предназначена функция cmsDecrypt. Так как сервер шифрует для клиента, используя его сертификат, то в качестве keyId должен быть передан дескриптор закрытого ключа клиента, соответствующий открытому ключу в сертификате. Этот дескриптор является уникальным и неизменным и потому может быть сохранен в учетной записи пользователя на сервере. Кроме того, дескриптор ключа пользователя может быть получен явным образом, путем вызова функцииgetKeyByCertificate.

Code Block
languagebash
titleШифрование данных на сервере для клиента:
openssl smime -encrypt -engine gost -gost89 -binary -outform PEM -in data.file -out message.enc user.crt 
Code Block
languagejs
titleРасшифрование данных на клиенте:
var data;
var options = {};
try
{
    data = plugin.cmsDecrypt(deviceId, keyId, cms, options);
}
catch (error) 
{
    console.log(error);
}