Электронная цифровая подпись на сайте при помощи КриптоПро ЭЦП Browser plug-in
Invite pending
В данной статье рассмотрим использование электронно-цифровой подписи на сайте.
Что необходимо, чтобы человек смог использовать электронно-цифровую подпись на сайте?
1) СКЗИ (средство криптографической защиты информации)
Мой опыт работы показывает, что порядка 90% использует КриптоПро CSP (скачать), который в явном или неявном виде продвигают удостоверяющие центры. Порядка 10% VipNet CSP (), который можно использовать бесплатно. С остальными СКЗИ на практике не встречался.
2) КриптоПро ЭЦП Browser plug-in (страница плагина).
3) Установленная подпись (хотя бы одна).
Проверка возможности осуществления подписи
javascript (+jquery)
1) Попытка создать объект cades.
Нужно сделать примечание, что тут и далее, будет деление на браузер с ActiveX(читай IE) и остальные.
Проверка будет осуществляться:
для ActiveX:
Для остальных:
Если проверка прошла неудачно, то уведомляем об этом пользователя.
Стоит иметь ввиду, что после обновления хрома до версии 42 (спасибо статье за информацию) нужно включить:
Следующая проверка — а разрешен ли плагин для запуска (не для IE проверка)?
Где objSign:
Проверяем на СКЗИ путем попытки открыть хранилище.
Проверяем на существование сертификатов в хранилище:
И их количество (бывает, что Certificates есть, но пуст, что нам тоже не подойдет):
Первый шаг сделали — проверили возможность подписания чего-либо.
Выбор электронной цифровой подписи
У клиента может быть установлено несколько сертификатов. Сертификаты могут быть от разных удостоверяющих центров (УЦ), выданными быть разным людям, с разными датами выдачами, поэтому надо предоставить выбор, каким именно он хочется воспользоваться.
1) Группируем по удостоверяющим центрам
Информация об удостоверяющем центре хранится в сертификате.
где certs — сертификаты из хранилища, см выше
Обратите внимание, что, в случае «кривых» сертификатов, вернуться может и undefined, имеет смысл сделать один дефолтный УЦ для таких случаев.
Теперь мы знаем список УЦ, услугами которых воспользовался клиент.
Запоминаем их и выведем через optgroup.
Сам text у option будет таким:
в
в
в
Ну и форматирование даты стандартное:
Еще можно подсветить option.
Зеленым — для работоспособных сертификатов, красным — нет.
Информацию можно получить при помощи самого сертификата.
Стоит отметить, что сама по себе данная проверка имеет малую ценность, ибо все причины не может отсечь.
Но самые базовые, например, проверка даты — проверяет.
В value у option запишем отпечаток
Можно порядковый номер записать, можно другие данные — на ваше усмотрение.
Подписание
Ну и, собственно, самый главный шаг, к которому мы стремились — подписание.
1) Находим выбранный сертификат.
Для нашего примера:
2) Подписываем:
где
Ну а в return возвращается подписанное сообщение.
p.s. По максимуму код постарался вычистить от специфики проекта. Если кому-то этот материал пригодится и будет интересно — напишу и серверную часть. Проверка подписанного сообщения (с цепочкой и без), проверка сертификата (ocsp и без), использования tsp и т.д.
Что необходимо, чтобы человек смог использовать электронно-цифровую подпись на сайте?
1) СКЗИ (средство криптографической защиты информации)
Мой опыт работы показывает, что порядка 90% использует КриптоПро CSP (скачать), который в явном или неявном виде продвигают удостоверяющие центры. Порядка 10% VipNet CSP (), который можно использовать бесплатно. С остальными СКЗИ на практике не встречался.
2) КриптоПро ЭЦП Browser plug-in (страница плагина).
3) Установленная подпись (хотя бы одна).
Проверка возможности осуществления подписи
javascript (+jquery)
1) Попытка создать объект cades.
Нужно сделать примечание, что тут и далее, будет деление на браузер с ActiveX(читай IE) и остальные.
Проверка будет осуществляться:
return ('ActiveXObject' in window);
для ActiveX:
try {
store = new ActiveXObject('CAdESCOM.store');
status = true;
} catch (e) {
status = false;
}
Для остальных:
if (navigator.mimeTypes['application/x-cades']) {
status = true;
} else {
status = false;
}
Если проверка прошла неудачно, то уведомляем об этом пользователя.
Стоит иметь ввиду, что после обновления хрома до версии 42 (спасибо статье за информацию) нужно включить:
chrome://flags/#enable-npapi
Следующая проверка — а разрешен ли плагин для запуска (не для IE проверка)?
try {
store = objSign.CreateObject('CAPICOM.store');
status = true;
} catch (e) {
status = false;
}
Где objSign:
objSign = $('<object/>', {
'id': 'cadesplugin',
'type': 'application/x-cades',
'css': {
'visibility': 'hidden',
'height': '0px',
'width': '0px',
'position': 'absolute'
}
}).appendTo('body').get(0);
Проверяем на СКЗИ путем попытки открыть хранилище.
try {
store.Open();
status = true;
} catch (e) {
status = false;
}
Проверяем на существование сертификатов в хранилище:
if ('Certificates' in store) {
certs = store.Certificates;
}
И их количество (бывает, что Certificates есть, но пуст, что нам тоже не подойдет):
if (certs.Count) {
status = true;
} else {
status = false;
}
Первый шаг сделали — проверили возможность подписания чего-либо.
Выбор электронной цифровой подписи
У клиента может быть установлено несколько сертификатов. Сертификаты могут быть от разных удостоверяющих центров (УЦ), выданными быть разным людям, с разными датами выдачами, поэтому надо предоставить выбор, каким именно он хочется воспользоваться.
1) Группируем по удостоверяющим центрам
Информация об удостоверяющем центре хранится в сертификате.
certs.Item(i).GetInfo(1)
где certs — сертификаты из хранилища, см выше
i
— порядковый номер сертификата от 1 (обратите внимание) до certs.Count.Обратите внимание, что, в случае «кривых» сертификатов, вернуться может и undefined, имеет смысл сделать один дефолтный УЦ для таких случаев.
Теперь мы знаем список УЦ, услугами которых воспользовался клиент.
Запоминаем их и выведем через optgroup.
Сам text у option будет таким:
cert.GetInfo(6) + ' (' + formatDate(cert.ValidFromDate) + ' - ' + formatDate(cert.ValidToDate) + ')'
в
cert.GetInfo(6)
— кому выдан сертификатв
ValidFromDate
— с какого срока сертификат начал/начнет действиев
ValidToDate
— соответственно, до какого срокаНу и форматирование даты стандартное:
function formatDate(d) {
try {
d = new Date(d);
return ('0' + d.getDate()).slice(-2) + '.' + ('0' + (d.getMonth() + 1)).slice(-2) + '.' + d.getFullYear();
} catch (e) {
return '';
}
}
Еще можно подсветить option.
Зеленым — для работоспособных сертификатов, красным — нет.
Информацию можно получить при помощи самого сертификата.
try {
return cert.IsValid().Result;
} catch (e) {
return false;
}
Стоит отметить, что сама по себе данная проверка имеет малую ценность, ибо все причины не может отсечь.
Но самые базовые, например, проверка даты — проверяет.
В value у option запишем отпечаток
cert.Thumbprint
.Можно порядковый номер записать, можно другие данные — на ваше усмотрение.
Подписание
Ну и, собственно, самый главный шаг, к которому мы стремились — подписание.
1) Находим выбранный сертификат.
Для нашего примера:
certs.Find(0, thumbprint).Item(1)
0
— означает, что мы ищем по отпечатку1
— что используем первый результат выборки (по факту единственный)2) Подписываем:
if (isActiveX()) {
var CPSigner = new ActiveXObject('CAdESCOM.CPSigner');
} else {
var CPSigner = objSign.CreateObject('CAdESCOM.CPSigner');
}
CPSigner.Certificate = cert;
if (isActiveX()) {
var SignedData = new ActiveXObject('CAdESCOM.CadesSignedData');
} else {
var SignedData = objSign.CreateObject('CAdESCOM.CadesSignedData');
}
SignedData.Content = text;
return SignedData.SignCades(CPSigner, 1, false);
где
cert
— сертификат, при помощи которого подписываемtext
— собственно, что подписываемНу а в return возвращается подписанное сообщение.
p.s. По максимуму код постарался вычистить от специфики проекта. Если кому-то этот материал пригодится и будет интересно — напишу и серверную часть. Проверка подписанного сообщения (с цепочкой и без), проверка сертификата (ocsp и без), использования tsp и т.д.