Как сделать цифровую подпись в веб-приложении (JavaScript) с помощью смарт-карты?
Мы написали систему управления документами и хотели бы иметь цифровую подпись документов с помощью веб-клиента. Наше клиентское приложение Java уже может применять и проверять цифровую подпись, но мы хотели бы сделать подпись даже с помощью нашего веб-клиента. Это написано в GWT, поэтому при запуске на стороне клиента это приложение JavaScript.
Мы не хотим создавать апплет Java, загружать его на клиент и запускать его. Мы хотели бы использовать устройство безопасности браузера или API браузера для подписи документа. Мы также хотели бы сохранить всю серверную часть документа и перенести на клиент только хэш документа.
Мы считаем, что это возможно с помощью NSS или npapi / npruntime, но мы не нашли никакой информации об этом. (Кстати, npruntime доступен и в IE? Должны ли мы использовать ActiveX для достижения того же результата с IE?)
У вас есть какие-нибудь намеки?
5 ответов
После еще нескольких поисков я нашел ответ. Mozilla экспортирует часть своего NSS-модуля через объект window.crypto. Более стандартный способ выполнения такой операции, вероятно, через DOMCrypt, который в настоящее время обсуждается в W3C. Разработчик Google Chrome будет ждать, пока W3C стандартизирует DOMCrypt, в то время как Microsoft требует использования объекта ActiveX, как описано здесь (это работает даже с Firefox/Chrome/Opera в Windows).
В настоящее время (май 2016 г.) это невозможно.
Chrome прекратил поддержку Java. "Края окон" не будет. Поддержка IE11 плохая, и Oracle решила прекратить плагин Java. Это было бы возможно только с Firefox, старыми версиями IE и плагином Java.
Новый стандарт WebCryptographyApi обеспечивает поддержку цифровой подписи для браузеров, но не поддерживает pcks#11
Реальное решение электронного правительства для решения этой проблемы: 1) Установите локальное приложение Java на ПК пользователя. Приложение прослушивает порт как, например, 5678 2) На вашей странице javascript определяет наличие поддержки апплетов. 3) Если поддержка отсутствует, подключается к приложению в виде http://127.0.0.1:5678/sign и отправить данные для подписи. 4) Приложение является локальным и не имеет проблем с использованием хранилища ключей операционной системы, которое включает в себя драйверы PKCS # 11. Создайте цифровую подпись и подготовьте результат. 5) Страница javascript периодически запрашивает результат и извлекает его по мере готовности.
В Win/IE вы все еще можете использовать CAPICOM http://en.wikipedia.org/wiki/CAPICOM без каких-либо сторонних ActiveX или внешних библиотек.
Это работает везде, где установлен IE.
Это удаляется однако.
Ниже приводится то, что я использую для входа в IE. Я называю это, например: var signature = signDigest(stringToBeSigned);
function signDigest(text) {
if (window.event)
window.event.cancelBubble = true;
var dest = sign(text); //TODO
return dest;
}
// CAPICOM constants
var CAPICOM_STORE_OPEN_READ_ONLY = 0;
var CAPICOM_CURRENT_USER_STORE = 2;
var CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
var CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
var CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
var CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
var CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
var CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
var CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
var CAPICOM_ENCODE_BASE64 = 0;
var CAPICOM_E_CANCELLED = -2138568446;
var CERT_KEY_SPEC_PROP_ID = 6;
function IsCAPICOMInstalled() {
if (typeof (oCAPICOM) == "object") {
if ((oCAPICOM.object != null)) {
// We found CAPICOM!
return true;
}
}
}
function FindCertificateByHash() {
try {
// instantiate the CAPICOM objects
var MyStore = new ActiveXObject("CAPICOM.Store");
// open the current users personal certificate store
MyStore.Open(CAPICOM_CURRENT_USER_STORE, "My", CAPICOM_STORE_OPEN_READ_ONLY);
// find all of the certificates that have the specified hash
var FilteredCertificates = MyStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, strUserCertigicateThumbprint);
var Signer = new ActiveXObject("CAPICOM.Signer");
Signer.Certificate = FilteredCertificates.Item(1);
return Signer;
// Clean Up
MyStore = null;
FilteredCertificates = null;
}
catch (e) {
if (e.number != CAPICOM_E_CANCELLED) {
return new ActiveXObject("CAPICOM.Signer");
}
}
}
function sign(src) {
if (window.crypto && window.crypto.signText)
return sign_NS(src);
else
return sign_IE(src);
}
function sign_NS(src) {
var s = crypto.signText(src, "ask");
return s;
}
function sign_IE(src) {
try {
// instantiate the CAPICOM objects
var SignedData = new ActiveXObject("CAPICOM.SignedData");
var TimeAttribute = new ActiveXObject("CAPICOM.Attribute");
// Set the data that we want to sign
SignedData.Content = src;
var Signer = FindCertificateByHash();
// Set the time in which we are applying the signature
var Today = new Date();
TimeAttribute.Name = CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
TimeAttribute.Value = Today.getVarDate();
Today = null;
Signer.AuthenticatedAttributes.Add(TimeAttribute);
// Do the Sign operation
var szSignature = SignedData.Sign(Signer, true, CAPICOM_ENCODE_BASE64);
return szSignature;
}
catch (e) {
if (e.number != CAPICOM_E_CANCELLED) {
alert("An error occurred when attempting to sign the content, the error was: " + e.description);
}
}
return "";
}
У меня были некоторые проблемы с кодировкой и т. Д., Поэтому я также включил свой контроллер (.net)
byte[] decbuff = Convert.FromBase64String(signature);
//CAPICOM USES 16 BIT ENCODING
Encoding utf16Enc = Encoding.GetEncoding("UTF-16LE");
byte[] utf16Data = utf16Enc.GetBytes(getContent);
ContentInfo content = new ContentInfo(utf16Data);
System.Security.Cryptography.Pkcs.SignedCms cms = new System.Security.Cryptography.Pkcs.SignedCms(content,true);
cms.Decode(decbuff);
int length = decbuff.Length;
X509Certificate2 cert = cms.SignerInfos[0].Certificate;
X509Chain chain = new X509Chain();
bool theVal = chain.Build(cert);
cms.CheckHash();
cms.CheckSignature(false);
Один проект, с которым я был связан, сделал это с Chrome и Native Messaging:
https://github.com/CACBridge/ChromeCAC
Это требует установки плагина chrome, но в остальном работает отлично. Идеально подходит, например, для интранет / групповых сред, где вы знаете, что вам нужно сделать это заранее.
Теперь вы можете сделать это. Веб-приложение на основе смарт-карт или токенов PKCS#11 может быть реализовано с помощью версии Silverlight NCryptoki. Смотрите http://www.ncryptoki.com/
У вас есть две возможности:
1) используя версию NCryptoki для Silverlight и разработайте собственный пользовательский элемент управления Silverlight, который реализует вашу логику, цифровую подпись в вашем случае, используя функции PKCS#11, предоставляемые смарт-картой
2) используя плагин JQuery на основе вышеуказанной версии Silverlight и реализуйте свое приложение на JavaScript, вызывая функции PKCS#11 на JavaScript
Кроме того, вы можете использовать версию Silverlight NDigitSign (см. Снова http://www.ncryptoki.com/), которая делает все необходимое и может быть реализована в любом веб-браузере.