数字签名的一些总结

来源:互联网 发布:淘宝海外 全球站入驻 编辑:程序博客网 时间:2024/05/02 08:38

数字签名和数字证书是什么

         下面通过一些图片通俗易懂的解释一下什么是数字签名(digital signature)和数字证书(digital certificate)。

1.

 

   鲍勃有两把钥匙,一把是公钥,另一把是私钥。


2.

 

    鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。


3.

   

    苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。


4.

   

    鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。


5.

  

    鲍勃给苏珊回信,决定采用"数字签名"。他写完后先用Hash函数,生成信件的摘要(digest)。


6.

    然后,鲍勃使用私钥,对这个摘要加密,生成"数字签名"(signature)。


7.

 

    鲍勃将这个签名,附在信件下面,一起发给苏珊。


8.

    苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的(因为鲍勃的公钥可以解密)。


9.

    苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。


10.

    复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成"数字签名",写信给苏珊,让苏珊用假的鲍勃公钥进行解密。


11.

 

    后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找"证书中心"(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成"数字证书"(Digital Certificate)。


12.

    鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。


13.

    苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明"数字签名"是否真的是鲍勃签的。


需要注意的是:

  1. 发送方和接收方使用Hash算法需要双方实现约定好。
  2. 数字证书是公钥的载体,同时包含证书颁发机构和标识及用户的标识,证书ID,有效期等信息(详见参考资料),另外还包含CA对此证书内容的进行了数字签名,以验证此证书的有效性.在验证一个数字证书的过程中,对数字证书的数字签名的验证将递归进行,只到找到双方共同可信任的CA根证书为止。

14.


     下面,我们看一个应用"数字证书"的实例:https协议。这个协议主要用于网页加密。


15.

   首先,客户端向服务器发出加密请求。


16.

   服务器用自己的私钥加密网页以后,连同本身的数字证书,一起发送给客户端。


17.

    客户端(浏览器)的"证书管理器",有"受信任的根证书颁发机构"列表。客户端会根据这张列表,查看解开数字证书的公钥是否在列表之内。


18.

   如果数字证书记载的网址,与你正在浏览的网址不一致,就说明这张证书可能被冒用,浏览器会发出警告。


19.

    如果这张数字证书不是由受信任的机构颁发的,浏览器会发出另一种警告。


20.

    如果数字证书是可靠的,客户端就可以使用证书中的服务器公钥,对信息进行加密,然后与服务器交换加密信息。


如何获取数字证书

1向CA机构申请

        数字证书可向专门的CA机构申请,有免费的数字证书和付费的数字证书.比如:中国数字认证网(http://www.ca365.com)、广东省电子商务认证中心(http://www.cnca.net/)就可申请到有效期为一年的免费数字证书.注意申请的证书是以该CA的证书作为申请的个人证书的根证书,所以如果想要申请的证书有效,需要下载并安装相应CA的根证书.

2.使用工具制作

        通过一些工具也可生成个人使用的数字证书,如微软的makecert(下载地址http://www.microsoft.com/downloads/details.aspx?familyid=2b742795-d0f0-4a66-b27f-22a95fcd3425&displaylang=en)),JDK中包含的keytool工具(以下会详细介绍如何使用)都可生成没有经过认证的数字证书.

如何实现签名

JDK有部分工具和API提供了对数字签名的支持:keytool,jarsigner,policytool等.

KeyTool工具可生成,导入,导出数字证书,支持的证书的格式为当前流行的

生成证书:keytool -genkey -alias mykey -keystore mystore

导入证书:keytool -import -alias abc -file ABCCA.cer -keystore mystore

导出证书: keytool -export -alias mykey -file MJ.cer -keystore mystore

对jar文件进行签名使用的工具是jarsigner:

格式如下:jarsigner -keystore keystoreFile jarfile alias

例如:jarsigner -keystore sylilzyKeystore.dat test.jar sylilzy

验证一个jar文件如下:

jarsigner -verify jarfile

以下步骤演示了一个完整的由获取数字证书到签名jar文件,然后访问该jar文件时显示签名信息的全过程:

上面提到,数字证书可由以下方式生成,第一,去http://www.ca365.com申请一个免费的数字证书,下载后为test.der



1.制作证书

使用keytool -genkey -alias mykey -keystore mystore生成密钥库mystore,提示相关信息,并填写完毕,如下:

E:\downloads\qm>keytool -genkey -alias mykey -keystore mystore输入密钥库口令:再次输入新口令:您的名字与姓氏是什么?  [Unknown]:  david您的组织单位名称是什么?  [Unknown]:  zte您的组织名称是什么?  [Unknown]:  zte您所在的城市或区域名称是什么?  [Unknown]:  chengdu您所在的省/市/自治区名称是什么?  [Unknown]:  chengdu该单位的双字母国家/地区代码是什么?  [Unknown]:  cnCN=david, OU=zte, O=zte, L=chengdu, ST=chengdu, C=cn是否正确?  [否]:  y输入 <mykey> 的密钥口令        (如果和密钥库口令相同, 按回车):
      执行命令后,生成了一个名为mystore的keystore文件(即密钥库),该文件中保存有别名为mykey的数字证书.输入以下命令即可查看此数字证书:

E:\downloads\qm>keytool -list -alias mykey -keystore mystore输入密钥库口令:mykey, 2014-12-30, PrivateKeyEntry,证书指纹 (SHA1): 31:48:02:41:F8:23:6D:C5:C5:12:F3:AF:5C:56:EA:10:FF:5E:88:3A

     或者带上-v参数显示详细信息
E:\downloads\qm>keytool -list -alias mykey -keystore mystore -v输入密钥库口令:别名: mykey创建日期: 2014-12-30条目类型: PrivateKeyEntry证书链长度: 1证书[1]:所有者: CN=david, OU=zte, O=zte, L=chengdu, ST=chengdu, C=cn发布者: CN=david, OU=zte, O=zte, L=chengdu, ST=chengdu, C=cn序列号: 6a66cb4f有效期开始日期: Tue Dec 30 21:27:34 CST 2014, 截止日期: Mon Mar 30 21:27:34 CST 2015证书指纹:         MD5: 96:B7:72:70:BC:37:25:AF:F6:28:D9:F0:C3:54:7B:4C         SHA1: 31:48:02:41:F8:23:6D:C5:C5:12:F3:AF:5C:56:EA:10:FF:5E:88:3A         SHA256: 43:1A:76:13:EA:10:22:C3:3E:E8:6A:8A:CF:4F:8E:D1:6D:30:F7:70:83:0C:04:F2:3D:30:E7:2E:95:B4:A6:57         签名算法名称: SHA1withDSA         版本: 3扩展:#1: ObjectId: 2.5.29.14 Criticality=falseSubjectKeyIdentifier [KeyIdentifier [0000: 37 E5 48 80 6F 92 9C FC   33 54 17 F6 B3 15 8C A6  7.H.o...3T......0010: A9 EE 51 38                                        ..Q8]]

  从mysore文件中导出数字证书mykey

E:\downloads\qm>keytool -export -keystore mystore -alias mykey -file my.cer输入密钥库口令:存储在文件 <my.cer> 中的证书
   导出的数字证书保存在my.cer文件中,如下图所示:

                        

2. 为jar包签名

   创建一个java工程testPro, 并新建一个com.test.Demo.java类,文件内容如下:

package com.test;public class Demo {public static void main(String[] args) {System.out.println("Hello World...");}}

将java工程打成jar包,testPro.jar,查看testPro.jar目录:




   执行jarsigner -keystore mystore test.jar mykey对jar包进行签名

E:\downloads\qm>jarsigner -keystore mystore testPro.jar mykey输入密钥库的密码短语:警告:签名者证书将在六个月内过期。

命令中,mystore是密钥库名称,mykey是证书的别名。因为没有指定密钥库的路径,所以只需要将密钥库和jar放在同一个目录下即可。


再次查看签名后的testPro.jar的\META-INF\目录,发现多出了两个文件,如下所示:

打开MYKEY.SF文件,内容如下:

Signature-Version: 1.0SHA-256-Digest-Manifest-Main-Attributes: VmrRqAIgAm0FCZViZFzpaP8OfDbN4 iY0MyYFuzTMPv8=SHA-256-Digest-Manifest: +zYfr3FMJyM4p20Z0bcD6cxLfVnJ5XX3WdhzdMS504M=Created-By: 1.7.0_17 (Oracle Corporation)Name: com/test/Demo.classSHA-256-Digest: MjNJ1FhRBN7804+sO9ot/hn90NTUou87EoHmbi0Wcxk=Name: .classpathSHA-256-Digest: WYUpd+cq82OtrX/UYH3DGBM8E7v1AMR8LyKzH+H65do=Name: .projectSHA-256-Digest: We2148LlKL7eojW3PKQNfCOkEcy3fA3dKVWd5MJdDWI=

从MYKEY.SF文件的内容可以看出,签名时分别为testPro.jar中Demo.class、.classpath和.project三个文件生成摘要


执行Demo类,运行结果如下:

E:\downloads\qm>java -classpath testPro.jar com.test.DemoHello World...

如果我们修改MYKEY.SF文件中的任何摘要信息,如把
Name: .projectSHA-256-Digest: We2148LlKL7eojW3PKQNfCOkEcy3fA3dKVWd5MJdDWI=
改成

Name: .projectSHA-256-Digest: We2148LlKL7eojW3PKQNfCOkEcy3fA3dKVWd5MJdDWI
再次执行Demo类结果如下:

E:\downloads\qm>java -classpath testPro.jar com.test.DemoException in thread "main" java.lang.SecurityException: cannot verify signature block file META-INF/MYKEY        at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:220)        at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:193)        at java.util.jar.JarVerifier.processEntry(JarVerifier.java:262)        at java.util.jar.JarVerifier.update(JarVerifier.java:216)        at java.util.jar.JarFile.initializeVerifier(JarFile.java:345)        at java.util.jar.JarFile.getInputStream(JarFile.java:412)        at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:752)        at sun.misc.Resource.cachedInputStream(Resource.java:77)        at sun.misc.Resource.getByteBuffer(Resource.java:160)        at java.net.URLClassLoader.defineClass(URLClassLoader.java:436)        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)        at java.security.AccessController.doPrivileged(Native Method)        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
或者将testPro中的Demo文件的内容修改成如下:

