如何在使用智能卡的Web应用程序(JavaScript)的数字签名?(How to make a d

2019-06-24 08:42发布

我们写了一个文件管理系统,并想进行数字签名使用Web客户端的文件。 我们的Java客户端应用程序已经能够应用并检查数字签名,但我们想作的签名,甚至与我们的网络客户端。 这是写在GWT等,当在客户端运行时,它是一个JavaScript应用程序。

我们不希望创建一个Java小程序并下载客户端并执行它。 我们想用浏览器的安全设备或浏览器API,以签署一份文件。 我们也想保持完整的文档服务器端,并移动到客户端仅在文档哈希值。

我们觉得这应该使用NSSNPAPI / npruntime是可能的,但我们没有发现这方面有任何的信息。 (顺便说一句,是npruntime也可以在IE浏览器?我们是否应该使用ActiveX实现与IE相同的结果?)

你有什么提示吗?

Answer 1:

经过一些谷歌上搜索我找到了答案。 通过其NSS模块的Mozilla的出口部分window.crypto对象。 做这样的操作的更标准的方法是很可能是通过DOMCrypt ,目前正在讨论在W3C 。 谷歌Chrome开发者将等待W3C规范DOMCrypt,而微软需要使用ActiveX对象的按此处的说明 (这与Firefox / Chrome浏览器/歌剧作品甚至在Windows上)。



Answer 2:

目前(2016年5月),这是不可能的。

Chrome浏览器已经降到Java支持。 “视窗边缘”不会有。 IE11支持是坏的,甲骨文决定停止Java插件。 这仅可能与Firefox,旧版本的IE浏览器和Java插件。

新WebCryptographyApi标准规定了浏览器的数字签名支持,但它并没有PCKS#11支持

真正的电子商务电子政务解决方案来解决这个问题:1)安装在用户的PC上的本地Java应用程序。 该应用程序监听端口为上,比如5678 2)在你的页面,javascript中检测是否有小程序3)如果没有支持的支持,连接到应用程序的形式HTTP://127.0.01:5678 /签名 ,并发送数据进行登录。 4)申请本地和使用的操作系统密钥库,其中包括驱动程序PKCS#11,使数字签名和准备,结果5)页面的JavaScript定期查询结果,并准备好当检索它没有任何麻烦



Answer 3:

我曾经参与一个项目这样做与浏览器和本地消息传递:

https://github.com/CACBridge/ChromeCAC

这需要镀铬插件的安装,但在其他方面的伟大工程。 非常适合例如当你知道你需要做的这个时间提前的Intranet /组环境。



Answer 4:

在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);


Answer 5:

现在你可以做到这一点。 基于PKCS#11智能卡或令牌的Web应用程序可以通过使用NCryptoki的Silverlight的版本中实现。 见http://www.ncryptoki.com

你有两个chanches:

1)使用NCryptoki的Silverlight的版本和开发,实现你的逻辑,你的情况下,数字签名,使用PKCS由智能卡提供#11函数自己的Silverlight用户控制

2)使用基于上述的Silverlight版本的jQuery插件,并通过调用PKCS#11函数在JavaScript实现在JavaScript应用程序

此外,您还可以使用NDigitSign的Silverlight的版本(见再次http://www.ncryptoki.com ),做你所需要的,可以在任何Web浏览器来实现。



文章来源: How to make a digital signature in a web application (JavaScript) using a smartcard?