java加密解密与数字证书的操作
2013-12-14 16:50
911 查看
1 keytool命令总结
一、创建数字证书交互模式
使用默认的密钥库.keystore(目录是c: Documents and Setting用户名)和算法(DSA)
keytool -genkey
默认的别名mykey
密钥库中可以存放多个条目(公钥/私钥对和证书),它们在密钥库中以别名(alias)区分。
keytool -genkey -alias mytest -keyalg RSA -keysize 1024 -keystore mykeystore -validity 4000
其中,
-keyalg参数可以指定密钥的算法,如果需要指定密钥的长度,可以再加上-keysize参数。密钥长度默认为1024位,使用DSA算法时,密钥长度必须在512到1024之间,并且是64的整数倍。
-keystore参数可以指定密钥库的名称。密钥库其实是存放密钥和证书的文件,密钥库对应的文件如果不存在自动创建。
-validity参数可以指定所创建的证书有效期是多少天。
非交互模式:
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认证指纹等额外信息)
keytool -list -v -keystore lfkeystore -alias lf
三、使用Keytool将数字证书导出到文件
将指定的证书从密钥库导出为没编码过的文件。
keytool -export -alias lf -file lf.cer -keystore lfkeystore
四、使用Keytool从文件中显示证书
keytool -printcert -file lf.cer
五、在Windows中从文件显示证书
只要文件名以.cer为后缀,Windows操作系统就可以直接识别。如在Windows中双击lf.cer图标,将出现证书窗口。其中包含了证书的所有者、颁发者、有效期等信息。
点击“详细资料”,可以看到证书的版本、序号、签名算法、颁发者、有效期、主题(即全名)、公钥算法、拇印算法、拇印等信息。其中的拇印即认证指纹。
六、密钥库的维护
使用Keytool删除指定条目
keytool -delete -alias tmp1 -keystore mykeystore
使用Keytool修改指定条目的口令
keytool -keypasswd -alias tmp1 -keystore mykeystore
(非交互模式:keytool -keypasswd -alias tmp1 -keystore mykeystore -storepass wshr.ut -keypass 123456 -new 080302,其中080302为原密码,123456为新密码 )
证书生成应用实例:
执行命令前先保证文件夹存在。例如:在c盘建立keystore文件夹
第一步:为服务器生成证书
确定域名:本机中域名解析修改文件是C:WINDOWSsystem32driversetchosts
使用keytool 为 Tomcat 生成证书和密钥库,假定目标机器的域名是“ hepengfei ”, keystore 文件存放在“ C:keystoreserver ”,口令为“ 080302 ”,命令如下:
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安装在客户端解决服务器信任问题:
keytool -export -keystore C:keystoreserver -alias serverkey -file c:keystoreserver.cer -storepass 080302
第二步:为客户端生成证书
(注意:个人证书的生成和使用比较特别,是分开的。先生成p12文件,然后导出cer文件,再将cer文件导入默认类型的keystore(JKS)文件)
这一步是为浏览器生成证书,以便让服务器来验证它。为了能将证书顺利导入至IE 和 Firefox ,证书格式应该是 PKCS12 ,因此,使用如下命令生成:
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服务器要信任客户端证书,就必须把客户端证书添加为服务器的信任认证。由于不能直接将 PKCS12 格式的证书库导入,我们必须先把客户端证书导出为一个单独的 CER 文件,使用如下命令:
keytool -export -alias MyPC -keystore C:keystoreuser.p12 -storetype PKCS12 -storepass 080302 -rfc -file C:keystoreuser.cer接着,将C:user.cer导入到服务器的证书库,添加为一个信任证书:
keytool -import -v -file C:keystoreuser.cer -keystore c:keystoreservertrust -alias user -storepass 080302
输入“是”确认完成。
通过list 命令查看:
keytool -list -keystore c:keystoreservertrust -storepass 080302
也可以考虑将服务器证书和服务器信任证书放到一个密钥库中
第四步:配置Tomcat 服务器
打开Tomcat 根目录下的 /conf/server.xml ,修改如下:
<="">
clientAuth="true" sslProtocol="TLS"
keystoreFile="C:JavaTomcatconfkeystoreserver" keystorePass="080302"
truststoreFile="C:JavaTomcatconfkeystoreservertrust" truststorePass="080302"
/>
详细解释见本节最前面介绍。
安装个人证书user.p12(密码: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四个
生成证书请求:
keytool -certreq -alias tomcat_server -sigalg MD5withRSA -file tomcat_server.csr -keypass 123456 -storepass 123456 -keystore server_keystore
PKCS12
使用Keytool列出pkcs12证书的内容
keytool -rfc -list -keystore tomcat_client.p12 -storetype pkcs12
使用Keytool导出pkcs12证书的公钥证书
keytool -keystore tomcat_client.p12 -storetype pkcs12 -export -alias mypc -file mypc.cer
将已经签名的证书导入密钥库(覆盖原来的公钥)
先导入证书链中的相关信任证书,再导入已经签名的证书(别名与私钥证书别名保持一样)。
2 Java程序实现密钥库的维护
2.1 Java程序列出密钥库所有条目
import java.util.*; import java.io.*; import java.security.*; public class ShowAlias{ public static void main(String args[ ]) throws Exception{ String pass="080302"; String name=".keystore"; FileInputStream in=new FileInputStream(name); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,pass.toCharArray()); Enumeratione=ks.aliases( ); while( e.hasMoreElements()) { System.out.println(e.nextElement()); } } }
2.2 Java程序修改密钥库口令
import java.io.*; import java.security.*; public class SetStorePass{ public static void main(String args[ ]) throws Exception{ char[ ] oldpass="080302".toCharArray(); char[ ] newpass="123456".toCharArray(); String name=".keystore"; FileInputStream in=new FileInputStream(name); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,oldpass); in.close(); FileOutputStream output=new FileOutputStream(name); ks.store(output,newpass); output.close(); } }
2.3 Java程序修改密钥库条目的口令及添加条目
package test; import java.io.*; import java.security.*; import java.security.cert.Certificate; public class SetKeyPass{ public static void main(String args[ ]) throws Exception{ //读取相关参数 String name=".keystore"; String alias="mykey"; char[ ] storepass="123456".toCharArray(); char[ ] oldkeypass="080302".toCharArray(); char[ ] newkeypass="123456".toCharArray(); //获取密钥库.keystore的KeyStore对象,并加载密钥库 FileInputStream in=new FileInputStream(name); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,storepass); //获取别名对应的条目的证书链 Certificate[ ] cchain=ks.getCertificateChain(alias); //读取别名对应的条目的私钥 PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass); //向密钥库中添加新的条目 ks.setKeyEntry(alias,pk,newkeypass,cchain); in.close(); //将KeyStore对象内容写入新文件 FileOutputStream output=new FileOutputStream("333"); ks.store(output,storepass); output.close(); } }
2.4 Java程序检验别名及删除条目
package test; import java.io.*; import java.security.*; public class DeleteAlias{ public static void main(String args[ ]) throws Exception{ String pass = "123456"; String name = ".keystore"; String alias = "mykey"; FileInputStream in=new FileInputStream(name); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,pass.toCharArray()); if (ks.containsAlias(alias)){ ks.deleteEntry(alias); FileOutputStream output=new FileOutputStream(name); ks.store(output,pass.toCharArray()); System.out.println("Alias "+alias+" deleted"); }else{ System.out.println("Alias not exist"); } } }
3 Java程序读取证书和显示证书指定信息
3.1 Java程序从证书文件读取证书
import java.io.*; import java.security.cert.*; public class PrintCert{ public static void main(String args[ ]) throws Exception{ CertificateFactory cf=CertificateFactory.getInstance("X.509"); FileInputStream in=new FileInputStream("my.cer"); Certificate c=cf.generateCertificate(in); in.close(); String s=c.toString( ); // 显示证书 FileOutputStream fout=new FileOutputStream("tmp.txt"); BufferedWriter out= new BufferedWriter(new OutputStreamWriter(fout)); out.write(s,0,s.length( )); out.close(); } }
3.2 Java程序从密钥库直接读取证书
import java.io.*; import java.security.*; import java.security.cert.Certificate; public class PrintCert2{ public static void main(String args[ ]) throws Exception{ String pass="080302"; String alias="mykey"; String name=".keystore"; FileInputStream in=new FileInputStream(name); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,pass.toCharArray()); Certificate c=ks.getCertificate(alias); in.close(); System.out.println(c.toString( )); } }
3.3 Java程序显示证书指定信息(全名/公钥/签名等)
import java.io.*; import java.security.*; import java.security.cert.*; import java.math.*; public class ShowCertInfo{ public static void main(String args[ ]) throws Exception{ CertificateFactory cf=CertificateFactory.getInstance("X.509"); FileInputStream in=new FileInputStream("my.cer"); java.security.cert.Certificate c=cf.generateCertificate(in); in.close(); X509Certificate t=(X509Certificate) c; System.out.println("版本号 "+t.getVersion()); System.out.println("序列号 "+t.getSerialNumber().toString(16)); System.out.println("全名 "+t.getSubjectDN()); System.out.println("签发者全名n"+t.getIssuerDN()); System.out.println("有效期起始日 "+t.getNotBefore()); System.out.println("有效期截至日 "+t.getNotAfter()); System.out.println("签名算法 "+t.getSigAlgName()); byte[] sig=t.getSignature(); System.out.println("签名n"+new BigInteger(sig).toString(16)); PublicKey pk=t.getPublicKey(); byte[ ] pkenc=pk.getEncoded(); System.out.println("公钥"); for(int i=0;i< div=""> System.out.print(pkenc[i]+","); } } }
4 ssl/https双向验证的配置与证书库的生成
1.SSL认证不需要特别配置,相关证书库生成看https认证中的相关部分
2.HTTPS认证
一、基本概念
1.单向认证,就是传输的数据加密过了,但是不会校验客户端的来源
2.双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址
如果只是加密,我感觉单向就行了。
如果想要用系统的人没有证书就访问不了系统的话,就采用双向
二、服务器配置:
打开Tomcat 根目录下的 /conf/server.xml 修改server.xml
客户端证书注册名称必须与域名一致,否则无法验证。
例如访问https://127.0.0.1:8443/Test必须使用名称为127.0.0.1的证书,
访问https://hepengfei:8443/Test必须使用名称为hepengfei的证书,
本机中域名解析修改文件是C:WINDOWSsystem32driversetchosts
端口号改为8443,为自定义端口 访问https://127.0.0.1:8443/Test
端口号改为443,则为默认端口 访问https://127.0.0.1/Test
clientAuth="true"为双向认证 clientAuth="false"为单向认证
使用密钥库文件和密码(自己使用的证书)
信任密钥库文件和密码(含有客户端证书或其根证书)
<="" 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文件夹
第一步:为服务器生成证书
确定域名:本机中域名解析修改文件是C:WINDOWSsystem32driversetchosts
使用keytool 为 Tomcat 生成证书和密钥库,假定目标机器的域名是“ hepengfei ”, keystore 文件存放在“ C:keystoreserver ”,口令为“ 080302 ”,命令如下:
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安装在客户端解决服务器信任问题:
keytool -export -keystore C:keystoreserver -alias serverkey -file c:keystoreserver.cer -storepass 080302
第二步:为客户端生成证书
(注意:个人证书的生成和使用比较特别,是分开的。先生成p12文件,然后导出cer文件,再将cer文件导入默认类型的keystore(JKS)文件)
这一步是为浏览器生成证书,以便让服务器来验证它。为了能将证书顺利导入至IE 和 Firefox ,证书格式应该是 PKCS12 ,因此,使用如下命令生成:
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服务器要信任客户端证书,就必须把客户端证书添加为服务器的信任认证。由于不能直接将 PKCS12 格式的证书库导入,我们必须先把客户端证书导出为一个单独的 CER 文件,使用如下命令:
keytool -export -alias MyPC -keystore C:keystoreuser.p12 -storetype PKCS12 -storepass 080302 -rfc -file C:keystoreuser.cer接着,将C:user.cer导入到服务器的证书库,添加为一个信任证书:
keytool -import -v -file C:keystoreuser.cer -keystore c:keystoreservertrust -alias user -storepass 080302
输入“是”确认完成。
通过list 命令查看:
keytool -list -keystore c:keystoreservertrust -storepass 080302
也可以考虑将服务器证书和服务器信任证书放到一个密钥库中
第四步:配置Tomcat 服务器
打开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(密码: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 数字签名-对数字证书的数字签名
import java.io.*; import java.security.*; import java.security.cert.*; import java.util.*; import sun.security.x509.*; /* * CA密钥库和其密码、CA中要使用的条目和其密码,新密钥库和其密码、新的条目名称 * 特别注意:java中有些类得到特别保护(比如X509CertImpl),必须设置规则才能访问【项目属性-Java Build Path-JRE * System Library-Access Rules-Edit-"sun/**"(Accessible)】 */ public class SignCert{ public static void main(String args[ ]) throws Exception{ String signerName = "keystore/ibe"; String signerAlias = "he"; char[] signerStorePass = "080302".toCharArray( ); char[] signerKeyPass = "080302".toCharArray( ); String CertName = "cert/ibe-mao.cer"; String newStore = "keystore/newstore"; String newStoreAlias = "mao"; char[] newStorePass = "080302".toCharArray(); // CA证书 FileInputStream in=new FileInputStream(signerName); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in,signerStorePass); java.security.cert.Certificate c1=ks.getCertificate(signerAlias); PrivateKey caprk=(PrivateKey)ks.getKey(signerAlias,signerKeyPass); in.close(); //得到签发者 byte[] encod1=c1.getEncoded(); X509CertImpl cimp1=new X509CertImpl(encod1); X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); //要签名的证书 CertificateFactory cf=CertificateFactory.getInstance("X.509"); FileInputStream in2=new FileInputStream(CertName); java.security.cert.Certificate c2=cf.generateCertificate(in2); in2.close(); byte[] encod2=c2.getEncoded(); X509CertImpl cimp2=new X509CertImpl(encod2); X509CertInfo cinfo2=(X509CertInfo)cimp2.get( X509CertImpl.NAME+"."+X509CertImpl.INFO); //设置新证书有效期 Date begindate =new Date(); //60 day Date enddate =new Date(begindate.getTime()+3000*24*60*60*1000L); CertificateValidity cv=new CertificateValidity(begindate,enddate); cinfo2.set(X509CertInfo.VALIDITY,cv); //设置新证书序列号 int sn=(int)(begindate.getTime()/1000); CertificateSerialNumber csn=new CertificateSerialNumber(sn); cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn); //设置新证书签发者 cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer); //设置新证书算法 AlgorithmId algorithm = new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid); cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM, algorithm); // 创建证书 X509CertImpl newcert=new X509CertImpl(cinfo2); // 签名 newcert.sign(caprk,"sha1WithRSA"); //打印到控制台,验证一下信息 System.out.println(newcert); // 存入密钥库 ks.setCertificateEntry(newStoreAlias, newcert); FileOutputStream out=new FileOutputStream(newStore); ks.store(out,newStorePass); out.close(); } }
注意: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
//对字符串或文件进行签名
package sign; import java.io.*; import java.security.*; import java.security.interfaces.*; public class Sign{ public static void main(String args[ ]) throws Exception{ //获取要签名的数据,放在data数组 FileInputStream f=new FileInputStream("1.txt"); int num=f.available(); byte[ ] data=new byte[num]; f.read(data); //获取私钥 FileInputStream f2=new FileInputStream("RSA_priv.dat"); ObjectInputStream b=new ObjectInputStream(f2); RSAPrivateKey prk=(RSAPrivateKey)b.readObject( ); //获取Signature对象 Signature s=Signature.getInstance("MD5WithRSA"); //初始化 s.initSign(prk); //传入要签名的数据 s.update(data); System.out.println(""); //签名 byte[ ] signeddata=s.sign( ); //保存签名 FileOutputStream f3=new FileOutputStream("Sign.dat"); f3.write(signeddata); } }
CheckSign.java
package sign; import java.io.*; import java.security.*; import java.security.interfaces.*; public class CheckSign{ // 从签名者那儿得到msg.dat和sign.dat和公钥RSA_pub.dat // 修改msg.dat则数据无法通过验证,因此不怕网络传递过程中被修改,或signer不承认,因为只有signer才能针对msg.dat得到sign.dat, // 如果checker将内容改为$300,则signer可要求其用签名验证, // 1.验证完整性 checker担心是否网络传递时将内容修改过了,或者是否确实是signer发来的,不是别人乱传的,经检查签名,正确,于是放心, // 2. 不可否认性。 signer不承认这个文件是自己发的,或说checker改过内容了,checker展示其签名sign.dat,只有signer有私钥,能根据msg.dat生成这样的内容,别人都不能。 public static void main(String args[ ]) throws Exception{ //获取数据,放在data数组 FileInputStream f=new FileInputStream("1.txt"); int num=f.available(); byte[ ] data=new byte[num]; f.read(data); //读签名 FileInputStream f2=new FileInputStream("Sign.dat"); int num2=f2.available(); byte[ ] signeddata=new byte[num2]; f2.read(signeddata); //读公钥 FileInputStream f3=new FileInputStream("RSA_pub.dat"); ObjectInputStream b=new ObjectInputStream(f3); RSAPublicKey pbk=(RSAPublicKey)b.readObject( ); //获取对象 Signature s=Signature.getInstance("MD5WithRSA"); //初始化 s.initVerify(pbk); //传入原始数据 s.update(data); boolean ok=false; try{ //用签名验证原始数据 ok= s.verify(signeddata); System.out.println(ok); } catch(SignatureException e){ System.out.println(e);} System.out.println("Check Over"); } }
7 生成RSA密钥
生成非对称加密的公钥和私钥-生成RSA密钥非对称加密将加密的密钥和解密的密钥分开。A事先生成一对密钥,一个用于加密,称为公钥(公钥),一个用于解密,称为私钥。由于产生这一对密钥的一些数学特性,公钥加密的信息只能用私钥解密。这样,A只要将公钥对外公开,不论谁就可以使用这个公钥给A发送秘密信息了。A接收到加密信息后可以用私钥打开。由于只需要传递公钥,而公钥只能加密不能解密,因此即使攻击者知道了公钥也无济于事。
本文介绍的是RSA非对称加密算法。
GenerateRSAKey.java
package sign; import java.io.*; import java.security.*; public class GenerateRSAKey { public static void main(String args[]) throws Exception{ KeyPairGenerator kpg=KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); KeyPair kp=kpg.genKeyPair(); PublicKey pbkey=kp.getPublic(); PrivateKey prkey=kp.getPrivate(); // 保存公钥 FileOutputStream f1=new FileOutputStream("RSA_pub.dat"); ObjectOutputStream b1=new ObjectOutputStream(f1); b1.writeObject(pbkey); // 保存私钥 FileOutputStream f2=new FileOutputStream("RSA_priv.dat"); ObjectOutputStream b2=new ObjectOutputStream(f2); b2.writeObject(prkey); } }
8 使用Java程序将已签名的数字证书导入密钥库
首先读取CA的证书mytest.cer和用户收到的签名后的证书lf_signed.cer(由CA私钥签发),使用这两个证书组成证书链,然后从用户的密钥库读取私钥,最后执行KeyStore对象的setKeyEntry( )方法将私钥和证书一起写入密钥库,并使用store( )方法保存为文件即可。import java.io.*; import java.security.*; import java.security.cert.*; /* * CA证书,已经签名的用户数字证书,用户密钥库名和密码以及相应证书的私钥名称,新生成的证书名称和密钥库名以及密码 */ public class ImportCert{ public static void main(String args[ ]) throws Exception{ //参数 String cacert="new.cer"; String lfcert="hqy.cer"; String lfstore="mykeystore"; char[] lfstorepass="080302".toCharArray( ); char[] lfkeypass="080302".toCharArray( ); //CA的证书 CertificateFactory cf=CertificateFactory.getInstance("X.509"); FileInputStream in1=new FileInputStream(cacert); java.security.cert.Certificate cac=cf.generateCertificate(in1); in1.close(); //用户的签名证书 FileInputStream in2=new FileInputStream(lfcert); java.security.cert.Certificate lfc=cf.generateCertificate(in2); in2.close(); //证书链 java.security.cert.Certificate[] cchain={lfc,cac}; //用户的密钥库 FileInputStream in3=new FileInputStream(lfstore); KeyStore ks=KeyStore.getInstance("JKS"); ks.load(in3,lfstorepass); PrivateKey prk=(PrivateKey)ks.getKey("new",lfkeypass); //导入证书 ks.setKeyEntry("new_signed",prk,lfstorepass,cchain); //保存密钥库 FileOutputStream out4=new FileOutputStream("nostore"); ks.store(out4,"080302".toCharArray()); out4.close(); } }
9 验证CertPath证书链
验证CertPath证书链-CertPathValidator类基于TrustAnchor验证证书链CertPathValidator类中的validate( )方法可以使用现成的PKIX certification path验证算法直接验证CertPath类型的对象。方法的第一个参数传入要验证的CertPath对象,第二个参数传入PKIXParameters类型的对象,它提供了验证时所使用的参数。
为了得到PKIXParameters类型的对象,必须指定最信任哪些CA。
ValidateCP.java
package cert; import java.io.*; import java.security.cert.*; import java.security.cert.Certificate; import java.util.*; public class ValidateCP{ public static void main(String args[ ]) throws Exception{ String[] arg=new String[]{"cert/ibe-mao-signed.cer","cert/ibe-he.cer"}; String trustAnchor = "cert/ibe-he.cer"; CertificateFactory cf = CertificateFactory.getInstance("X.509"); int i; Listmylist = new ArrayList(); for (i=0;i<arg.length;i++){ FileInputStream in=new FileInputStream(arg[i]); Certificate c=cf.generateCertificate(in); mylist.add(c); } CertPath cp = cf.generateCertPath(mylist); //以上将证书列表转换成证书链 //设置锚点 FileInputStream in=new FileInputStream(trustAnchor); Certificate trust=cf.generateCertificate(in); // Create TrustAnchor TrustAnchor anchor = new TrustAnchor( (X509Certificate)trust,null); // Set the PKIX parameters PKIXParameters params = new PKIXParameters(Collections.singleton(anchor)); params.setRevocationEnabled(false); CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); try { PKIXCertPathValidatorResult result =(PKIXCertPathValidatorResult) cpv.validate(cp, params); System.out.println(result); System.out.println(result.getTrustAnchor()); } catch (CertPathValidatorException cpve) { System.out.println("Validation failure, cert[" + cpve.getIndex() + "] :" + cpve.getMessage()); } } }
10 使用CBC方式进行加密
对明文分组的不同处理方式形成了不同的加密方式,本章前面各节的程序中没有指定加密方式,默认的加密方式是ECB(Electronic Code Book),它对每个明文分组独立进行处理。所以明文若8个字节一组相同的话(如本节开头的“Hello123Hello123Hello123Hello123”),加密出的结果也是8个字节一组相同的。另一种加密方式称为CBC(Cipher Block Chaining),它先加密第一个分组,然后使用得到的密文加密第二个分组,加密第二个分组得到的密文再加密第三个分组,……。这样,即使两个分组相同,得到的密文也不同。剩下的问题是如果两个密文的开头8个字节相同,按照这种加密方式,只要使用的密钥相同,则每条密文的开头8个字节也将相同。为此,CBC使用一个8个字节的随机数(称为初始向量,IV)来加密第一个分组,其作用类似于基于口令加密中的盐。
因此,使用CBC方式首先要生成初始向量,然后在获取密码器对象时通过getInstance( )方法的参数设定加密方式,在密码器初始化时传入初始向量。
//必须拥有DES加密密钥文件 DesKey.dat 和需要加密的文件1.txt
import java.io.*; import java.util.*; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; public class CBC{ public static void main(String args[]) throws Exception{ FileInputStream fi=new FileInputStream("1.txt"); int l=fi.available(); byte[] c=new byte[l]; fi.read(c); FileInputStream f1=new FileInputStream("DesKey.dat"); ObjectInputStream b=new ObjectInputStream(f1); Key k=(Key)b.readObject( ); byte[] rand=new byte[8]; Random r=new Random( ); r.nextBytes(rand); IvParameterSpec iv=new IvParameterSpec(rand); Cipher cp=Cipher.getInstance("DESede/CBC/PKCS5Padding"); cp.init(Cipher.ENCRYPT_MODE, k, iv); byte ptext[]=c; byte ctext[]=cp.doFinal(ptext); for(int i=0;i< div=""> System.out.print(ctext[i] +","); } FileOutputStream f2=new FileOutputStream("SEncCBC.dat"); f2.write(rand); f2.write(ctext); Cipher cp1=Cipher.getInstance("DESede/CBC/PKCS5Padding"); cp1.init(Cipher.DECRYPT_MODE, k, iv); byte[] jm=cp1.doFinal(ctext); FileOutputStream fo=new FileOutputStream("2.txt"); fo.write(jm); fo.close(); } }
11 基于口令的加密解密
基于口令的加密和解密
import java.io.*; import java.util.*; import javax.crypto.*; import javax.crypto.spec.*; public class PBE{ public static void main(String args[]) throws Exception{ FileInputStream fi=new FileInputStream("1.rar"); int l=fi.available(); byte[] b=new byte[l]; fi.read(b); //生成密钥 char[] passwd="123".toCharArray(); PBEKeySpec pbks=new PBEKeySpec(passwd); SecretKeyFactory kf= SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKey k=kf.generateSecret(pbks); //生成盐 byte[] salt=new byte[8]; Random r=new Random( ); r.nextBytes(salt); //创建并初始化密码器 Cipher cp=Cipher.getInstance("PBEWithMD5AndDES"); PBEParameterSpec ps=new PBEParameterSpec(salt,1000); cp.init(Cipher.ENCRYPT_MODE, k,ps); //获取明文并加密 byte ctext[]=cp.doFinal(b); //生成输出文件 //准备解密 Cipher cp1=Cipher.getInstance("PBEWithMD5AndDES"); cp1.init(Cipher.DECRYPT_MODE, k,ps); byte ptext1[]=cp1.doFinal(ctext); FileOutputStream f=new FileOutputStream("2.rar"); f.write(ptext1); f.close(); } }
11 对称密钥的生成和保存-生成DES密钥
对称密钥的生成及以对象序列化方式保存import java.io.*; import javax.crypto.*; public class GetDesKey{ public static void main(String args[]) throws Exception{ KeyGenerator kg=KeyGenerator.getInstance("DESede"); kg.init(168); SecretKey k=kg.generateKey( ); FileOutputStream f=new FileOutputStream("DesKey.dat"); ObjectOutputStream b=new ObjectOutputStream(f); b.writeObject(k);//要写入对象数据只能使用对象数据流 byte[] c=k.getEncoded();//生成编码的字节表示展示一下,使用时可以删除 for(int i=0;i<c.length;i++){ System.out.print(c[i]); }}}
以字节保存对称密钥
import java.io.*; import java.security.*; public class Skey_kb{ public static void main(String args[]) throws Exception{ FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream b=new ObjectInputStream(f); Key k=(Key)b.readObject( ); byte[ ] kb=k.getEncoded( ); FileOutputStream f2=new FileOutputStream("keykb1.dat"); f2.write(kb); // 打印密钥编码中的内容 for(int i=0;i<kb.length;i++ ){ System.out.print(kb[i]+","); } } }
11 针对流的加密和解密
针对流的加密和解密针对输入流的解密和解密
//必须拥有的文件:key1.dat(DES密钥文件),需要加密的文件1.rar
import java.io.*; import java.security.*; import java.util.Scanner; import javax.crypto.*; public class StreamInCipher{ public static void main(String args[]) throws Exception{ Scanner reader=new Scanner(System.in); System.out.println("please choose the type of opration:1.加密 2.解密"); int choose=reader.nextInt(); String fi="1.zip"; String fc="code.txt"; String fo="2.zip"; String f1=null; String f2=null; if(choose==1){ f1=fi; f2=fc; } if(choose==2){ f1=fc; f2=fo; } FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream ob=new ObjectInputStream(f); Key k=(Key)ob.readObject( ); Cipher cp=Cipher.getInstance("DESede"); if(choose==1) cp.init(Cipher.ENCRYPT_MODE, k); else cp.init(Cipher.DECRYPT_MODE, k); FileInputStream in=new FileInputStream(f1); FileOutputStream out=new FileOutputStream(f2); CipherInputStream cin=new CipherInputStream(in, cp); int b=0; while( (b=cin.read())!=-1){ out.write(b); System.out.println("ok!"); System.out.println(b); } cin.close(); out.close(); in.close(); } }
针对输出流的解密和解密
import java.io.*; import java.security.*; import java.util.Scanner; import javax.crypto.*; public class StreamOutCipher{ public static void main(String args[]) throws Exception{ Scanner reader=new Scanner(System.in); System.out.println("please choose the type of opration:1.加密 2.解密"); int choose=reader.nextInt(); String fi="1.zip"; String fc="code.txt"; String fo="2.zip"; String f1=null; String f2=null; if(choose==1){ f1=fi; f2=fc; } if(choose==2){ f1=fc; f2=fo; } FileInputStream f=new FileInputStream("key1.dat"); ObjectInputStream ob=new ObjectInputStream(f); Key k=(Key)ob.readObject( ); Cipher cp=Cipher.getInstance("DESede"); if(choose==1) cp.init(Cipher.ENCRYPT_MODE, k); else cp.init(Cipher.DECRYPT_MODE, k); FileInputStream in=new FileInputStream(f1); FileOutputStream out=new FileOutputStream(f2); CipherOutputStream cout=new CipherOutputStream(out, cp); int b=0; while( (b=in.read())!=-1){ cout.write(b); //System.out.println(b); } cout.close(); out.close(); in.close(); } }
相关文章推荐
- Java加密解密与数字证书的操作
- JAVA加密解密之数字证书
- Java数字证书对文件、加密、解密、签名、校验签名(一)
- Java数字证书对文件、加密、解密、签名、校验签名(二)
- Java数字证书对文件/加密/解密/签名/校验签名
- Java数字证书对文件、加密、解密、签名、校验签名
- 第五十篇: JAVA加密解密之数字证书
- 使用X.509数字证书加密解密实务(一)-- 证书的获得和管理
- JAVA对数字证书的常用操作
- 公钥私钥加密解密数字证书数字签名详解
- JAVA和PYTHON同时实现AES的加密解密操作---且生成的BASE62编码一致
- JAVA对数字证书的常用操作(转贴)
- 公钥私钥加密解密数字证书数字签名详解【转】
- PHP通过OpenSSL生成证书、密钥并且加密解密数据,以及公钥,私钥和数字签名的理解
- Java加密技术(八)——数字证书
- Java-web下使用RSA进行加密解密操作
- 使用X.509数字证书加密解密实务(三)-- 使用RSA证书结合对称加密技术加密长数据
- Visual Studio 2017中使用正则修改部分内容 如何使用ILAsm与ILDasm修改.Net exe(dll)文件 C#学习-图解教程(1):格式化数字字符串 小程序开发之图片转Base64(C#、.Net) jquery遍历table为每一个单元格取值及赋值 。net加密解密相关方法 .net关于坐标之间一些简单操作
- 【Java】通过DES加密和解密工具,对字符串进行加密和解密操作
- 初步理解加密,解密,数字签名,数字证书