数字证书操作

来源:互联网 发布:线上交易平台数据安全 编辑:程序博客网 时间:2024/05/23 16:43

转:http://changshi.chen.blog.163.com/blog/static/25423895200922274320258/

 

证书生成命令:keytool -genkey -alias abnerCA -keyalg RSA -keysize 1024 -keystore abnerCALib -validity 3650

证书显示:keytool –list –keystore abnerCALib

导出证书到证书文件:keytool -export -alias abnerCA -file abnerCA.cer -keystore abnerCALib

查看证书信息:keytool –printcert –file abnerCA.cer

证书删除:keytool -delete -alias abnerCA -keystore abnerCALib

CA给数字证书的签名操作:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.util.Calendar;
import java.util.Date;

import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateValidity;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;

 /**
 * <p>Description: 该程序根据签发者(CA)的证书信息(即CA的私钥)来对被签发者
 * 的证书进行签名,过程即是使用CA的证书和被签证书来重构形成一个新的证书</p>
 * @author abnerchai
 * @version 1.0
 */  
 public class Test {
  public static void main(String[] args) throws Exception{
//   存放CA证书和被签证书的证书库的访问密码
   char[] storepass = "100200".toCharArray();
//   CA数字证书条目的访问密码    
   char[] cakeypass = "200100".toCharArray();
//   CA证书在证书库中的别名,这个CA的证书用来签名其它的证书
   String alias = "missionCA";
//   存放CA证书和被签证书的证书库的名字
   String name = "abnerCALib";
//   新证书库的名字,如果需要将签名后的证书放入新库,这是新库的名字
   String newLib = "SignedLib";
//   设置新库的访问密码
   char[] newLibPass = "100200".toCharArray();
//   被签证书的证书文件名
   String cerFileName = "abnerCA.cer";
//   被签证书在证书库中的alias别名
   String aliasName = "abnerCA";
//   被签证书的条目在证书库的私钥密码
   char[] namePass = "200100".toCharArray();
//   被签证书的有效期,以年为单位,以当前时间开始计算
   int n =3;
//   序列号可自己定义,这里定义的意义为2004年6月签发,是本年度CA签发的第多少个以001计算,要求唯一
   int sn = 200406001;
//   签名后新产生的被签过名的证书在库中的别名
   String afteraliasName = "abnerCA_Signed";
//   签名后新产生的被签过名的证书在库的条目的私钥的密码   
   char[] afterNewPass = "200100".toCharArray();
//   装载证书库
   FileInputStream in = new FileInputStream(name);
//   JKS为证书库的类型
   KeyStore ks = KeyStore.getInstance("JKS");
   ks.load(in,storepass);
//   从证书库中读出签发者(CA)的证书
   java.security.cert.Certificate cl = ks.getCertificate(alias);
//   根据别名和证书密码读出CA证书的私钥
   PrivateKey privateKey = (PrivateKey)ks.getKey(alias,cakeypass);
   in.close();
//   从证书库中读出的签发者(CA)的证书中提取签发者的信息
   byte[] encodl = cl.getEncoded();//提取证书的编码,这里是字母l不是数据字1
   X509CertImpl cimpl = new X509CertImpl(encodl);
//   这里是字母l不是数据字1,根据证书的编码创建X509CertImpl类型的对象
//   根据上面的对象获得X509CertInfo类型的对象,该对象封装了证书的全部内容。
   X509CertInfo cinfo_first =
    (X509CertInfo)cimpl.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);
//   然后获得X500Name类型的签发者信息
   X500Name issuer = (X500Name)
    cinfo_first.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME);
//   获取待签发的证书,即获取被签发者的证书
//   可从密钥库中获取,也可从导出的证书文件中获取,这里给出两种方式   ////////////////////////////////////////////////////////////////////////

//   方式一、采用从导出的cer文件中获取 start

//////////////////////////////////////////////////////////////////////////////   /

   /*

   CertificateFactory cf = CertificateFactory.getInstance("X.509");
//   X.509是使用最多的一种数字证书标准

   FileInputStream in2 = new FileInputStream(cerFileName);//被签证书文件

   java.security.cert.Certificate c2 = cf.generateCertificate(in2);
//   生成需要被签的证书
   in2.close();
   byte[] encod2 = c2.getEncoded();
   X509CertImpl cimp2 = new X509CertImpl(encod2);

//   获得被签证书的详细内容,然后根据这个证书生成新证书

   X509CertInfo cinfo_second =
      (X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);
   */

//////////////////////////////////////////////////////////////////////////////   /

//   end 方式一

//////////////////////////////////////////////////////////////////////////////   /

//////////////////////////////////////////////////////////////////////////////   /

//   方式二、从证书库中读出被签的证书 start

//////////////////////////////////////////////////////////////////////////////   /

   java.security.cert.Certificate c3 = ks.getCertificate(aliasName);
//   从证书库中读出被签证书,然后生成新的证书
   byte[] encod3 = c3.getEncoded();
   X509CertImpl cimp3 = new X509CertImpl(encod3);
   X509CertInfo cinfo_second =
    (X509CertInfo)cimp3.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);

//   end方式二

//////////////////////////////////////////////////////////////////////////
//   设置新证书的有效期,使之为当前向后n年有效,新证书的