package com.test;public class Demo {public static void main(String[] args) {System.out.println("Hello World...");}}
即第6行增加了一个空行,重新生成class文件放入testPro.jar,替换原有的Demo.class文件,重新执行Demo,将报如下错误信息:

E:\downloads\qm>java -classpath testPro.jar com.test.DemoException in thread "main" java.lang.SecurityException: SHA-256 digest error for com/test/Demo.class        at sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:220)        at java.util.jar.JarVerifier.processEntry(JarVerifier.java:229)        at java.util.jar.JarVerifier.update(JarVerifier.java:216)        at java.util.jar.JarVerifier$VerifierStream.read(JarVerifier.java:471)        at sun.misc.Resource.getBytes(Resource.java:124)        at java.net.URLClassLoader.defineClass(URLClassLoader.java:444)        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)        at java.security.AccessController.doPrivileged(Native Method)        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
    通过签名对jar文件签名,这样就防止被人恶意修改jar文件破坏运行程序,因为一旦jar文件被修改,我们在调用jar中程序时就会抛出安全异常,就知道jar被人修改了。



下面keytool的命令详解附在这里:

Keytool是一个Java数据证书的管理工具,Keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中在keystore里,包含两种数据:
密钥实体(Key entity)——密钥(secret key)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trusted certificate entries)——只包含公钥


