本页主题: Web系统中文档的数字签名问题 打印 | 加为IE收藏 | 复制链接 | 收藏主题 | 上一主题 | 下一主题

Mike
群熵工程师
级别: 管理员


精华: 7
发帖: 951
威望: 714 点
金钱: 6601 RMB
贡献值: 0 点
好评度: 611 点
在线时间:1405(小时)
注册时间:2003-11-28
最后登录:2018-04-23

 Web系统中文档的数字签名问题

作者: Svetlin Nakov 著 陈娇娇 翻译

假设我们正在开发一个信息系统,这个系统拥有基于Web的用户界面,通过因特网我们可以使用这个界面。这个系统的用户必须能够发送文档到服务器。而且这些文档可以是不同格式的文件——MS Word .DOC 文件、Adobe Acrobat .PDF 文件、MS Excel .XLS 文件、JPEG和GIF图像、文本文件等等。为了追踪发送者的标记并且保证没有人在他们发送之后修改文档,系统有必要为用户提供数字签名发送的文件。让我们讨论一下在实现这种系统的过程中所产生的问题。

公匙加密方法

为了数字签名的需要,系统可以使用公匙加密算法,并且为了校验签名该文档的用户的标记,使用数字证书是最方便的。

使用自签发证书

证书可以是自签发的(self-signed ),或者是由认证机构颁发的。如果用户给自己颁发自签发的证书并且是用它们来签名文档,那就不能保证某些恶意用户不给自己颁发另一个名字的证书并且即使它是其他用户他也能签名文档。我们应该找到更好的方法来避免这个安全漏洞。

使用本地认证机构

负责系统维护的人——系统管理员——发行数字证书,这是有可能的。有两种方法可以做这件事——要么系统管理员为用户生成公匙和私匙,要么他们自己生成。在第一种情况下很有可能系统管理员会滥用职权。保留用户亲自生成他们的公匙和私匙的可能性,在他们发送公匙和有关他们标记的信息给系统管理员之后,系统管理员相应的颁发证书。这种设计的缺陷就是无法保证用户不伪造它们的标记信息。唯一可做的就是每个用户亲自提交他的公匙并且管理员在仔细检查他的ID证件后才给他颁发证书。这种方案要更加可行一些,但是实际上管理员充当了认证机构的角色,并且他仍然能够滥用他的证书颁发权利。

使用许可的认证机构

为了管理证书的问题,我们可以使用许可的认证机构的服务。系统中的每个用户可以从认证机构处购买证书,并且认证机构能够保证证书确实属于他所颁发的用户。对应于任何证书的私匙只有他的所有者才能使用,其他人不能。这就保证了当用户使用许可的认证机构颁发的证书签名文档时,确实是他的签名。只有在恶意用户获得其他用户的私匙时才有可能伪造,而用户是要为私匙承担个人责任的。

