...
Данные сценарии предполагают клиент-серверное взаимодействие, написание клиентских скриптов на JavaScript и соответствующих им серверных вызовов openssl.
Общие операции
Операции с устройством
Поиск подключенных устройств
Любой клиентский сценарий начинается с поиска подключенных к компьютеру USB-устройств Рутокен.Так как все функции Плагина выполняются в отдельных потоках, не заставляя браузер ждать выполнения операций, его интерфейс постороен на промисах. Промисы - это способ организации асинхронного кода. Универсальный метод добавления обработчиков:
Code Block | |||
---|---|---|---|
| |||
var devices = Array();
try
{
devices = plugin.enumerateDevices();
}
catch (error)
{
console.log(error);
} | |||
| |||
promise.then(onFulfilled, onRejected)
// onFulfilled – функция, которая будет вызвана с результатом при успешном выполнении асинхронной функции.
// onRejected – функция, которая будет вызвана с ошибкой при ошибке выполнения асинхроннной функции. |
Операции с устройством
Поиск подключенных устройств
Любой клиентский сценарий начинается с поиска подключенных к компьютеру USB-устройств Рутокен.
Code Block | ||
---|---|---|
| ||
function handleError(reason) {
if (isNaN(reason.message)) {
alert(reason);
} else {
var errorCodes = plugin.errorCodes;
switch (parseInt(reason.message)) {
case errorCodes.PIN_INCORRECT:
alert("Неверный PIN");
break;
default:
alert("Неизвестная ошибка #" + reason.message);
}
}
}
// ...
plugin.enumerateDevices().then(function(devices) {
if (devices.length > 0) {
// ...
} else {
return Promise.reject("Рутокен не обнаружен");
}
}, handleError) |
При этом вызове При этом возвращается список идентификаторов подключенных устройств. Идентификатор представляет собой число, связанное с номером слота, к которому подключено устройство. При повторном перечислении это число может отличаться для одного и того же устройства. число может отличаться для одного и того же устройства.
Стоит заметить, что вызов этот произойдет асинхронно. Первый аргумент метода then, вызывается в случае успешного выполнения Primve enumerateDevices, второй --в случае ошибки. В данном примере был написан обобщенный обработчик ошибок. Его можно расширить и использовать в дальнейшем в своих проектах.
Рутокен Плагин определяет все подключенные к компьютеру USВ-устройства Рутокен ЭЦП Поэтому следующим шагом следует определить тип устройства.
Получение информации об устройстве
...
Code Block | ||||
---|---|---|---|---|
| ||||
var// optionsвызывается = {}; try { метод Promise, который должен вернуть Id устройства .then(function(rutokenHandle){ options={} return plugin.changePin(deviceIdrutokenHandle, "12345678", "1234567112345678", options); } catch (error) .then(function() { alert("PIN console.log(errorизменен успешно"); }, handleError) |
Здесь первым параметром выступает старый PIN-код, а вторым новый PIN-код.
Работа с сертификатами
1. На токене могут храниться 3 категории сертификатов:
...
Code Block | ||||
---|---|---|---|---|
| ||||
var certs = Array(); try { certs = plugin.enumerateCertificates(deviceId, plugin.CERT_CATEGORY_USER); } catch (error) { console.log(error); }// вызывается метод Promise, который должен вернуть Id устройства .then(function(rutokenHandle) { return plugin.enumerateCertificates(rutokenHandle, plugin.CERT_CATEGORY_USER); }) // Подписание данных из текстового поля на первом найденном сертификате .then(function(certs) { if (certs.length > 0) { // ... } else { return Promise.reject("Сертификат на Рутокен не обнаружен"); } }, handleError) |
3. Сертификат можно экспортировать в PEM-формате:
Code Block | ||||
---|---|---|---|---|
| ||||
// вызывается метод Promise, который должен вернуть Id устройства и Id сертификата .then(function(rutokenHandle, certHandle) { returnvar certpem; try { certpem = plugin.getCertificate(deviceIdrutokenHandle, certIdcertHandle); } catch (error) { console.log(error) // Отображение подписанных данных в формате PEM .then(function(pem) { alert(pem); }, handleError) |
Получится примерно такая строка:
...
Code Block | ||||
---|---|---|---|---|
| ||||
var certpem = "-----BEGIN CERTIFICATE----- MIIBmjCCAUegAwIBAgIBATAKBgYqhQMCAgMFADBUMQswCQYDVQQGEwJSVTEPMA0G A1UEBxMGTW9zY293MSIwIAYDVQQKFBlPT08gIkdhcmFudC1QYXJrLVRlbGVjb20i MRAwDgYDVQQDEwdUZXN0IENBMB4XDTE0MTIyMjE2NTEyNVoXDTE1MTIyMjE2NTEy NVowEDEOMAwGA1UEAxMFZmZmZmYwYzAcBgYqhQMCAhMwEgYHKoUDAgIjAQYHKoUD AgIeAQNDAARADKA/O1Zw50PzMpcNkWnW39mAJcTehAhkQ2Vg7bHkIwIdf7zPe2Px HyAr6lH+stqdACK6sFYmkZ58cBjzL0WBwaNEMEIwJQYDVR0lBB4wHAYIKwYBBQUH AwIGCCsGAQUFBwMEBgYpAQEBAQIwCwYDVR0PBAQDAgKkMAwGA1UdEwEB/wQCMAAw CgYGKoUDAgIDBQADQQD5TY55KbwADGKJRK+bwCGZw24sdIyayIX5dn9hrKkNrZsW detWY3KJFylSulykS/dfJ871IT+8dXPU5A7WqG4+ -----END CERTIFICATE-----"; // ... try { // вызывается метод Promise, который должен вернуть Id устройства и Id сертификата .then(function(rutokenHandle, certPem) { return plugin.importCertificate(deviceIdrutokenHandle, certpemcertPem, plugin.CERT_CATEGORY_USER); } catch (error) { console.log(error) // Отображение подписанных данных в формате PEM .then(function() { alert("Сертификат импортирован успешно"); }, handleError) |
6. Вызовом функции deleteCertificate можно удалить сертификат с токена.
Работа с ключевыми парами ГОСТ
1. Для получения декрипторов дескрипторов ключевых пар, хранящихся на устройстве, требуется ввод PIN-кода. Следует понимать, что само значение закрытого ключ получено быть не может, так как ключ является неизвлекаемым.
Code Block | ||
---|---|---|
| ||
var// keysвызывается = Array(); try { plugin.login(deviceId, "12345678"); keys = plugin.enumerateKeys(deviceId, null); } catch (error) { console.log(error); }метод Promise, который должен вернуть Id устройства .then(function(rutokenHandle) { return plugin.enumerateKeys(rutokenHandle, ""); }) .then(function(keys) { if (keys.length > 0) { // ... } else { return Promise.reject("Ключи на Рутокене не обнаружены"); } }, handleError) |
2. Для генерации ключевой пары требуется ввод PIN-кода. При генерации ключа можно задать параметры ключевой пары. Если опция не задана, будут выбраны параметры А для любого из алгоритмов ГОСТ.
...
Code Block | ||||
---|---|---|---|---|
| ||||
var// optionsвызывается = {}; var keyId; try { keyId =метод Promise, который должен вернуть Id устройства .then(function(rutokenHandle) { return plugin.generateKeyPair(deviceIdrutokenHandle, undefined, marker, options); } catch (error) .then(function(keyId) { alert("Ключевая пара console.log(errorсгенерирована успешно"); }, handleError) |
3. С помощью функции deleteKeyPair ключевая пара может быть удалена с токена.
...
Code Block | ||||
---|---|---|---|---|
| ||||
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, recipientCertvar data = "some data" var recipientsCertsInPem = [ "-----BEGIN CERTIFICATE----- MIIBmjCCAUegAwIBAgIBATAKBgYqhQMCAgMFADBUMQswCQYDVQQGEwJSVTEPMA0G A1UEBxMGTW9zY293MSIwIAYDVQQKFBlPT08gIkdhcmFudC1QYXJrLVRlbGVjb20i MRAwDgYDVQQDEwdUZXN0IENBMB4XDTE0MTIyMjE2NTEyNVoXDTE1MTIyMjE2NTEy NVowEDEOMAwGA1UEAxMFZmZmZmYwYzAcBgYqhQMCAhMwEgYHKoUDAgIjAQYHKoUD AgIeAQNDAARADKA/O1Zw50PzMpcNkWnW39mAJcTehAhkQ2Vg7bHkIwIdf7zPe2Px HyAr6lH+stqdACK6sFYmkZ58cBjzL0WBwaNEMEIwJQYDVR0lBB4wHAYIKwYBBQUH AwIGCCsGAQUFBwMEBgYpAQEBAQIwCwYDVR0PBAQDAgKkMAwGA1UdEwEB/wQCMAAw CgYGKoUDAgIDBQADQQD5TY55KbwADGKJRK+bwCGZw24sdIyayIX5dn9hrKkNrZsW detWY3KJFylSulykS/dfJ871IT+8dXPU5A7WqG4+ -----END CERTIFICATE-----" ] // вызывается метод Promise. rutokenHandle, certHandle -- переменные внешней области видимости .then(function (rutokenHandle) { var options = {}; return plugin.cmsEncrypt(rutokenHandle, recipientsCertsInPem, data, options); } catch (error) .then(function(msg) { console.log(error alert(msg); }, handleError) |
Перед расшифрованием сообщение нужно обрамить PEM-заголовками "-----BEGIN PKCS7-----" и "-----END PKCS7-----":
...