Java加密解密与数字证书的操作

时间:2022-05-24 21:04:40

1 keytool命令总结

一、创建数字证书

交互模式

使用默认的密钥库.keystore(文件夹是c: Documents and Settingusername)和算法(DSA)

keytool -genkey

默认的别名mykey

密钥库中能够存放多个条目(公钥/私钥对和证书),它们在密钥库中以别名(alias)区分。

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -alias mytest -keyalg RSA -keysize 1024 -keystore mykeystore -validity 4000

当中,   

-keyalg參数能够指定密钥的算法,假设须要指定密钥的长度,能够再加上-keysize參数。密钥长度默觉得1024位,使用DSA算法时,密钥长度必须在512到1024之间,而且是64的整数倍。

-keystore參数能够指定密钥库的名称。密钥库事实上是存放密钥和证书的文件,密钥库相应的文件假设不存在自己主动创建。

-validity參数能够指定所创建的证书有效期是多少天。

非交互模式:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -dname "CN=tmp, OU=NC, O=Shanghai University, L=ZB, ST=Shanghai, C=CN" -alias tmp -keyalg RSA -keystore mykeystore -keypass wshr.ut -storepass wshr.ut  -validity 1000

二、数字证书的显示(从密钥库中)

默认密钥库所有证书信息

keytool -list -v(显示具体信息)

显示指定密钥库指定条目证书信息(包括了发照者(签发者)、序号、有效期、MD5和SHA1认证指纹等额外信息)

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -list -v -keystore lfkeystore -alias lf

三、使用Keytool将数字证书导出到文件

将指定的证书从密钥库导出为没编码过的文件。

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -export -alias lf -file lf.cer  -keystore lfkeystore

四、使用Keytool从文件里显示证书

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -printcert -file  lf.cer

五、在Windows中从文件显示证书

仅仅要文件名称以.cer为后缀,Windows操作系统就能够直接识别。如在Windows中双击lf.cer图标,将出现证书窗体。当中包括了证书的全部者、颁发者、有效期等信息。

点击“具体资料”,能够看到证书的版本号、序号、签名算法、颁发者、有效期、主题(即全名)、公钥算法、拇印算法、拇印等信息。当中的拇印即认证指纹。

六、密钥库的维护

使用Keytool删除指定条目

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -delete -alias tmp1 -keystore mykeystore

使用Keytool改动指定条目的口令

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -keypasswd -alias tmp1 -keystore mykeystore

(非交互模式:keytool -keypasswd -alias tmp1 -keystore mykeystore -storepass wshr.ut -keypass 123456 -new 080302,当中080302为原password,123456为新password )

证书生成应用实例:

运行命令前先保证目录存在。比如:在c盘建立keystore目录

第一步:为server生成证书

确定域名:本机中域名解析改动文件是C:WINDOWSsystem32driversetchosts

使用keytool 为 Tomcat 生成证书和密钥库,假定目标机器的域名是“ hepengfei ”, keystore 文件存放在“ C:keystoreserver ”,口令为“ 080302 ”,命令例如以下:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -v -keystore C:keystoreserver -alias serverkey -keyalg RSA -validity 3650 -dname "CN=hepengfei,OU=cn,O=cn,L=cn,ST=cn,c=cn" -storepass 080302 -keypass 080302

生成server.cer安装在client解决服务器信任问题:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -export -keystore C:keystoreserver -alias serverkey -file c:keystoreserver.cer -storepass 080302

第二步:为client生成证书

(注意:个人证书的生成和使用比較特别,是分开的。先生成p12文件,然后导出cer文件,再将cer文件导入默认类型的keystore(JKS)文件)

这一步是为浏览器生成证书,以便让server来验证它。为了能将证书顺利导入至IE 和 Firefox ,证书格式应该是 PKCS12 ,因此,使用例如以下命令生成:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -v -keystore C:keystoreuser.p12 -alias MyPC -keyalg RSA -storetype PKCS12 -validity 3650 -dname "CN=MyPC,OU=cn,O=cn,L=cn,ST=cn,c=cn" -storepass 080302 -keypass 080302

server要信任client证书,就必须把client证书加入为server的信任认证。因为不能直接将 PKCS12 格式的证书库导入,我们必须先把client证书导出为一个单独的 CER 文件,使用例如以下命令:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -export -alias MyPC -keystore C:keystoreuser.p12 -storetype PKCS12 -storepass 080302 -rfc -file C:keystoreuser.cer

接着,将C:user.cer导入到server的证书库,加入为一个信任证书:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -import -v -file C:keystoreuser.cer -keystore c:keystoreservertrust -alias user -storepass 080302

输入“是”确认完毕。



通过list 命令查看:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -list -keystore c:keystoreservertrust -storepass 080302

也能够考虑将server证书和server信任证书放到一个密钥库中



第四步:配置Tomcat server 



打开Tomcat 根文件夹下的 /conf/server.xml ,改动例如以下:

<="">

clientAuth="true" sslProtocol="TLS"

keystoreFile="C:JavaTomcatconfkeystoreserver" keystorePass="080302"