数字证书购买对于每个用户来说都有一定的费用,但是这是保证安全性的唯一可靠方法。通常除了证书之外,用户还会获得一个PFX文件,这个文件包含证书以及对应的私匙,私匙受密码保护。如果购买的结果是认证机构直接安装证书到客户端的Web浏览器上,那么用户就能够将它扩展成一个PFX文件(采用PKCS#12 的格式)并且从安装的那一刻起就可以用它来签名文档。我们假定拥有他们自己证书的用户也拥有受保护的密码存储(PFX文件),该密码存储保存着他们的私匙以及他们的证书。

只在客户端的设备上签名是可能的

签名需要访问签名用户的私匙。因为每个用户的私匙只有他自己才能访问的道,所以有必要让签名在他的PC上进行。否则用户就不得不发送他的私匙给服务器,这就面临着一个潜在的安全危险——密码可能在途中被盗。在用户的PC上对Web应用中的文档进行签名不是一件容易的事情,因为在他的配置中客户端只有一个标准的Web浏览器——他没有为签名文档配置内建的功能。

在客户端的设备上数字签名的方法

我们将分析在客户端的PC上签名文档的可能方法。我们还要考虑将签名过程与负责接收签过名的文档的Web 应用集成。

使用外部签名工具

一种可能的方法就是使用户在他们的PC上安装某些专门设计的软件,但是这个有一定的困难。一个就是签名软件必须有支持用户使用的不同操作系统的不同版本。而且,对这种软件做支持是很笨重的,因为对它的任何修改都会迫使用户下载和安装新版本。与系统的Web接口集成也是一件困难的任务,并且如果软件安装不好的话,用户用起来就会有麻烦。用户不想在他们的PC上安装该软件还有一个可能原因就是安全性,而且如果他们不使用它们自己的设备,他们就无法使用外部签名工具。

上述原因使得我们不得不寻找另外一条解决在客户端的设备上数字签名问题的方法。

使用客户端脚本技术

使用JavaScript或者其他客户端脚本技术,如ActiveX、 Macromedia Flash、.NET Windows Forms Controls 或者 Java-applets,是可行的。

JavaScript语言的问题就是他并不支持处理数字签名和证书所需的标准功能。除了他不能获得到安装在用户的Web浏览器上的证书的访问之外,他还不能访问外部的受保护的密码存储。而且JavaScript还不能访问本地的文件系统,从而不能读取应该被签名的文件。

Macromedia Flash 技术也不支持数字签名和证书,而且它不能访问本地的文件系统,而这是必须的,因为在签名之前,文件必须读取。

从技术上来说,ActiveX controls 提供了一个解决方案,但是他们只能作用于Microsoft Windows 上的Internet Explorer。意外地,除了IE之外一些其他的浏览器也支持ActiveX controls,但是ActiveX技术不能在非微软的操作系统上运行。这就将用户限制在那些使用MS Windows和IE的用户群之中。

Windows Forms Controls 也只能作用于IE,并且它们还需要额外安装Microsoft .NET Framework。要求用户为了能够签名Web应用中的文档就使用IE、MS Windows 和.NET Framework,这是不能接受的。

最后一个方案就是使用Java applets。他们的优点是他们能够作用于所有知名的浏览器,也能运行在所有的操作系统上。缺点就是他们不能访问他们正在运行的设备上的本地文件系统,但是使用签名的Java applets可以克服这个缺陷。我们来看看Java applets究竟能给我们提供 什么。

Java Applets

Java applets 可编译成Java 程序,这个程序可作为对象嵌入到HTML文档中,并且浏览该文档时可被Web浏览器执行。嵌入applet到Web页中与嵌入图片非常相似,不同的是applets 不仅仅是图形图像。他们是为他们的图形用户界面使用它们所在页面的整个矩形区域的程序。

Applets包含一个(或者几个)编译的Java 类,这些类保存在JAR文件中。与所有的Java程序一样,applets可被Java Virtual Machine (JVM) 执行,因此所有的Java激活的Web浏览器都有虚拟设备,这些虚拟设备要么内建,要么另外安装。当包含applet 的HTML 文档被打开时,浏览器装载它的虚拟设备并在其里面启动该applet。为了保证用户的安全性, applets不允许执行可能访问运行该applet的设备上的用户信息的操作。 通常applet不能访问本地文件系统,这使得为数字签名的目的而使用该技术变得有点困难。

签名的 Java Applets

签名的Java Applets 为增强正规的applets 许可提供了一个机制。与所有其他的applets 一样,他们提供了JAR档案,这个档案包含一组编译的Java 类,但是除了这些之外他们还包含所有这些类的数字签名以及数字证书(连同它完整的认证链一起),通过数字证书可以校验这些签名。在签名的applet的执行之上,Web浏览器还显示来自用来签名applet的证书的信息,并且询问用户它是否相信该证书。如果用户信任它,applet无条件执行并且可以自由的完全访问他运行所在设备的本地文件系统。信任由未知软件开发商签名的applet,或者证书没有得到校验就签名的applet是非常危险的,因为这些applet可以获得对设备的自由访问并且能够执行所有的恶意代码 ,如病毒或者特洛伊。

让我们一步步解决编写用于数字签名文档的Java-applet 过程中所存在的个别问题。

用jarsigner签名Java Applets

为了访问本地文件系统applet必须签名。假设我们已经编写了Java-applet 的代码并且已经将他编译成文件Applet.jar。签名这个JAR文件是有必要的。为此我们可以使用工具jarsigner ,它是与JDK 1.4一起标准发行的。 如下所示:


jarsigner -storetype pkcs12 -keystore keystore.pfx -storepass store_password -keypass private_key_password Applet.jar signFilesAlias




该命令使用私匙签名JAR文件Applet.jar,私匙是保存在受保护的名为signFilesAlias的密码存储keystore.pfx之内的,使用密码store_password 和private_key_password 可以相应的访问密码存储和私匙。Jarsigner工具支持两种类型的受保护的用于密码和证书的存储(密码存储)——Java Key Store (.JKS)和PKCS#12 (.PFX 文件)。为了使用它,我们必须有一个由认证机构(包含证书以及其相应私匙的PFX文件)颁发的证书或者我们必须生成我们自己的自签发证书。

生成自签发证书

我们可以使用工具keytool来生成我们自己的自签发证书。keytool也是与JDK 1.4一起标准发行的。如:

keytool -genkey -alias signFiles -keystore SignApplet.jks -keypass !secret -dname "CN=My Company" -storepass !secret




该命令生成一个X.509 证书和一个相应的私匙,并且将他们保存在密码存储SignApplet.jks 的名signFiles 之下。在证书中,它的所有者写成"My Company",并使用密码"!secret" 来控制对密码存储和私匙的访问。keytool 工具默认存储格式为JKS (Java Key Store)。

而且,我们可以采用如下方式用此证书来签发我们的applet :

jarsigner -keystore SignApplet.jks -storepass !secret -keypass !secret Applet.jar signFiles




该命令使用私匙签发applet Applet.jar。该私匙保存在用于访问密码"!secret"的密码存储SignApplet.jks的名"signFiles"之下。因此,我们可获得一个签名的JAR文件,该文件包含Applet.jar 检索到的所有文件格式,以及这些文件的数字签名和来自密码存储SignApplet.jks 的证书(注:密码存储SignApplet.jks具有完整的认证链)。如果编写的输出文件没有给出文件名,如例中所示,输入JAR文件也可用作输出JAR文件。

嵌入Applets到HTML文档内

我们用来嵌入签名的applet到HTML文档内的代码与我们用来嵌入正式 applet 的HTML代码毫无差别。因此使用签名的applet 时不推荐使用废弃的标记


"<applet>"


因为它无法显示applet运行时正确机能所需的最小JDK版本。某些Web浏览器(如IE)有对JDK v1.1的保准支持,并且除非特别声明签名的applet需要虚拟设备的更高版本,否则applet启动有限权限(当作普通的非签名applet ),从而不按意向执行,或者根本不启动。为了避免这种情况,推荐在Internet Explorer 中或者其他浏览器的


<embed>中使用<object>标记,



并推荐标明applet 所需的JDK的最小版本。一个名为HtmlConverter.exe的专用工具可用来自动标记从

<applet>



到更新的、嵌入标记的JDK 1.4 applet的转换。

执行客户端Web浏览器(一般为Java Plug-In)中的applet的环境负责判断给出的applet是否签名。如果是,在他的下载对话框中显示警告:为正确机能需要完全访问客户端系统的、签名的signed applet 已经下载。环境还给出签名applet所用证书的详细信息,宣布该applet是否有效,然后询问用户他是否可以执行没有任何安全限制的applet 。如果用户同意,applet 启动完全访问权限,否则它作为一个正规的、非签名的applet来执行。

从applet中访问Web服务

我们现在考虑另外一个问题。文档签名的applet 必须有一些方法,通过这些方法发送计算的数字签名给服务器。这可以采用几种方式来实现——applet 打开一个到服务器的socket 然后使用该socket 来发送签名,或者它通过对服务器URL的访问请求来发送信息,或者它与Web浏览器通讯并发送信息给Web浏览器, Web浏览器接着再发送信息给服务器。最后一个方法是最方便的,因为它为发送和接收签名文件所需的编程最少。在这种情况下,服务器接收同一个单一Web浏览器请求中的文件以及它的签名,而不需要作其他动作。

Applets 和Web浏览器之间的通讯

假设我们有一个普通的HTML表格,这个表格可用来发送文件给某个Web应用,而且不用签名。如果我们想要扩展这个表格,使它能够支持文档的数字签名,那么我们就能够简单的集成Java-applet ,以便在它之上签名文件。万一我们有一个applet可以计算文件的数字签名并能够在HTML表格的某些字段内编写该签名,那么发送数字签名所花的功夫是最小的。在递交HTML表格时,Web浏览器将一起发送签名,所以applet不必建立任何客户端-服务器通讯。

从Applets处访问HTML表格

通常Java-applets可以访问他们所嵌入的HTML的代码。这种能力可用来从HTML表格中获取用户正在发送的文件名,所以它的内容可以读取和签名。签名的结构可返回到同一个HTML表格的某些字段内。从技术上来说applet 和Web浏览器之间的交互可用标准类netscape.javascript.JSObject来实现, netscape.javascript.JSObject可被支持applet执行的所有浏览器访问。它还提供用来访问从中已经下载applet的当前Web浏览器窗口的所有属性,这就有效的证明了我们获得对该窗口中的HTML文档、其中的HTML表格、这些表格中的字段的访问,总之一句话,我们获得了对可以使用JavaScript访问的所有事物的访问权。一些浏览器允许applets运行JavaScript,也允许它在标记中严格声明之后访问他们从中下载的HTML文档,注:在标记中严格声明是为了将他们嵌入到HTML页中。 某些标记如"mayscript" 和 "scriptable"参数,他们都必须拥有值 "true"。

从JavaScript中访问Applet方法

通常不止一条方法可执行applet 和浏览器之间的通讯——不必让applet在表格字段中编写所发送文件的数字签名计算的结果,我们可以用JavaScript函数调用applet的方法,该方法将返回签名并再次与JavaScript一道将签名保存在表格的一个字段内。这实际上是无效的因为在多数浏览器中JavaScript运行时不允许访问文件系统。不管applet 是否签名,是否允许访问本地文件,只要是通过JavaScript调用它,它就丧失了这个能力。那就是为什么我们不从JavaScript 中调用用于签名文档的Java 函数,而是创建一个按钮状的applet,只要点击该按钮就可以签名所选择的文件并且在表格中预先指定的字段内编写签名。在签名计算后,我们能够随意的让applet通过JavaScript自动提交HTML表格,这样用户在签名完成后就不能修改表格了。如果那样的话,拥有没有提交按钮的HTML表格也是很方便的,并且仅从applet 内部提交而且签名成功的话,提供表格也是有可能的。那样用户就不能发送非签名的或者错误签名的文件。

在Web浏览器中签名文档的步骤

在签名过程中,不但发送文档和从文档中计算得出的数字签名到服务器有必要,要用到的证书以及它完整的认证链(如果有的话)也要发送到服务器上。证书是必要的,那是因为它存储了签名用户的公匙,没有它校验是通不过的。此外,证书还提供了将该公匙链接到确实完成了签名的某个用户之上的方法。如果我们只发送文档、签名和公匙给服务器,我们能够校验签名的有效性,但是我们没有关于公匙所有者的标记的信息,除非服务器保存了所有可能客户端的记录。一般而言,发送用户的证书以及它完整的认证链给服务器是最方便的。从点击签名的applet 的按钮开始完成文档签名的步骤如下:

1.提示用户从本地文件系统中选择一个受保护的密码存储文件(PFX 文件),该文件包含拥有相应认证链和私匙的他的数字证书。要求用户输入密码,以访问所选密码存储中的信息。

2.装在所选的PFX文件,获取用户的证书,相应的私匙和完整的认证链。

3.要签名的文件名从HTML表格中取出来。使用用户的私匙签名文件。

4.将签名的结果和用户的证书以及它完整的认证链写入HTML表格中的指定字段内。

接收签名文件的服务器负责检测文件是否正确使用与接收的证书相应的私匙签名。除此以外,服务器必须校验使用的证书是否有效。如果有必要确认签名者的标记的话,校验通常是在文件接收之后立即或者稍候进行的。

校验签名、证书和认证链

除了applet必须签名用户发送的文件之外,我们的基于Web的信息系统也应该具有接收文件和校验签名的功能。 为了确认实际上是谁签名了文件,校验所接收的用户的证书和认证链是有必要的。我们来讨论一下所涉及的这些校验问题。

校验数字签名

校验数字签名的目的是为了判断出发送的签名是否与发送的文件和证书对应,以及他是否可信等等。校验通过标准的签名校验程序进行——发送者的公匙从证书中可以得到并且检查收到的文档签名是否是从与该公匙对应的私匙处获得。在Java Cryptography Architecture 中有用于数字签名校验的标准类。

校验数字证书

校验收到的证书主要是判断存储在证书中的公匙是否真的属于证书所颁发的人,也就是说用户是否是签名文档的人。这种校验有点复杂并且需要一些准备。

有几种机制可用来校验数字证书。我们将使用其中的良种。校验证书的经典方法需要检测认证链。为了校验认证链要求它包含的所有证书都可用。否则认证无法完成。

在我们的系统内,在签名过程中用户使用标准的、受保护的、保存在PFX文件内的、用于密码和证书的存储(密码存储)。我们现在已经知道这些文件包含证书以及它相应的私匙。在多数情况下,证书与它的完整认证链在一起,但是有时候这个链不可用。例如当用户使用自签发的证书签名文档时,它没有认证链。因此服务器除了接收了签名的文件之外,可能还接收了有完整的认证链的用户证书,也有可能接收了没有认证链的证书。

校验有认证链的证书

如果认证链提交了,可通过经典的方法校验它——校验形成此链的所有证书(以及证书之间的所有链接)。为此可使用Java Certification Path API 和可在JDK 1.4中实现的PKIX算法。只有当应用拥有一组正确的、所信任的认证机构的Root 证书(所信任的CA root证书)才有必要。

校验没有认证链的证书

万一没有用于签名的证书的认证链,有另外一个,尽管有点不方便,方法可用于校验——直接校验证书。不建立和校验所给出的证书的认证链,只校验它是否由信任的证书直接签名,也是可能的。系统能够存储这种信任证书的清单。当需要校验所给出的证书时,它就会搜索整个清单以便找到看起来像所给出的证书的直接发行者。如果找到了这种信任证书,所校验的证书可认为有效,除非它已经到期了。

这种证书校验模式主要的不便就是系统需要存储人们可能使用的所有认证机构的证书。如果系统没有认证机构发行并签名的所给出的用户的证书,就算它有效,该用户的证书也不会通过校验。总之这种校验方法在用户提交没有认证链的证书的时候证明是有用的。

注意,通常用户证书不是由认证机构的root证书直接签发的,只有一些中间证书是由一些CA的某些root证书签发的。如果我们使用直接证书校验,我们应该有用于直接发行我们客户端的证书的所有可能信任的中间证书的清单。该清单上的证书应该就是我们无条件相信的证书。如果我们在认证链的基础上使用证书,我们只需要我们信任的顶级认证机构的root证书的清单,而不需要这些中间证书。

关于作者

Svetlin Nakov 是保加利亚索非亚大学的兼职计算机科学讲师。它有着5年的专业软件工程和培训经验,目前担任一家领先的保加利亚软件公司的IT顾问。他擅长的领域包括:Java以及相关技术、.NET框架、网络安全、数据结构与算法、以及编程代码的品质。
顶端 Posted: 06-02-08 12:25 | [楼 主]
Mike
群熵工程师
级别: 管理员


精华: 7
发帖: 951
威望: 714 点
金钱: 6601 RMB
贡献值: 0 点
好评度: 611 点
在线时间:1405(小时)
注册时间:2003-11-28
最后登录:2018-04-23

 问: 如何产生签名applet,以使applet能够访问本地资源?

答:
在jdk1.1中,可以使用javakey命令来产生公钥,私钥,证书和签名的jar文件,详细资料 请参考: http://java.sun.com/security/usingJavakey.html而java 2对签名机制做了比较大的改进,允许用户更灵活地设置安全权限.Java 2提供了三个工具:keytool,policytool和jarsigner来实现签名applet.例如,Joe编写了一个签名applet:SignedApplet.java,那么产生一个简单的签名applet的过程如下:


//产生密钥,密钥别名为joe,口令为sign12,存放在密钥库joestore中

keytool -genkey -alias joe -keypass sign12 -keystore joestore

//将SignedApplet.class及相关文件打包成jar文件

jar cvf SignedAppletDemo.jar

//利用keytool生成的自签名的证书产生签名applet(jar文件)

jarsigner -keystore joestore -signedjar joe.jar SignedAppletDemo.jar joe

//将自签名证书从keystore中输出到文件

keytool -export -keystore joestore -alias joe -file joe.cer



而对于签名applet的接受方Susan,需要通过如下步骤来安全地执行

Joe编写的签名applet:

//得到Joe的证书并将之读入到密钥库中susanstore中

keytool -import -alias joe -file joe.cer -keystore susanstore

//运行policytool产生满足Susan要求的policy文件

policytool

//用appletviewer运行之,或在浏览器中安装java plugin来运行之.



关于签名applet在Java Plugin中的部署请参考以下网页:

http://java.sun.com/security/signExample12/



注:以上的例子为简单起见,使用了keytool产生的自签名证书.其实,用户也可以

使用keytool -certreq向商业CA中心申请电子证书.
顶端 Posted: 06-02-08 12:26 | 1 楼
帖子浏览记录 版块浏览记录
群熵信息 - 技术讨论区 » 面向WEB的Java技术

Total 0.013401(s) query 5, Time now is:06-18 13:39, Gzip enabled
Powered by PHPWind v6.3.2 Certificate Code © 2003-08 PHPWind.com Corporation

上海服务器租用 杭州世导双线服务器托管 云主机 VPS