//   截止日期不能超过CA证书的有效日期

   Date beginDate = new Date();
   Calendar cal = Calendar.getInstance();
   cal.setTime(beginDate);
   cal.add(cal.YEAR,n);
   Date endDate = cal.getTime();
   CertificateValidity cv = new CertificateValidity(beginDate,endDate);
   cinfo_second.set(X509CertInfo.VALIDITY,cv);
//   设置新证书的序列号

   CertificateSerialNumber csn = new CertificateSerialNumber(sn);
   cinfo_second.set(X509CertInfo.SERIAL_NUMBER,csn);
//   设置新证书的签发者
   cinfo_second.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);
//   新的签发者是CA的证书中读出来的

//   设置新证书的算法,指定CA签名该证书所使用的算法为md5WithRSA

   AlgorithmId algorithm = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
   cinfo_second.set(CertificateAlgorithmId.NAME+"."+
     CertificateAlgorithmId.ALGORITHM,algorithm);

//   创建新的签名后的证书

   X509CertImpl newcert = new X509CertImpl(cinfo_second);

//   签名,使用CA证书的私钥进行签名,签名使用的算法为MD5WithRSA

   newcert.sign(privateKey,"MD5WithRSA");//这样便得到了经过CA签名后的证书

//   把新证书存入证书库
//   把新生成的证书存入一个新的证书库,也可以存入原证书库,
//   存入新证书库,则新证书库中不仅包含原证书库中的所有条目,
//   而且新增加了一个这次产生的条目。注意,这时,新产生的签名后的证书只
//   包括公钥和主体信息及签名信息,不包括私钥信息。这里给出两种方式。
//////////////////////////////////////////////////////////////////////////   /

//   方式一:存入新密钥库

//////////////////////////////////////////////////////////////////////////   /

   /*
   ks.setCertificateEntry(afteraliasName,newcert);
   FileOutputStream out = new FileOutputStream(newLib);
//   存入新库signedLib,并设置新库的库访问密码
   ks.store(out,newLibPass);
   out.close();
   */

//////////////////////////////////////////////////////////////////////////   /

//   end 方式一

//////////////////////////////////////////////////////////////////////////   /

//   也可以采用另外一种方式,存入原证书库中

//   存入原库中,即在原证书库中增加一条证书,这个证书是原证书经过签名后的证书

//   这个新证书含有私钥和私钥密码

//////////////////////////////////////////////////////////////////////////   /

//   方式二,存入原密钥库

//////////////////////////////////////////////////////////////////////////   /

//   先在原库中读出被签证书的私钥

   PrivateKey prk = (PrivateKey)ks.getKey(aliasName,namePass);
   java.security.cert.Certificate[] cchain = {newcert};
//   存入原来的库,第二个参数为原证书的私钥,第三个参数为新证书的私钥密码,第三个参数为新证书

   ks.setKeyEntry(afteraliasName,prk,afterNewPass,cchain); //用新密钥替代原来的没有签名的证书的密码

   FileOutputStream out2 = new FileOutputStream(name);
   ks.store(out2,storepass);//存入原来的库中,第二个参数为该库的访问密码

//////////////////////////////////////////////////////////////////////////   /

//   end 方式二

//////////////////////////////////////////////////////////////////////////   /

  }

}

以上代码生成了一个用CA私钥进行了签名的新的证书,我们只要将CA的证书安装到系统中,以后以CA签名的数字证书都将得到信任.

在实际应用当中,比如我们要使一个applet可以访问文件系统,这样我们只要将JAR文件用我们的证书进行签名如下:

jarsigner -keystore abnerCALib myapplet.jar Mission_Water_Signed

就可以让终端用户选择是否信任我们的程序并进而读取用户系统的文件.

如果用户系统中没有安装JRE,我们可以使用htmlconverter这个工具转换一下,转换成JAVA插件的形式让客户下载,这种方式是IE所支持的,如下:

<!-- ShowFileApplet.html -->

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=GB2312">

<title>HTMLTestPage</title>

</head>

<body>

applet将会显示,如果你的浏览器支持Java<br>

<OBJECT

classid = "clsid:CAFEEFAC-0014-0001-0001-ABCDEFFEDCBA"

codebase = "http://java.sun.com/products/plugin/autodl/jinstall-1_4_1_01-windows-i586.cab#Version=1,4,1,1"

WIDTH = "400" HEIGHT = "300" NAME = "TestApplet" ALIGN = "middle" VSPACE = "0" HSPACE = "0" >

<PARAM NAME = CODE VALUE = "com.applet.ShowFileApplet.class" >

<PARAM NAME = ARCHIVE VALUE = "./applet/myapplet.jar" >

<PARAM NAME = NAME VALUE = "TestApplet" >

<PARAM NAME = "type" VALUE = "application/x-java-applet;jpi-version=1.4.1_01">

<PARAM NAME = "scriptable" VALUE = "false">

<COMMENT>

<EMBED

type = "application/x-java-applet;jpi-version=1.4.1_01"

CODE = "com.applet.ShowFileApplet.class"

ARCHIVE = "./applet/myapplet.jar"

NAME = "TestApplet"

WIDTH = "400"

HEIGHT = "300"

ALIGN = "middle"

VSPACE = "0"

HSPACE = "0"

scriptable = false

pluginspage = "http://java.sun.com/products/plugin/index.html#download">

<NOEMBED>

</NOEMBED>

</EMBED>

</COMMENT>

</OBJECT>

</body>

</html>

原创粉丝点击