truststoreFile="C:JavaTomcatconfkeystoreservertrust" truststorePass="080302"

/>

详解见本节最前面介绍。

安装个人证书user.p12(password:080302)和服务器证书server.cer

到这里启动tomcat,输入 https://hepengfei:8443/Test,就OK了。

假设数字证书注冊名称不是127.0.0.1,而是相应的一个hepengfei,

使用ip訪问(https://127.0.0.1:8443/Test)能够进入选择数字证书界面(仿真格式):

选择数字证书

名称     颁发商

MyPC     MyPC

具体信息  查看证书

确定   取消

注意点:

keytool -list -v -keystore user

使用的库要privateKeyEntry

信任的库要trustedCertEntry

ConvertKeystoreType.java用于转换密钥库类型(PKCS12与JKS格式证书库转换工具)

ssl使用当中四个密钥库

https使用server、servertrust、user.p12(安装到本地计算机)、server.cer四个

生成证书请求:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -certreq -alias tomcat_server -sigalg MD5withRSA -file tomcat_server.csr -keypass 123456 -storepass 123456 -keystore server_keystore

PKCS12

使用Keytool列出pkcs12证书的内容

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -rfc -list -keystore tomcat_client.p12 -storetype pkcs12

使用Keytool导出pkcs12证书的公钥证书

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool  -keystore tomcat_client.p12 -storetype pkcs12 -export -alias mypc -file mypc.cer

将已经签名的证书导入密钥库(覆盖原来的公钥)

先导入证书链中的相关信任证书,再导入已经签名的证书(别名与私钥证书别名保持一样)。

2 Java程序实现密钥库的维护

2.1 Java程序列出密钥库全部条目

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.util.*;
  2. import java.io.*;
  3. import java.security.*;
  4. public class ShowAlias{
  5. public static void main(String args[ ]) throws Exception{
  6. String pass="080302";
  7. String name=".keystore";
  8. FileInputStream in=new FileInputStream(name);
  9. KeyStore ks=KeyStore.getInstance("JKS");
  10. ks.load(in,pass.toCharArray());
  11. Enumeratione=ks.aliases( );
  12. while( e.hasMoreElements()) {
  13. System.out.println(e.nextElement());
  14. }
  15. }
  16. }

2.2 Java程序改动密钥库口令

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. public class SetStorePass{
  4. public static void main(String args[ ]) throws Exception{
  5. char[ ] oldpass="080302".toCharArray();
  6. char[ ] newpass="123456".toCharArray();
  7. String name=".keystore";
  8. FileInputStream in=new FileInputStream(name);
  9. KeyStore ks=KeyStore.getInstance("JKS");
  10. ks.load(in,oldpass);
  11. in.close();
  12. FileOutputStream output=new FileOutputStream(name);
  13. ks.store(output,newpass);
  14. output.close();
  15. }
  16. }

2.3 Java程序改动密钥库条目的口令及加入条目

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package test;
  2. import java.io.*;
  3. import java.security.*;
  4. import java.security.cert.Certificate;
  5. public class SetKeyPass{
  6. public static void main(String args[ ]) throws Exception{
  7. //读取相关參数
  8. String name=".keystore";
  9. String alias="mykey";
  10. char[ ] storepass="123456".toCharArray();
  11. char[ ] oldkeypass="080302".toCharArray();
  12. char[ ] newkeypass="123456".toCharArray();
  13. //获取密钥库.keystore的KeyStore对象,并载入密钥库
  14. FileInputStream in=new FileInputStream(name);
  15. KeyStore ks=KeyStore.getInstance("JKS");
  16. ks.load(in,storepass);
  17. //获取别名相应的条目的证书链
  18. Certificate[ ] cchain=ks.getCertificateChain(alias);
  19. //读取别名相应的条目的私钥
  20. PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass);
  21. //向密钥库中加入新的条目
  22. ks.setKeyEntry(alias,pk,newkeypass,cchain);
  23. in.close();
  24. //将KeyStore对象内容写入新文件
  25. FileOutputStream output=new FileOutputStream("333");
  26. ks.store(output,storepass);
  27. output.close();
  28. }
  29. }

2.4 Java程序检验别名及删除条目

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package test;
  2. import java.io.*;
  3. import java.security.*;
  4. public class DeleteAlias{
  5. public static void main(String args[ ]) throws Exception{
  6. String pass = "123456";
  7. String name = ".keystore";
  8. String alias = "mykey";
  9. FileInputStream in=new FileInputStream(name);
  10. KeyStore ks=KeyStore.getInstance("JKS");
  11. ks.load(in,pass.toCharArray());
  12. if (ks.containsAlias(alias)){
  13. ks.deleteEntry(alias);
  14. FileOutputStream output=new FileOutputStream(name);
  15. ks.store(output,pass.toCharArray());
  16. System.out.println("Alias "+alias+" deleted");
  17. }else{
  18. System.out.println("Alias not exist");
  19. }
  20. }
  21. }

3 Java程序读取证书和显示证书指定信息

