Как сделать цифровую подпись в веб-приложении (JavaScript) с помощью смарт-карты?

Мы написали систему управления документами и хотели бы иметь цифровую подпись документов с помощью веб-клиента. Наше клиентское приложение Java уже может применять и проверять цифровую подпись, но мы хотели бы сделать подпись даже с помощью нашего веб-клиента. Это написано на GWT, поэтому при запуске на стороне клиента это приложение JavaScript.

Мы не хотим создавать апплет Java, загружать его на клиент и запускать его. Мы хотели бы использовать устройство безопасности браузера или API браузера для подписи документа. Мы также хотели бы сохранить всю серверную часть документа и перенести на клиента только хеш документа.

Мы считаем, что это возможно, используя NSS или NPAPI / npruntime, но мы не нашли никакой информации об этом. (Кстати, npruntime доступен и в IE? Должны ли мы использовать ActiveX для достижения того же результата с IE?)

У тебя есть намеки?

Ответы на вопрос(5)

http: //en.wikipedia.org/wiki/CAPICO без каких-либо сторонних 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);
 Yablargo07 нояб. 2016 г., 18:04
Только иногда, если он «испорчен» - я закрываю браузер, открываю, и он запрашивает учетные данные. Я иногда получаю точку, когда он перестает спрашивать, но перезагрузка браузера всегда, кажется, исправляет это.
 SeaSide04 нояб. 2016 г., 13:30
Я также использую CAPICOM для подписи xml знаком X509Certificate2. Когда я выбираю сертификат в магазине, он не просит меня ввести имя пользователя и пароль для этого сертификата. Это та же самая ситуация и с вашим кодом выше?

с которым я был связан, сделал это с помощью Chrome и Native Messaging:

https: //github.com/CACBridge/ChromeCA

Это требует установки подключаемого модуля Chrome, но в остальном прекрасно работает. Идеально подходит, например, для Интранет / групповые среды, в которых вы знаете, что вам нужно будет сделать это заранее.

токенов PKCS # 11 может быть реализовано с помощью версии Silverlight NCryptoki. Видетьhttp: //www.ncryptoki.co

У тебя есть две возможности:

1) с помощью версии NCryptoki для Silverlight и разработки собственного пользовательского элемента управления Silverlight, который реализует вашу логику (цифровую подпись в вашем случае) с использованием функций PKCS # 11, предоставляемых смарт-картой

2) используя плагин JQuery на основе вышеуказанной версии Silverlight и реализуйте свое приложение в JavaScript, вызывая функции PKCS # 11 в JavaScript

Кроме того, вы можете использовать версию Silverlight NDigitSign (см. Сноваhttp: //www.ncryptoki.co), который делает все, что вам нужно, и может быть реализован в любом веб-браузере.

 eppesuig19 окт. 2013 г., 21:51
Спасибо за указание на это решение. Я не знал о проекте ncryptoki, но, поскольку он основан на Silverlight, он все еще требует установки программного обеспечения на клиентский компьютер (как для java-апплета), и, что более важно, он, вероятно, будет работать только на машинах Windows. Наконец, для этого потребуется написать приложение, которое напрямую использует PKCS # 11, и я действительно хотел бы избежать такой программы.
Решение Вопроса

его модуля NSS через Window.crypto объект. Более стандартный способ сделать такую операцию, вероятно, через DOMCrypt, это в настоящее время дискуссии в W3C. Разработчик Google Chrome будет ждать W3C для стандартизации DOMCrypt, в то время как Microsoft требует использования объекта Active как объяснил здесь (это работает даже с Firefox / Chrome / Opera в Windows).

 ares27 мая 2015 г., 13:16
DOMCrypt ссылка не та, что должна быть.
 marcellorvalle27 окт. 2015 г., 18:32
window.crypto не было Удален после Firefox 33?
 eppesuig28 мая 2015 г., 09:54
Thanks @ares, DNS DOMcrypt.org, похоже, теперь назначен другому владельцу. Я изменил ссылку на другую страницу с очень похожим содержанием.

Chrome прекратил поддержку Java. «Края окон» не будет. Поддержка IE11 плохая, и Oracle решила прекратить плагин Java. Это было бы возможно только с Firefox, старыми версиями IE и плагином Java.

Новый стандарт WebCryptographyApi обеспечивает поддержку цифровой подписи для браузеров, но не поддерживает pcks # 11

Реальное решение для электронного правительства, чтобы решить эту проблему: 1) Установите локальное приложение Java на ПК пользователя. Приложение прослушивает порт как, например, 5678 2) На вашей странице javascript определяет наличие поддержки апплетов. 3) Если поддержки нет, подключается к приложению в формеhttp: //127.0.01: 5678 / знак и отправляет данные на подпись. 4) Приложение является локальным и не имеет проблем с использованием хранилища ключей операционной системы, которое включает драйверы PKCS # 11. Создайте цифровую подпись и подготовьте результат. 5) Страница javascript периодически запрашивает результат и извлекает его, когда готово

 pedrofb25 мая 2016 г., 09:48
В Испании есть решение для электронного правительства, чтобы решить эту проблему. Я задокументирую это в ответе
 Eugene Mayevski 'Allied Bits25 мая 2016 г., 08:32
пплеты @Java могут быть запущены через Java Web Start. Это работает во всех настольных браузерах, хотя требуются дополнительные усилия.

Ваш ответ на вопрос