从通用浏览器访问智能卡的架构?或者:如何弥合从浏览器到PC / SC堆栈的差距?

时间:2013-04-04 09:14:19

标签: cross-browser smartcard pcsc

从通用浏览器(通过http(s)连接到服务器),最好是从Javascript访问本地智能卡的可能的客户端架构有哪些,最终用户的安装麻烦最少?服务器需要能够至少向卡发出其选择的APDU(或者可能将其中的一部分委托给它生成的客户端代码)。我假设在工作PC / SC堆栈的客户端可用,配有智能卡读卡器。自XP,现代OS X和Unix以来,至少在Windows上这是一个合理的假设。

到目前为止,我确定了以下选项:

  1. 一些自定义ActiveX。这就是我现有的应用程序所使用的(我们在内部开发),一旦获得安装ActiveX的许可,对IE的客户来说很容易部署,但它与“通用浏览器”要求不匹配。
    更新:ActiveX主要由弃用的IE支持,包括IE11;但不是边缘。
  2. 使用Netscape Plugin API的一些PC / SC浏览器扩展,这似乎是上面的平滑扩展。我找到的唯一现成品是SConnect,但似乎barely alive,其API documentation (webarchive)已不再正式提供,并且与特定的智能卡供应商有很强的联系。原则可能很好,但为每个平台制作这样的插件将是很多工作。
    更新:许多浏览器都删除了NPAPI支持,包括Chrome和Firefox。
  3. 一个Java Applet,运行在Oracle的JVM(1.)6或更高版本之上,随javax.smartcardio一起提供。从功能的角度来看,这很好,有很好的记录,我可以忍受一些已知的错误,但我担心接受Java-as-a-browser-extension会产生不可抗拒的向下螺旋。
  4. 还有其他想法吗?

    另外:是否有某种方法可以防止恶意服务器滥用浏览器所拥有的任何PC / SC接口(例如,提供3个错误的PIN来阻止卡片,只是为了它的肮脏;或者制造一些更邪恶的东西)。

12 个答案:

答案 0 :(得分:24)

事实上,除了建立SSL之外,浏览器不能将(加密)智能卡用于其他目的。

需要由浏览器执行的其他代码来访问智能卡。

有几十个自定义和专有插件(使用你提到的所有三个选项)用于各种目的(签名是最受欢迎的,我猜),因为没有标准或普遍接受的方式,至少在欧洲和我'我也确定其他地方。

创建,分发和维护自己应该是​​一个爆炸性的,因为浏览器每个月左右发布一次,每个新版本都会更改用户界面技巧,所以你可能需要经常调整你的代码。

你可能希望拥有GUI功能,至少是要求用户允许访问卡或其中的某些功能。

要创建多平台,多浏览器插件,可以使用类似firebreath的内容。

就个人而言,我不认为将PC / SC暴露在网络上是好事。 PC / SC本质上是一个低级协议,当暴露这个时,您也可以公开对磁盘的块级访问,并希望“Web上的应用程序只是我的,并且它们表现良好”(这应该回答你的“同时“)。同时像SConnect这样的瘦补丁是最容易创建的,用于提供javscript plugin.sendAPDU()样式代码(或者只是包装所有PC / SC API并让javascript调用者处理相同级别的细节与本机PC / SC API用例一样)。

为此目的创建插件通常由急剧的当前缺陷驱动。

解决未来(移动等)是另一个故事,像W3C webcrypto和OpenMobile API这样的东西最终可能会以某种方式创建将客户端密钥容器暴露给Web应用程序的东西。如果您的智能卡目标是加密,我的建议是避免PC / SC并使用平台服务(Windows上的CryptoAPI,OSX上的Keychain,Linux上的PKCS#11)

任何类型的设计都有要求。如果您考虑使用而不是任意APDU,则这一切都适用。如果您的要求是发送任意APDU,请创建一个插件,然后继续使用它。

答案 1 :(得分:22)

更新(8/2016):正在讨论一种名为 WebUSB API 的新API。你可以already use it with Chrome v54+

此标准将在所有主流浏览器中实施,并将取代对Smard卡的第三方应用程序或扩展的需求: - )

所以新答案是肯定的!

类似OSI的架构堆栈是:

注意: Google在2017年宣布他们为will abandon Chrome Apps

上一页

现在(2015年),您可以使用chrome.usb API创建Google Chrome应用。

然后通过其CCID-compliant界面访问智能卡读卡器。

它不是跨浏览器,而是JavaScript可编程的&跨平台。

无论如何,现代浏览器不再支持Netscape Plugin API(NPAPI)。浏览器供应商正在驳斥Java小程序。

答案 2 :(得分:7)

我刚刚发布了一个解决此问题的beta插件。 此测试版代码可在此处获取:

https://github.com/ubinity/webpcsc-firebreath

此插件基于firebreath框架,并已在Linux / WinXP / Win7下使用Fireofx和Chrome进行了beta测试。提供源代码和扩展包。

基本思想是提供PCSLite API访问,然后在此基础上开发更友好的JS-api。

此插件正在积极开发中,因此请随时发送任何报告和请求。

答案 3 :(得分:4)

对于您的第一个问题,我几乎没有希望:要么您对智能卡功能的一小部分(如签署电子邮件或PDF)感到满意,那么您可以使用一些现成的软件(如PKCS),理想情况下由智能卡公司维护,或者您需要更广泛的功能,并需要为自己投入相当大的精力。当然,PCSC是选择的起点。

至少对你的“也:”有一些希望。

1)注意,某些规范(例如ICAO /德国BSI TR-3110)请求一种方法,其中PIN未被阻止,但是一旦错误计数器在回复之前命中1,则使用大量时间。必须使用不同的命令启用最终尝试,否则不会进行进一步的比较和错误计数器调整。