3.1 Java程序从证书文件读取证书

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.cert.*;
  3. public class PrintCert{
  4. public static void main(String args[ ]) throws Exception{
  5. CertificateFactory cf=CertificateFactory.getInstance("X.509");
  6. FileInputStream in=new FileInputStream("my.cer");
  7. Certificate c=cf.generateCertificate(in);
  8. in.close();
  9. String s=c.toString( );
  10. // 显示证书
  11. FileOutputStream fout=new FileOutputStream("tmp.txt");
  12. BufferedWriter out= new BufferedWriter(new OutputStreamWriter(fout));
  13. out.write(s,0,s.length( ));
  14. out.close();
  15. }
  16. }

3.2 Java程序从密钥库直接读取证书

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.security.cert.Certificate;
  4. public class PrintCert2{
  5. public static void main(String args[ ]) throws Exception{
  6. String pass="080302";
  7. String alias="mykey";
  8. String name=".keystore";
  9. FileInputStream in=new FileInputStream(name);
  10. KeyStore ks=KeyStore.getInstance("JKS");
  11. ks.load(in,pass.toCharArray());
  12. Certificate c=ks.getCertificate(alias);
  13. in.close();
  14. System.out.println(c.toString( ));
  15. }
  16. }

3.3 Java程序显示证书指定信息(全名/公钥/签名等)

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.security.cert.*;
  4. import java.math.*;
  5. public class ShowCertInfo{
  6. public static void main(String args[ ]) throws Exception{
  7. CertificateFactory cf=CertificateFactory.getInstance("X.509");
  8. FileInputStream in=new FileInputStream("my.cer");
  9. java.security.cert.Certificate c=cf.generateCertificate(in);
  10. in.close();
  11. X509Certificate t=(X509Certificate) c;
  12. System.out.println("版本 "+t.getVersion());
  13. System.out.println("序列号 "+t.getSerialNumber().toString(16));
  14. System.out.println("全名 "+t.getSubjectDN());
  15. System.out.println("签发者全名n"+t.getIssuerDN());
  16. System.out.println("有效期起始日 "+t.getNotBefore());
  17. System.out.println("有效期截至日 "+t.getNotAfter());
  18. System.out.println("签名算法 "+t.getSigAlgName());
  19. byte[] sig=t.getSignature();
  20. System.out.println("签名n"+new BigInteger(sig).toString(16));
  21. PublicKey pk=t.getPublicKey();
  22. byte[ ] pkenc=pk.getEncoded();
  23. System.out.println("公钥");
  24. for(int i=0;i< div="">
  25. System.out.print(pkenc[i]+",");
  26. }
  27. }
  28. }

4 ssl/https双向验证的配置与证书库的生成

1.SSL认证

不须要特别配置,相关证书库生成看https认证中的相关部分

2.HTTPS认证

一、基本概念

1.单向认证,就是传输的数据加密过了,可是不会校验client的来源 

2.双向认证,假设client浏览器没有导入client证书,是訪问不了web系统的,找不到地址 

假设仅仅是加密,我感觉单向即可了。 

假设想要用系统的人没有证书就訪问不了系统的话,就採用双向

二、server配置:

打开Tomcat 根文件夹下的 /conf/server.xml 改动server.xml

client证书注冊名称必须与域名一致,否则无法验证。

比如訪问https://127.0.0.1:8443/Test必须使用名称为127.0.0.1的证书,

訪问https://hepengfei:8443/Test必须使用名称为hepengfei的证书,

本机中域名解析改动文件是C:WINDOWSsystem32driversetchosts

port号改为8443,为自己定义port    訪问https://127.0.0.1:8443/Test

port号改为443,则为默认port    訪问https://127.0.0.1/Test

clientAuth="true"为双向认证      clientAuth="false"为单向认证

使用密钥库文件和password(自己使用的证书)

信任密钥库文件和password(含有client证书或其根证书)

<="" 1.1? sslenabled="true">maxThreads="150" scheme="https" secure="true"

clientAuth="true" sslProtocol="TLS"

keystoreFile="C:JavaTomcatconfkeystoreserver" keystorePass="080302"

truststoreFile="C:JavaTomcatconfkeystoreservertrust" truststorePass="080302"

/>

三、证书的生成例如以下:

运行命令前先保证目录存在。比如:在c盘建立keystore目录

第一步:为server生成证书

确定域名:本机中域名解析改动文件是C:WINDOWSsystem32driversetchosts

使用keytool 为 Tomcat 生成证书和密钥库,假定目标机器的域名是“ hepengfei ”, keystore 文件存放在“ C:keystoreserver ”,口令为“ 080302 ”,命令例如以下:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -v -keystore C:keystoreserver -alias serverkey -keyalg RSA -validity 3650 -dname "CN=hepengfei,OU=cn,O=cn,L=cn,ST=cn,c=cn" -storepass 080302 -keypass 080302

生成server.cer安装在client解决服务器信任问题:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -export -keystore C:keystoreserver -alias serverkey -file c:keystoreserver.cer -storepass 080302

第二步:为client生成证书