ailas(别名)每个keystore都关联这一个独一无二的alias,这个alias通常不区分大小写

 

JDK中keytool常用命令:

-genkey      在用户主目录中创建一个默认文件".keystore",还会产生一个mykey的别名,mykey中包含用户的公钥、私钥和证书 
-alias       产生别名
-keystore    指定密钥库的名称(产生的各类信息将不在.keystore文件中
-keyalg      指定密钥的算法    
-validity    指定创建的证书有效期多少天
-keysize     指定密钥长度
-storepass   指定密钥库的密码
-keypass     指定别名条目的密码
-dname       指定证书拥有者信息 例如:  "CN=sagely,OU=atr,O=szu,L=sz,ST=gd,C=cn"
-list        显示密钥库中的证书信息      keytool -list -v -keystore sage -storepass ....
-v           显示密钥库中的证书详细信息
-export      将别名指定的证书导出到文件  keytool -export -alias caroot -file caroot.crt
-file        参数指定导出到文件的文件名
-delete      删除密钥库中某条目          keytool -delete -alias sage -keystore sage
-keypasswd   修改密钥库中指定条目口令    keytool -keypasswd -alias sage -keypass .... -new .... -storepass ... -keystore sage
-import      将已签名数字证书导入密钥库  keytool -import -alias sage -keystore sagely -file sagely.crt 
             导入已签名数字证书用keytool -list -v 以后可以明显发现多了认证链长度,并且把整个CA链全部打印出来。

------------------------------------------------------------------------------------------------

keytool JAVA是个密钥和证书管理工具。它使用户能够管理自己的公钥/私钥对及相关证书,用于(通过数字签名)自我认证(用户向别的用户/服务认证自己)或数据完整性以及认证服务。它还允许用户储存他们的通信对等者的公钥(以证书形式)。通过keytool –help查看其用法,详细信息可以参考http: //java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/keytool.html 

创建证书Java 中的 keytool.exe (位于 JDK/Bin 目录下)可以用来创建数字证书,所有的数字证书是以一条一条(采用别名区别)的形式存入证书库的中,证书库中的一条证书包含该条证书的私钥,公钥和对应的数字证书的信息。证书库中的一条证书可以导出数字证书文件,数字证书文件只包括主体信息和对应的公钥。 
每一个证书库是一个文件组成,它有访问密码,在首次创建时,它会自动生成证书库,并要求指定访问证书库的密码。 
在创建证书的的时候,需要填写证书的一些信息和证书对应的私钥密码。这些信息包括 CN=xx,OU=xx,O=xx,L=xx,ST=xx,C=xx,它们的意思是: 
? CN(Common Name - 名字与姓氏):其实这个“名字与姓氏”应该是域名,比如说localhost或是blog.devep.net之类的。输成了姓名,和真正运行的时候域名不符,会出问题。浏览器访问时,弹出一个对话框,提示“安全证书上的名称无效,或者与站点名称不匹配”,用户选择继续还是可以浏览网页。但是用http client写程序访问的时候,会抛出类似于“javax.servlet.ServletException: HTTPS hostname wrong: should be ”的异常。 
? OU(Organization Unit - 组织单位名称) 
? O(Organization - 组织名称) 
? L(Locality - 城市或区域名称) 
? ST(State - 州或省份名称) 
? C(Country - 国家名称) 
可以采用交互式让工具提示输入以上信息,也可以采用参数,如:-dname “CN=xx,OU=xx,O=xx,L=xx,ST=xx,C=xx”来自动创建。 

创建一个证书 
指定证书库(又称密钥库)为 D:/keystore/test,创建别名为 Tomcat 的一条证书,它指定用 RSA 算法生成,且指定密钥长度为 1024,证书有效期为 1 年: 
keytool -genkey -alias Tomcat -keyalg RSA -keysize 1024 -keystore C:/keystore/test -validity 365 
显示证书库中的证书使用如下命令: keytool -list -keystore C:/keystore/test 将显示 C:/keystore/test 证书库的的所有证书列表 

导出到证书文件 
使用命令:keytool -export -alias Tomcat -file C:/keystore/TC.cer -keystore C:/keystore/test 将把证书库C:/keystore/test 中的别名为 Tomcat 的证书导出到 TC.cer 证书文件中,它包含证书主体的信息及证书的公钥,不包括私钥,可以公开。 
导出的证书文件是以二进制编码文件,无法用文本编辑器正确显示,可以加上 -rfc参数以一种可打印的编者编码输出。 如: 
keytool -export -alias Tomcat -file C:/keystore/TC.cer -keystore C:/keystore/test –rfc 

查看证书的信息 
通过命令: keytool -printcert -file D:/keystore/TC.cer 可以查看证书文件的信息。 也可以在 Windows 资源管理器中双击产生的证书文件直接查看。 

删除密钥库中的条目 
keytool -delete -alias Tomcat -keystore C:/keystore/test 
这条命令将 C:/keystore/test 库中的 Tomcat 这一条证书删除了。 

修改证书条目口令 
keytool -keypasswd -alias Tomcat -keystore C:/keystore/test,可以以交互的方式修改 C:/keystore/test 证书库中的条目为 Tomcat 的证书。 
Keytool -keypasswd -alias Tomcat -keypass oldpasswd -new newpasswd -storepass storepasswd -keystore C:/keystore/test 这一行命令以非交互式的方式修改库中别名为 Tomcat 的证书的密码为新密码 newpasswd,行中的 oldpasswd 是指该条证书的原密码, storepasswd 是指证书库的密码。

0 0