2)通过要求安全消息传递,只需保护Verify命令。敏感应用程序对所有内容使用安全消息传递,因此第一步取消会话密钥,第二步应用于所有后续命令和响应。结果是,在完成错误计数器的比较或修改之前,该命令由于不正确的MAC而被拒绝。

答案 4 :(得分:4)

还有另一个类似于http://github.com/cardid/WebCard提供的@cslashm提议的浏览器插件。也是开源的,可以根据原始问题的要求安装“最小安装麻烦”。您可以查看使用访问http://plugin.cardid.org

的示例

WebCard已在IE 8至11,Windows中的Chrome和Firefox以及Mac OS X中的Chrome和Safari中进行了测试。由于它只是PC / SC的包装,因此需要在Mac OS X中安装来自{的SmartCard服务{3}}

答案 5 :(得分:2)

由于chrome和firefox将停止NPAPI插件的支持,没有安全的解决方案可用于维护智能卡读取的会话而不是你的证书卡支持相互ssl,我回答了类似的问题{ {3}},这可能会有所帮助

答案 6 :(得分:1)

它很脏,但是如果在客户端机器上安装桥接守护程序/服务是可接受的/可行的,那么你可以编写一个本地桥接服务(例如在python / pyscard中),通过REST接口公开智能卡,然后浏览器中的javascript,介于该本地服务(外观)和远程服务器API之间。

答案 7 :(得分:1)

说到Chrome,您现在可以使用Google提供的Smart Card Connector app捆绑PC / SC-Lite端口和通用CCID驱动程序。

应用程序本身可以通过之前评论者提到的chrome.usb API进行操作。

因此,不是重写整个堆栈(从最低级别 - 原始USB开始),现在开发人员可以只编写在PC / SC API之上工作的部分 - 这是由Connector应用程序公开的。

答案 8 :(得分:0)

客户端,客户端,客户端插件... .. JSApis .. 好.. 我们知道这一点:所有浏览器在与Apache或IIS服务器通信时,实际上需要在需要https / SSL握手过程时签署“某事”。

例如,典型的Apache配置如下:

SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +FakeBasicAuth +StdEnvVars +ExportCertData +OptRenegotiate

启动密码键盘弹出,用户必须插入智能卡引脚才能继续。

好吧,我的想法是:为什么不转向服务器,并调整那种行为,以便在初始化握手时上传一些字节流来签名?

答案 9 :(得分:0)

我有一个设置,扫描智能卡读卡器以登录用户。 PC / SC库在桌面上运行良好。有人提到要使用 Emscripten(https://github.com/kripken/emscripten)编译器,它将c ++编译成JavaScript代码。但这并没有奏效,因为PC / SC使用的某些功能只能在服务器端使用。 经过多方研究。我终于放弃了客户端解决方案,Chrome web usb API也无法识别读者 然后,我决定尝试使用signalR,并在连接到智能卡读卡器的PC上设置一个集线器,这种方法非常好。

答案 10 :(得分:0)

使用浏览器扩展程序访问智能卡或USB令牌

Java applet,Active X等已被淘汰,或者正在从新的Modern Browsers中淘汰。近年来,有关WebCrypto API的讨论很多,但到目前为止,WebCrypto API不能提供对(Windows)或任何其他密钥存储区或本地加密USB /智能卡设备的访问。

对于使用Digital Signature和PDF或eReturn签名从浏览器进行身份验证,可以使用其中一种免费的Chrome扩展程序是Signer.Digital chrome扩展程序。可以从https://signer.digital/downloads/Signer.Digital.Chrome.Host.Setup.zip下载本地系统(在Windows的chrome浏览器上运行的主机) 安装此主机并重新启动Chrome会自动添加Signer.Digital Chrome Extension

此扩展程序的实际工作如图here

所示。

测试步骤:

  1. 为USB令牌或智能卡安装设备驱动程序-这将使您的证书在Windows证书存储区中

  2. 上面显示的安装设置。

  3. 重新启动Chrome浏览器。

  4. 打开this link

  5. 输入用户名和密码,然后单击注册按钮-这将要求选择“数字签名”并在服务器上注册(仅对于此会话-不是永久的)。

  6. 然后再次输入相同的用户ID和密码,并选择相同的证书,然后单击登录。选择其他证书将不允许登录。

从扩展名调用方法的JavaScript

要在服务器上注册证书:

//Get Selected Certificate Information 
SignerDigital.getSelectedCertificate()
    .then(
        function (CertInfo) {        
    //Success returns Certificate Subject and Thumbprint
        },
            function (errmsg) {
                //Send errmsg to server or display the result in browser.
              }
     );

使用数字签名进行身份验证或登录:

SignerDigital.signAuthToken(authToken, "SHA-256")       //or "SHA256"
    .then(
        function (SignData) {        //Success returns Signed Auth Token
        },
            function (errmsg) {
                //Send errmsg to server or display the result in browser.
              }
     );

要签署PDF:

    //Calculate Sign for the Hash by Calling function from Extension SignerDigital
    SignerDigital.signPdfHash(hash, $("#CertThumbPrint").val(), "SHA-256")      //or "SHA256"
     .then(
            function (signDataResp) {
              //Send signDataResp to Server
        },
            function (errmsg) {
                //Send errmsg to server or display the result in browser.
              }
     );

如果失败:,则返回错误消息,以“ SDHost错误:”开头

答案 11 :(得分:0)

此问题的另一种解决方案称为FortifyApp,您可以了解其工作原理here

TL; DR;它是一个可在OSX,Windows和Linux上运行的客户端可安装应用程序,该应用程序通过Web加密polyfill公开智能卡,还可以提供对其他证书/密钥存储的访问。