(注意:个人证书的生成和使用比較特别,是分开的。先生成p12文件,然后导出cer文件,再将cer文件导入默认类型的keystore(JKS)文件)

这一步是为浏览器生成证书,以便让server来验证它。为了能将证书顺利导入至IE 和 Firefox ,证书格式应该是 PKCS12 ,因此,使用例如以下命令生成:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -genkey -v -keystore C:keystoreuser.p12 -alias MyPC -keyalg RSA -storetype PKCS12 -validity 3650 -dname "CN=MyPC,OU=cn,O=cn,L=cn,ST=cn,c=cn" -storepass 080302 -keypass 080302

server要信任client证书,就必须把client证书加入为server的信任认证。因为不能直接将 PKCS12 格式的证书库导入,我们必须先把client证书导出为一个单独的 CER 文件,使用例如以下命令:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -export -alias MyPC -keystore C:keystoreuser.p12 -storetype PKCS12 -storepass 080302 -rfc -file C:keystoreuser.cer

接着,将C:user.cer导入到server的证书库,加入为一个信任证书:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -import -v -file C:keystoreuser.cer -keystore c:keystoreservertrust -alias user -storepass 080302

输入“是”确认完毕。

通过list 命令查看:

[plain] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. keytool -list -keystore c:keystoreservertrust -storepass 080302

也能够考虑将server证书和server信任证书放到一个密钥库中



第四步:配置Tomcat server 



打开Tomcat 根文件夹下的 /conf/server.xml ,改动例如以下:

<="" 1.1? sslenabled="true">maxThreads="150" scheme="https" secure="true"

clientAuth="true" sslProtocol="TLS"

keystoreFile="C:JavaTomcatconfkeystoreserver" keystorePass="080302"

truststoreFile="C:JavaTomcatconfkeystoreservertrust" truststorePass="080302"

/>

详解见本节最前面介绍。

安装个人证书user.p12(password:080302)和服务器证书server.cer

到这里启动tomcat,输入 https://hepengfei:8443/Test,就OK了。

假设数字证书注冊名称不是127.0.0.1,而是相应的一个hepengfei,

使用ip訪问(https://127.0.0.1:8443/Test)能够进入选择数字证书界面(仿真格式):

选择数字证书

名称     颁发商

MyPC     MyPC

具体信息  查看证书

确定   取消

注意点:

keytool -list -v -keystore user

使用的库要privateKeyEntry

信任的库要trustedCertEntry

ConvertKeystoreType.java用于转换密钥库类型(PKCS12与JKS格式证书库转换工具)

ssl使用当中四个密钥库

https使用server、servertrust、user.p12(安装到本地计算机)、server.cer四个

5 数字签名-对数字证书的数字签名

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.security.cert.*;
  4. import java.util.*;
  5. import sun.security.x509.*;
  6. /*
  7. * CA密钥库和其password、CA中要使用的条目和其password,新密钥库和其password、新的条目名称
  8. * 特别注意:java中有些类得到特别保护(比方X509CertImpl),必须设置规则才干訪问【项目属性-Java Build Path-JRE
  9. * System Library-Access Rules-Edit-"sun/**"(Accessible)】
  10. */
  11. public class SignCert{
  12. public static void main(String args[ ]) throws Exception{
  13. String signerName = "keystore/ibe";
  14. String signerAlias = "he";
  15. char[] signerStorePass = "080302".toCharArray( );
  16. char[] signerKeyPass = "080302".toCharArray( );
  17. String CertName = "cert/ibe-mao.cer";
  18. String newStore = "keystore/newstore";
  19. String newStoreAlias = "mao";
  20. char[] newStorePass = "080302".toCharArray();
  21. // CA证书
  22. FileInputStream in=new FileInputStream(signerName);
  23. KeyStore ks=KeyStore.getInstance("JKS");
  24. ks.load(in,signerStorePass);
  25. java.security.cert.Certificate c1=ks.getCertificate(signerAlias);
  26. PrivateKey caprk=(PrivateKey)ks.getKey(signerAlias,signerKeyPass);
  27. in.close();
  28. //得到签发者
  29. byte[] encod1=c1.getEncoded();
  30. X509CertImpl cimp1=new X509CertImpl(encod1);
  31. X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);
  32. X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME);
  33. //要签名的证书
  34. CertificateFactory cf=CertificateFactory.getInstance("X.509");
  35. FileInputStream in2=new FileInputStream(CertName);
  36. java.security.cert.Certificate c2=cf.generateCertificate(in2);
  37. in2.close();
  38. byte[] encod2=c2.getEncoded();
  39. X509CertImpl cimp2=new X509CertImpl(encod2);
  40. X509CertInfo cinfo2=(X509CertInfo)cimp2.get(
  41. X509CertImpl.NAME+"."+X509CertImpl.INFO);
  42. //设置新证书有效期
  43. Date begindate =new Date();
  44. //60 day
  45. Date enddate =new Date(begindate.getTime()+3000*24*60*60*1000L);
  46. CertificateValidity cv=new CertificateValidity(begindate,enddate);
  47. cinfo2.set(X509CertInfo.VALIDITY,cv);
  48. //设置新证书序列号
  49. int sn=(int)(begindate.getTime()/1000);
  50. CertificateSerialNumber csn=new CertificateSerialNumber(sn);
  51. cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);
  52. //设置新证书签发者
  53. cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);
  54. //设置新证书算法
  55. AlgorithmId algorithm = new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid);
  56. cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM, algorithm);
  57. // 创建证书
  58. X509CertImpl newcert=new X509CertImpl(cinfo2);
  59. // 签名
  60. newcert.sign(caprk,"sha1WithRSA");
  61. //打印到控制台,验证一下信息
  62. System.out.println(newcert);
  63. // 存入密钥库
  64. ks.setCertificateEntry(newStoreAlias, newcert);
  65. FileOutputStream out=new FileOutputStream(newStore);
  66. ks.store(out,newStorePass);
  67. out.close();
  68. }
  69. }

