signcert.java~28~
来自「java的打字程序」· JAVA~28~ 代码 · 共 375 行
JAVA~28~
375 行
package chapter11;
import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.math.*;
import sun.security.x509.*;
import javax.swing.*;
import java.awt.FlowLayout;
import com.borland.jbcl.layout.XYLayout;
import com.borland.jbcl.layout.*;
/**
* 使用CA的证书信息签发一个证书,这一过程即通过签发者CA的证书信息对被签发者的证书进行签名。
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2004</p>
*
* <p>Company: aaa</p>
*
* @author 陈雄华
* @version 1.0
*/
public class SignCert extends JFrame {
public SignCert() {
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
}
String name ; //存放CA证书和被签证书的证书库的名字
char[] storepass ; //存放CA证书和被签证书的证书库的访问密码
String alias; //CA证书在证书库中的别名,这个CA的证书用来签名其它的证书
char[] cakeypass ; //CA数字证书条目的访问密码
String aliasName; //被签证书在证书库中的alias别名
char[] namePass; //被签证书的条目在证书库的私钥密码
int n ; //被签证书的有效期,以年为单位,以当前时间开始计算
int sn ; //序列号可自己定义,这里定义的意义为2004年6月签发,是本年度CA签发的第多少个以001计算,要求唯一
String afteraliasName; //签名后新产生的被签过名的证书在库中的别名
char[] afterNewPass ; //签名后新产生的被签过名的证书在库的条目的私钥的密码
XYLayout xYLayout1 = new XYLayout();
JLabel jLabel1 = new JLabel();
JTextField nameFld = new JTextField();
JLabel jLabel2 = new JLabel();
JTextField storepassFld = new JTextField();
JLabel jLabel3 = new JLabel();
JTextField aliasFld = new JTextField();
JLabel jLabel4 = new JLabel();
JTextField cakeypassFld = new JTextField();
JLabel jLabel5 = new JLabel();
JTextField aliasNameFld = new JTextField(); JLabel jLabel8 = new JLabel();
JTextField nFld = new JTextField();
JLabel jLabel9 = new JLabel();
JTextField snFld = new JTextField();
JLabel jLabel10 = new JLabel();
JTextField afteraliasNameFld = new JTextField();
JButton jButton1 = new JButton();
JTextField namePassFld = new JTextField();
JLabel jLabel6 = new JLabel();
JLabel jLabel7 = new JLabel();
JTextField afterNewPassFld = new JTextField();
JLabel jLabel11 = new JLabel();
JLabel jLabel12 = new JLabel();
private void fillSetting()
{
name = nameFld.getText();
storepass = storepassFld.getText().toCharArray();
String alias = aliasFld.getText();
cakeypass = cakeypassFld.getText().toCharArray();
aliasName = aliasNameFld.getText();
namePass = namePassFld.getText().toCharArray();
int n = (new Integer(nFld.getText())).intValue();
int sn = (new Integer(snFld.getText())).intValue();
afteraliasName = afteraliasNameFld.getText();
afterNewPass = afterNewPassFld.getText().toCharArray();
}
private void sign() {
boolean isError = false;
try {
//装载证书库
FileInputStream in = new FileInputStream(name);
KeyStore ks = KeyStore.getInstance("JKS"); //JKS为证书库的类型
ks.load(in, storepass);
//从证书库中读出签发者(CA)的证书
java.security.cert.Certificate cl = ks.getCertificate(alias); //读出一个CA证书,这里的l是字母l不是数据字1
PrivateKey privateKey = (PrivateKey) ks.getKey(alias, cakeypass); //根据别名和证书密码读出CA证书的私钥
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 方式二
///////////////////////////////////////////////////////////////////////////
} catch (SignatureException ex) {
isError = true;
ex.printStackTrace();
} catch (NoSuchProviderException ex) {
isError = true;
ex.printStackTrace();
} catch (InvalidKeyException ex) {
isError = true;
ex.printStackTrace();
} catch (UnrecoverableKeyException ex) {
isError = true;
ex.printStackTrace();
} catch (CertificateException ex) {
isError = true;
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
isError = true;
ex.printStackTrace();
} catch (IOException ex) {
isError = true;
ex.printStackTrace();
} catch (KeyStoreException ex) {
isError = true;
ex.printStackTrace();
}
if (isError) {
JOptionPane.showMessageDialog(this, "失败");
} else {
JOptionPane.showMessageDialog(this, "成功");
}
}
private void jbInit() throws Exception {
this.getContentPane().setLayout(xYLayout1); jLabel1.setText("CA证书所在库密码");
nameFld.setText(""); jLabel2.setText("CA证书密码"); jLabel3.setText(
"CA证书别名"); jLabel4.setText("证书库名"); jLabel5.setText("被签证书别名");
jLabel8.setText("有效期(年)"); jLabel9.setText("签发序列号");
xYLayout1.setWidth(400); xYLayout1.setHeight(366); jLabel10.setText(
"证书被签后的别名"); jButton1.setText("签名"); jLabel6.setText("被签证书私钥密码");
jLabel7.setText("被签后证书的私钥密码"); afterNewPassFld.setToolTipText("");
afterNewPassFld.setText(""); jLabel11.setText("int型"); jLabel12.setText(
"int型"); this.
getContentPane().add(jButton1, new XYConstraints(111, 323, 207, -1)); this.
getContentPane().add(jLabel6, new XYConstraints(13, 175, -1, -1)); this.
getContentPane().add(jLabel10, new XYConstraints(14, 204, -1, -1)); this.
getContentPane().add(jLabel1, new XYConstraints(14, 46, -1, -1)); this.
getContentPane().add(jLabel3, new XYConstraints(45, 75, -1, -1)); this.
getContentPane().add(jLabel2, new XYConstraints(44, 109, -1, -1)); this.
getContentPane().add(jLabel4, new XYConstraints(59, 15, -1, -1)); this.
getContentPane().add(jLabel5, new XYConstraints(37, 145, -1, -1)); this.
getContentPane().add(jLabel8, new XYConstraints(54, 259, -1, -1)); this.
getContentPane().add(jLabel9, new XYConstraints(49, 287, -1, -1)); this.
getContentPane().add(jLabel7, new XYConstraints(2, 230, -1, -1)); this.
getContentPane().add(cakeypassFld,
new XYConstraints(118, 107, 210, -1)); this.
getContentPane().add(aliasNameFld,
new XYConstraints(117, 142, 210, -1)); this.
getContentPane().add(nFld,
new XYConstraints(116, 255, 212, -1)); this.
getContentPane().add(snFld,
new XYConstraints(117, 283, 210, -1)); this.
getContentPane().add(nameFld, new XYConstraints(118, 13, 210, -1)); this.
getContentPane().add(storepassFld,
new XYConstraints(117, 44, 210, -1)); this.
getContentPane().add(aliasFld, new XYConstraints(117, 72, 210, -1)); this.
getContentPane().add(afteraliasNameFld,
new XYConstraints(116, 199, 213, -1)); this.
getContentPane().add(afterNewPassFld,
new XYConstraints(116, 225, 212, -1)); this.
getContentPane().add(namePassFld,
new XYConstraints(117, 171, 212, -1)); this.
getContentPane().add(jLabel11, new XYConstraints(330, 257, -1, -1)); this.
getContentPane().add(jLabel12, new XYConstraints(332, 287, -1, -1)); }
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?