9

我们编写了一个文档管理系统,并希望使用 Web 客户端对文档进行数字签名。我们的 Java 客户端应用程序已经能够应用和检查数字签名,但我们希望即使使用我们的 Web 客户端也可以进行签名。这是用 GWT 编写的,因此在客户端运行时,它是一个 JavaScript 应用程序。

我们不想创建一个 Java 小程序并将其下载到客户端并执行它。我们想使用浏览器安全设备或浏览器 API 来签署文件。我们还想保留完整的文档服务器端,并仅将文档哈希转移到客户端。

我们认为使用NSSnpapi/npruntime应该可以做到这一点,但我们没有找到任何有关此的信息。(顺便说一句,npruntime 在 IE 中也可用吗?我们应该使用 ActiveX 来实现与 IE 相同的结果吗?)

你有什么提示吗?

4

5 回答 5

9

经过一番谷歌搜索后,我找到了答案。Mozilla 通过window.crypto对象导出其 NSS 模块的一部分。执行此类操作的更标准方法可能是通过DOMCrypt,目前 W3C 中正在讨论该方法。Google Chrome 开发人员将等待 W3C 标准化 DOMCrypt,而 Microsoft 需要使用 ActiveX 对象,如此处所述(这甚至适用于 Windows 上的 Firefox/Chrome/Opera)。

于 2012-05-12T05:27:54.673 回答
5

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

Chrome 已放弃对 Java 的支持。'Windows edge' 不会有。IE11 支持不好,Oracle 决定停止使用 java 插件。只有 Firefox、旧版本的 IE 和 Java 插件才有可能。

新的 WebCryptographyApi 标准为浏览器提供数字签名支持,但不支持 pcks#11

解决此问题的真正电子政务解决方案: 1) 在用户 PC 上安装本地 Java 应用程序。应用程序侦听端口,例如 5678 2) 在您的页面中,javascript 检测是否支持小程序 3) 如果不支持,则以 http://127.0.01:5678/的形式连接到应用程序签名并将数据发送给签名。4) 应用程序是本地的,使用操作系统密钥库没有问题,其中包括驱动程序 PKCS #11。进行数字签名并准备结果 5) 页面 javascript 定期查询结果并在准备好时检索它

于 2016-05-24T18:23:32.240 回答
0

在 Win/IE 中,您仍然可以在没有任何第三方 ActiveX 或外部库的情况下使用 CAPICOM http://en.wikipedia.org/wiki/CAPICOM 。
这适用于安装 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);
于 2013-07-01T16:26:02.710 回答
0

我参与的一个项目是使用 Chrome 和 Native Messaging 完成的:

https://github.com/CACBridge/ChromeCAC

这需要安装 chrome 插件,否则效果很好。非常适合例如您知道需要提前执行此操作的 Intranet/Group 环境。

于 2016-11-07T17:06:19.803 回答
-1

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

你有两个chanches:

1) 使用 NCryptoki 的 Silverlight 版本并使用智能卡提供的 PKCS#11 函数开发您自己的 Silverlight 用户控件,该控件实现您的逻辑,在您的情况下为数字签名

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

此外,您可以使用 NDigitSign 的 Silverlight 版本(参见http://www.ncryptoki.com),它可以满足您的所有需求,并且可以在任何 Web 浏览器中实现。

于 2013-10-19T15:17:40.400 回答