注意:SignCert.java须要进行以下的处理才干正常导包。(eclipse把默认訪问受限的api设成了error)

选中项目--右键--进入Properties(属性)视图

选中Java Build Path--点击Libraries--展开JRE System Library[JavaSE-1.6],选中Access rules这一项(假设没有,那就是JDK安装和配置的问题)。

Edit--点击Add--在Rule Pattern(规则式样)编辑你同意导入的类库,如本例中输入(sun/**),同意就是在Resolution选项中选中Accessible(当然,有些项目须要能够选择Forbidden、Discourage某些类库)。

然后重新启动就能够了。

6 数字签名与数字签名验证

(对字符串或文件进行签名以及对应数字签名验证)

Sign.java

//对字符串或文件进行签名

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package sign;
  2. import java.io.*;
  3. import java.security.*;
  4. import java.security.interfaces.*;
  5. public class Sign{
  6. public static void main(String args[ ]) throws Exception{
  7. //获取要签名的数据,放在data数组
  8. FileInputStream f=new FileInputStream("1.txt");
  9. int num=f.available();
  10. byte[ ] data=new byte[num];
  11. f.read(data);
  12. //获取私钥
  13. FileInputStream f2=new FileInputStream("RSA_priv.dat");
  14. ObjectInputStream b=new ObjectInputStream(f2);
  15. RSAPrivateKey prk=(RSAPrivateKey)b.readObject( );
  16. //获取Signature对象
  17. Signature s=Signature.getInstance("MD5WithRSA");
  18. //初始化
  19. s.initSign(prk);
  20. //传入要签名的数据
  21. s.update(data);
  22. System.out.println("");
  23. //签名
  24. byte[ ] signeddata=s.sign( );
  25. //保存签名
  26. FileOutputStream  f3=new FileOutputStream("Sign.dat");
  27. f3.write(signeddata);
  28. }
  29. }

CheckSign.java

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package sign;
  2. import java.io.*;
  3. import java.security.*;
  4. import java.security.interfaces.*;
  5. public class CheckSign{
  6. // 从签名者那儿得到msg.dat和sign.dat和公钥RSA_pub.dat
  7. // 改动msg.dat则数据无法通过验证,因此不怕网络传递过程中被改动,或signer不承认,由于仅仅有signer才干针对msg.dat得到sign.dat,
  8. // 假设checker将内容改为$300,则signer可要求其用签名验证,
  9. // 1.验证完整性  checker操心是否网络传递时将内容改动过了,或者是否确实是signer发来的,不是别人乱传的,经检查签名,正确,于是放心,
  10. // 2. 不可否认性。 signer不承认这个文件是自己发的,或说checker改过内容了,checker展示其签名sign.dat,仅仅有signer有私钥,能依据msg.dat生成这种内容,别人都不能。
  11. public static void main(String args[ ]) throws Exception{
  12. //获取数据,放在data数组
  13. FileInputStream f=new FileInputStream("1.txt");
  14. int num=f.available();
  15. byte[ ] data=new byte[num];
  16. f.read(data);
  17. //读签名
  18. FileInputStream f2=new FileInputStream("Sign.dat");
  19. int num2=f2.available();
  20. byte[ ] signeddata=new byte[num2];
  21. f2.read(signeddata);
  22. //读公钥
  23. FileInputStream f3=new FileInputStream("RSA_pub.dat");
  24. ObjectInputStream b=new ObjectInputStream(f3);
  25. RSAPublicKey  pbk=(RSAPublicKey)b.readObject( );
  26. //获取对象
  27. Signature s=Signature.getInstance("MD5WithRSA");
  28. //初始化
  29. s.initVerify(pbk);
  30. //传入原始数据
  31. s.update(data);
  32. boolean ok=false;
  33. try{
  34. //用签名验证原始数据
  35. ok=  s.verify(signeddata);
  36. System.out.println(ok);
  37. }
  38. catch(SignatureException e){ System.out.println(e);}
  39. System.out.println("Check Over");
  40. }
  41. }

7 生成RSA密钥

生成非对称加密的公钥和私钥-生成RSA密钥

非对称加密将加密的密钥和解密的密钥分开。A事先生成一对密钥,一个用于加密,称为公钥(公钥),一个用于解密,称为私钥。因为产生这一对密钥的一些数学特性,公钥加密的信息仅仅能用私钥解密。这样,A仅仅要将公钥对外公开,不论谁就能够使用这个公钥给A发送秘密信息了。A接收到加密信息后能够用私钥打开。因为仅仅须要传递公钥,而公钥仅仅能加密不能解密,因此即使攻击者知道了公钥也无济于事。

本文介绍的是RSA非对称加密算法。

GenerateRSAKey.java

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package sign;
  2. import java.io.*;
  3. import java.security.*;
  4. public class GenerateRSAKey {
  5. public static void main(String args[]) throws Exception{
  6. KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA");
  7. kpg.initialize(1024);
  8. KeyPair kp=kpg.genKeyPair();
  9. PublicKey pbkey=kp.getPublic();
  10. PrivateKey prkey=kp.getPrivate();
  11. //  保存公钥
  12. FileOutputStream  f1=new FileOutputStream("RSA_pub.dat");
  13. ObjectOutputStream b1=new  ObjectOutputStream(f1);
  14. b1.writeObject(pbkey);
  15. //  保存私钥
  16. FileOutputStream  f2=new FileOutputStream("RSA_priv.dat");
  17. ObjectOutputStream b2=new  ObjectOutputStream(f2);
  18. b2.writeObject(prkey);
  19. }
  20. }

8 使用Java程序将已签名的数字证书导入密钥库

首先读取CA的证书mytest.cer和用户收到的签名后的证书lf_signed.cer(由CA私钥签发),使用这两个证书组成证书链,然后从用户的密钥库读取私钥,最后运行KeyStore对象的setKeyEntry( )方法将私钥和证书一起写入密钥库,并使用store( )方法保存为文件就可以。

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.security.cert.*;
  4. /*
  5. * CA证书,已经签名的用户数字证书,用户密钥库名和password以及对应证书的私钥名称,新生成的证书名称和密钥库名以及password
  6. */
  7. public class ImportCert{
  8. public static void main(String args[ ]) throws Exception{
  9. //參数
  10. String cacert="new.cer";
  11. String lfcert="hqy.cer";
  12. String lfstore="mykeystore";
  13. char[] lfstorepass="080302".toCharArray( );
  14. char[] lfkeypass="080302".toCharArray( );
  15. //CA的证书
  16. CertificateFactory cf=CertificateFactory.getInstance("X.509");
  17. FileInputStream in1=new FileInputStream(cacert);
  18. java.security.cert.Certificate cac=cf.generateCertificate(in1);
  19. in1.close();
  20. //用户的签名证书
  21. FileInputStream in2=new FileInputStream(lfcert);
  22. java.security.cert.Certificate lfc=cf.generateCertificate(in2);
  23. in2.close();
  24. //证书链
  25. java.security.cert.Certificate[] cchain={lfc,cac};
  26. //用户的密钥库
  27. FileInputStream in3=new FileInputStream(lfstore);
  28. KeyStore ks=KeyStore.getInstance("JKS");
  29. ks.load(in3,lfstorepass);
  30. PrivateKey prk=(PrivateKey)ks.getKey("new",lfkeypass);
  31. //导入证书
  32. ks.setKeyEntry("new_signed",prk,lfstorepass,cchain);
  33. //保存密钥库
  34. FileOutputStream out4=new FileOutputStream("nostore");
  35. ks.store(out4,"080302".toCharArray());
  36. out4.close();
  37. }
  38. }

9 验证CertPath证书链

验证CertPath证书链-CertPathValidator类基于TrustAnchor验证证书链

CertPathValidator类中的validate( )方法能够使用现成的PKIX certification path验证算法直接验证CertPath类型的对象。方法的第一个參数传入要验证的CertPath对象,第二个參数传入PKIXParameters类型的对象,它提供了验证时所使用的參数。

为了得到PKIXParameters类型的对象,必须指定最信任哪些CA。

ValidateCP.java

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. package cert;
  2. import java.io.*;
  3. import java.security.cert.*;
  4. import java.security.cert.Certificate;
  5. import java.util.*;
  6. public class ValidateCP{
  7. public static void main(String args[ ]) throws Exception{
  8. String[] arg=new String[]{"cert/ibe-mao-signed.cer","cert/ibe-he.cer"};
  9. String trustAnchor = "cert/ibe-he.cer";
  10. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  11. int i;
  12. Listmylist = new ArrayList();
  13. for (i=0;i<arg.length;i++){
  14. FileInputStream in=new FileInputStream(arg[i]);
  15. Certificate c=cf.generateCertificate(in);
  16. mylist.add(c);
  17. }
  18. CertPath cp = cf.generateCertPath(mylist);
  19. //以上将证书列表转换成证书链
  20. //设置锚点
  21. FileInputStream in=new FileInputStream(trustAnchor);
  22. Certificate trust=cf.generateCertificate(in);
  23. // Create TrustAnchor
  24. TrustAnchor anchor = new TrustAnchor( (X509Certificate)trust,null);
  25. // Set the PKIX parameters
  26. PKIXParameters params = new PKIXParameters(Collections.singleton(anchor));
  27. params.setRevocationEnabled(false);
  28. CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
  29. try {
  30. PKIXCertPathValidatorResult result =(PKIXCertPathValidatorResult) cpv.validate(cp, params);
  31. System.out.println(result);
  32. System.out.println(result.getTrustAnchor());
  33. } catch (CertPathValidatorException cpve) {
  34. System.out.println("Validation failure, cert[" + cpve.getIndex() + "] :" + cpve.getMessage());
  35. }
  36. }
  37. }

10 使用CBC方式进行加密

对明文分组的不同处理方式形成了不同的加密方式,本章前面各节的程序中没有指定加密方式,默认的加密方式是ECB(Electronic Code Book),它对每一个明文分组独立进行处理。所以明文若8个字节一组同样的话(如本节开头的“Hello123Hello123Hello123Hello123”),加密出的结果也是8个字节一组同样的。

还有一种加密方式称为CBC(Cipher Block Chaining),它先加密第一个分组,然后使用得到的密文加密第二个分组,加密第二个分组得到的密文再加密第三个分组,……。这样,即使两个分组同样,得到的密文也不同。剩下的问题是假设两个密文的开头8个字节同样,依照这样的加密方式,仅仅要使用的密钥同样,则每条密文的开头8个字节也将同样。为此,CBC使用一个8个字节的随机数(称为初始向量,IV)来加密第一个分组,其作用类似于基于口令加密中的盐。

因此,使用CBC方式首先要生成初始向量,然后在获取password器对象时通过getInstance( )方法的參数设定加密方式,在password器初始化时传入初始向量。

//必须拥有DES加密密钥文件 DesKey.dat 和须要加密的文件1.txt

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.util.*;
  3. import java.security.*;
  4. import javax.crypto.*;
  5. import javax.crypto.spec.*;
  6. public class CBC{
  7. public static void main(String args[]) throws Exception{
  8. FileInputStream fi=new FileInputStream("1.txt");
  9. int l=fi.available();
  10. byte[] c=new byte[l];
  11. fi.read(c);
  12. FileInputStream f1=new FileInputStream("DesKey.dat");
  13. ObjectInputStream b=new ObjectInputStream(f1);
  14. Key k=(Key)b.readObject( );
  15. byte[] rand=new byte[8];
  16. Random r=new Random( );
  17. r.nextBytes(rand);
  18. IvParameterSpec iv=new IvParameterSpec(rand);
  19. Cipher cp=Cipher.getInstance("DESede/CBC/PKCS5Padding");
  20. cp.init(Cipher.ENCRYPT_MODE, k, iv);
  21. byte ptext[]=c;
  22. byte ctext[]=cp.doFinal(ptext);
  23. for(int i=0;i< div="">
  24. System.out.print(ctext[i] +",");
  25. }
  26. FileOutputStream f2=new FileOutputStream("SEncCBC.dat");
  27. f2.write(rand);
  28. f2.write(ctext);
  29. Cipher cp1=Cipher.getInstance("DESede/CBC/PKCS5Padding");
  30. cp1.init(Cipher.DECRYPT_MODE, k, iv);
  31. byte[] jm=cp1.doFinal(ctext);
  32. FileOutputStream fo=new FileOutputStream("2.txt");
  33. fo.write(jm);
  34. fo.close();
  35. }
  36. }

11 基于口令的加密解密

基于口令的加密和解密

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.util.*;
  3. import javax.crypto.*;
  4. import javax.crypto.spec.*;
  5. public class PBE{
  6. public static void main(String args[]) throws Exception{
  7. FileInputStream fi=new FileInputStream("1.rar");
  8. int l=fi.available();
  9. byte[] b=new byte[l];
  10. fi.read(b);
  11. //生成密钥
  12. char[] passwd="123".toCharArray();
  13. PBEKeySpec pbks=new PBEKeySpec(passwd);
  14. SecretKeyFactory kf=
  15. SecretKeyFactory.getInstance("PBEWithMD5AndDES");
  16. SecretKey k=kf.generateSecret(pbks);
  17. //生成盐
  18. byte[] salt=new byte[8];
  19. Random r=new Random( );
  20. r.nextBytes(salt);
  21. //创建并初始化password器
  22. Cipher cp=Cipher.getInstance("PBEWithMD5AndDES");
  23. PBEParameterSpec ps=new PBEParameterSpec(salt,1000);
  24. cp.init(Cipher.ENCRYPT_MODE, k,ps);
  25. //获取明文并加密
  26. byte ctext[]=cp.doFinal(b);
  27. //生成输出文件
  28. //准备解密
  29. Cipher cp1=Cipher.getInstance("PBEWithMD5AndDES");
  30. cp1.init(Cipher.DECRYPT_MODE, k,ps);
  31. byte ptext1[]=cp1.doFinal(ctext);
  32. FileOutputStream f=new FileOutputStream("2.rar");
  33. f.write(ptext1);
  34. f.close();
  35. }
  36. }

11 对称密钥的生成和保存-生成DES密钥

对称密钥的生成及以对象序列化方式保存

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import javax.crypto.*;
  3. public class GetDesKey{
  4. public static void main(String args[]) throws Exception{
  5. KeyGenerator kg=KeyGenerator.getInstance("DESede");
  6. kg.init(168);
  7. SecretKey k=kg.generateKey( );
  8. FileOutputStream  f=new FileOutputStream("DesKey.dat");
  9. ObjectOutputStream b=new  ObjectOutputStream(f);
  10. b.writeObject(k);//要写入对象数据仅仅能使用对象数据流
  11. byte[] c=k.getEncoded();//生成编码的字节表示展示一下,使用时能够删除
  12. for(int i=0;i<c.length;i++){
  13. System.out.print(c[i]);
  14. }}}

以字节保存对称密钥

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. public class Skey_kb{
  4. public static void main(String args[]) throws Exception{
  5. FileInputStream f=new FileInputStream("key1.dat");
  6. ObjectInputStream b=new ObjectInputStream(f);
  7. Key k=(Key)b.readObject( );
  8. byte[ ] kb=k.getEncoded( );
  9. FileOutputStream  f2=new FileOutputStream("keykb1.dat");
  10. f2.write(kb);
  11. // 打印密钥编码中的内容
  12. for(int i=0;i<kb.length;i++<span style="font-family: Verdana, Arial, Helvetica, sans-serif;"> ){</span>
  13. System.out.print(kb[i]+",");
  14. }
  15. }
  16. }

11 针对流的加密和解密

针对流的加密和解密

针对输入流的解密和解密

//必须拥有的文件:key1.dat(DES密钥文件),须要加密的文件1.rar

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.util.Scanner;
  4. import javax.crypto.*;
  5. public class StreamInCipher{
  6. public static void main(String args[]) throws Exception{
  7. Scanner reader=new Scanner(System.in);
  8. System.out.println("please choose the type of opration:1.加密  2.解密");
  9. int choose=reader.nextInt();
  10. String fi="1.zip";
  11. String fc="code.txt";
  12. String fo="2.zip";
  13. String f1=null;
  14. String f2=null;
  15. if(choose==1){
  16. f1=fi;
  17. f2=fc;
  18. }
  19. if(choose==2){
  20. f1=fc;
  21. f2=fo;
  22. }
  23. FileInputStream f=new FileInputStream("key1.dat");
  24. ObjectInputStream ob=new ObjectInputStream(f);
  25. Key k=(Key)ob.readObject( );
  26. Cipher cp=Cipher.getInstance("DESede");
  27. if(choose==1)
  28. cp.init(Cipher.ENCRYPT_MODE, k);
  29. else
  30. cp.init(Cipher.DECRYPT_MODE, k);
  31. FileInputStream in=new FileInputStream(f1);
  32. FileOutputStream out=new FileOutputStream(f2);
  33. CipherInputStream cin=new CipherInputStream(in, cp);
  34. int b=0;
  35. while( (b=cin.read())!=-1){
  36. out.write(b);
  37. System.out.println("ok!");
  38. System.out.println(b);
  39. }
  40. cin.close();
  41. out.close();
  42. in.close();
  43. }
  44. }

针对输出流的解密和解密

[java] view
plain
copyJava加密解密与数字证书的操作Java加密解密与数字证书的操作
  1. import java.io.*;
  2. import java.security.*;
  3. import java.util.Scanner;
  4. import javax.crypto.*;
  5. public class StreamOutCipher{
  6. public static void main(String args[]) throws Exception{
  7. Scanner reader=new Scanner(System.in);
  8. System.out.println("please choose the type of opration:1.加密  2.解密");
  9. int choose=reader.nextInt();
  10. String fi="1.zip";
  11. String fc="code.txt";
  12. String fo="2.zip";
  13. String f1=null;
  14. String f2=null;
  15. if(choose==1){
  16. f1=fi;
  17. f2=fc;
  18. }
  19. if(choose==2){
  20. f1=fc;
  21. f2=fo;
  22. }
  23. FileInputStream f=new FileInputStream("key1.dat");
  24. ObjectInputStream ob=new ObjectInputStream(f);
  25. Key k=(Key)ob.readObject( );
  26. Cipher cp=Cipher.getInstance("DESede");
  27. if(choose==1)
  28. cp.init(Cipher.ENCRYPT_MODE, k);
  29. else
  30. cp.init(Cipher.DECRYPT_MODE, k);
  31. FileInputStream in=new FileInputStream(f1);
  32. FileOutputStream out=new FileOutputStream(f2);
  33. CipherOutputStream cout=new CipherOutputStream(out, cp);
  34. int b=0;
  35. while( (b=in.read())!=-1){
  36. cout.write(b);
  37. //System.out.println(b);
  38. }
  39. cout.close();
  40. out.close();
  41. in.close();
  42. }
  43. }