Page tree

Versions Compared

Key

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

...

Данные сценарии предполагают клиент-серверное взаимодействие, написание клиентских скриптов на JavaScript и соответствующих им серверных вызовов openssl.

Общие операции

Операции с устройством

Поиск подключенных устройств

Любой клиентский сценарий начинается с поиска подключенных к компьютеру USB-устройств Рутокен.Так как все функции Плагина выполняются в отдельных потоках, не заставляя браузер ждать выполнения операций, его интерфейс постороен на промисах. Промисы - это способ организации асинхронного кода. Универсальный метод добавления обработчиков:

Code Block
languagejs
var devices = Array();

try 
{
    devices = plugin.enumerateDevices();
}
catch (error) 
{
    console.log(error);
}

...

titleДобавление Promise обработчика
promise.then(onFulfilled, onRejected)
// onFulfilled – функция, которая будет вызвана с результатом при успешном выполнении асинхронной функции.
// onRejected – функция, которая будет вызвана с ошибкой при ошибке выполнения асинхроннной функции.

Операции с устройством

Поиск подключенных устройств

Любой клиентский сценарий начинается с поиска подключенных к компьютеру USB-устройств Рутокен.

Code Block
languagejs
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
languagejs
titleПример смены PIN-кода на устройстве:
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
languagejs
titleПример чтения пользовательских сертификатов с устройства:
 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-формате:

var certpem; try { certpem =
Code Block
languagejs
js
// вызывается метод Promise, который должен вернуть Id устройства и Id сертификата
.then(function(rutokenHandle, certHandle) {
	return plugin.getCertificate(deviceIdrutokenHandle, certIdcertHandle);
}
catch (error) 
{
    console.log(error)
// Отображение подписанных данных в формате PEM
.then(function(pem) {
	alert(pem);
}, handleError)

Получится примерно такая строка:

...

Code Block
languagejs
titleПример записи сертификата на устройство как пользовательского:
 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
languagejs
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
languagejs
titleПример генерации ключевой пары ГОСТ Р 34.10-2012:
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
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, 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-----":

...