用java实现签发数字证书

from  http://renhl169.blog.163.com/blog/static/20365322201023194724282/

最近研究了一下数字签名和关于证书相关。

证书必须通过CA权威机构签发,但在开发期间有多种途径实现签发证书用于测试:

1)去相关ca获取测试证书,一般有效期在15-30天

2)用keytool工具可以生成证书,但不能实现签发.

3)用openssl实现,不过对c或c++不熟悉的用起来比较麻烦

4)利用weblogic提供的CertGen实现签发。

综合上述几种途径(这几中方法多少都要配合keytool实现),第一种是最简单的,

但为了深入了解证书签发过程,我自己写了个工具实现了证书签发。

下面是工具的代码,编译后直接运行,供大家学习参考:

package com.app;

import java.io.*;

import java.security.*;

import java.security.cert.*;

import sun.security.x509.*;

import java.util.*;

/**

* Title:签发证书

* Description: 用于根证书签发

* Copyright: Copyright (c) 2004.8.12

* Company: smartcomm

* @author 大脸猫(billdengyj)

* @version 1.0

*/

public class SignCertificate

{

private String mKeystore=""; //密锁库路径

private char[] mKeystorePass=null;//密锁库密码

private char[] mSignPrivateKeyPass=null;//取得签发者私锁所需的密码

private String mSignCertAlias="";//签发者别名

private String mSignedCert=""; //被签证书

private String mNewCert=""; //签发后的新证书全名

private int mValidityDay=3; //签发后的新证书有效期(天)

private PrivateKey mSignPrivateKey=null;//签发者的私锁

private X509CertInfo mSignCertInfo=null;//签发证书信息

private X509CertInfo mSignedCertInfo=null;//被签证书信息

public static void main(String args[])

{

/**

* 参数检查

*/

String vArgs0=null;

if(args.length==0 || (args.length!=7 && !args[0].equals("/")))

{

System.out.println("参数错误,可以加参数'/'查询用法");

System.exit(1);

}

vArgs0=args[0];

if(vArgs0.equals("/"))

{

System.out.println(

"语法:********************************************************************");

System.out.println("java com.app.SignCertificate keystore keystorepass " +

"signCertAlias signPrivateKeyPass signedCert newCert validity");

System.out.println(

"说明:********************************************************************");

System.out.println("keystore:密锁库完整地址");

System.out.println("keystorepass:打开密锁库的密码");

System.out.println("signCertAlias:用于签名的证书别名");

System.out.println("signPrivateKeyPass:用取得签名待签证书的私锁密码");

System.out.println("signedCert:待签名证书完整路径");

System.out.println("newCert:被签名后的新证书保存路径全名");

System.out.println("validity:被签名后的新证书有效期(天)");

System.out.println(

"=======================================================================");

System.out.println("必须提供签名证书保存的密锁库、待签名证书等信息,最后被签名的证书(.cer)被保存到新文件中");

System.exit(1);

}

SignCertificate vSignCert=new SignCertificate();

vSignCert.mKeystore=vArgs0;

vSignCert.mKeystorePass=args[1].toCharArray();

vSignCert.mSignCertAlias=args[2];

vSignCert.mSignPrivateKeyPass=args[3].toCharArray();

vSignCert.mSignedCert=args[4];

vSignCert.mNewCert=args[5];

vSignCert.mValidityDay=Integer.parseInt(args[6]);

try

{

/**

* 证书签名

*/

vSignCert.getSignCertInfo(); //获取签名证书信息

vSignCert.signCertificate(); //用签名证书信息签发待签名证书

vSignCert.createNewCertificate(); //创建并保存签名后的新证书

}catch(Exception e)

{

System.out.println("Error:"+e.getMessage());

}

}

/**

* 取得签名证书信息

* @throws Exception

*/

private void getSignCertInfo() throws Exception

{

FileInputStream vFin=null;

KeyStore vKeyStore=null;

java.security.cert.Certificate vCert=null;

X509CertImpl vCertImpl=null;

byte[] vCertData=null;

//获取签名证书密锁库

vFin=new FileInputStream(mKeystore);

vKeyStore=KeyStore.getInstance("JKS");

vKeyStore.load(vFin,mKeystorePass);

//获取签名证书

vCert= vKeyStore.getCertificate(mSignCertAlias);

vCertData=vCert.getEncoded();

vCertImpl=new X509CertImpl(vCertData);

//获取签名证书信息

mSignCertInfo=(X509CertInfo)vCertImpl.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);

mSignPrivateKey=(PrivateKey)vKeyStore.getKey(mSignCertAlias,mSignPrivateKeyPass);

vFin.close();

}

/**

* 取得待签证书信息,并签名待签证书

* @throws Exception

*/

private void signCertificate() throws Exception

{

FileInputStream vFin=null;

java.security.cert.Certificate vCert=null;

CertificateFactory vCertFactory=null;

byte[] vCertData=null;

X509CertImpl vCertImpl=null;

//获取待签名证书

vFin=new FileInputStream(mSignedCert);

vCertFactory=CertificateFactory.getInstance("X.509");

vCert=vCertFactory.generateCertificate(vFin);

vFin.close();

vCertData=vCert.getEncoded();

//设置签名证书信息:有效日期、序列号、签名者、数字签名算发

vCertImpl=new X509CertImpl(vCertData);

mSignedCertInfo=(X509CertInfo)vCertImpl.get(X509CertImpl.NAME+"."+X509CertImpl.INFO);

mSignedCertInfo.set(X509CertInfo.VALIDITY,getCertValidity());

mSignedCertInfo.set(X509CertInfo.SERIAL_NUMBER,getCertSerualNumber());

mSignedCertInfo.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,

mSignCertInfo.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME));

mSignedCertInfo.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,getAlgorithm());

}

/**

* 待签签证书被签名后,保存新证书

* @throws Exception

*/

private void createNewCertificate() throws Exception

{

FileOutputStream vOut=null;

X509CertImpl vCertImpl=null;

//用新证书信息封成为新X.509证书

vCertImpl=new X509CertImpl(mSignedCertInfo);

//生成新正书验证码

vCertImpl.sign(mSignPrivateKey,"MD5WithRSA");

vOut=new FileOutputStream(mNewCert+".cer");

//保存为der编码二进制X.509格式证书

vCertImpl.derEncode(vOut);

vOut.close();

}

//辅助方法===========================================================================

/**

* 得到新证书有效日期

* @throws Exception

* @return CertificateValidity

*/

private CertificateValidity getCertValidity() throws Exception

{

long vValidity=(60*60*24*1000L)*mValidityDay;

Calendar vCal=null;

Date vBeginDate=null,vEndDate=null;

vCal=Calendar.getInstance();

vBeginDate=vCal.getTime();

vEndDate=vCal.getTime();

vEndDate.setTime(vBeginDate.getTime()+vValidity);

return new CertificateValidity(vBeginDate,vEndDate);

}

/**

* 得到新证书的序列号

* @return CertificateSerialNumber

*/

private CertificateSerialNumber getCertSerualNumber()

{

Calendar vCal=null;

vCal=Calendar.getInstance();

int vSerialNum=0;

vSerialNum=(int)(vCal.getTimeInMillis()/1000);

return new CertificateSerialNumber(vSerialNum);

}

/**

* 得到新证书的签名算法

* @return AlgorithmId

*/

private AlgorithmId getAlgorithm()

{

AlgorithmId vAlgorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);

return vAlgorithm;

}

}

**************************************************************************************************

使用方法:

这个工具是用来做签名的,所以在使用前必须有几个准备工作:

1)用keytool工具生成用于签名的根证书,密锁库为serverstore:

c:\keytool -genkey -keystore .\serverstore -alias root -keyalg RSA -keysize 1024

---期间会有相关提问。特别注意分清keystore密码和privateKey密码!!!!!!

2)用keytool工具生成待签名的证书,密锁库为serverstore:

c:\keytool -genkey -keystore .\serverstore -alias daniel -keyalg RSA -keysize 1024

---期间会有相关提问。特别注意分清keystore密码和privateKey密码!!!!!!

3)导出待签名证书:

c:\keytool -import -keystore .\serverstore -alias daniel -files .\daniel.cer

4)使用编译后的工具,用root签名daniel证书(见(2)(3))

java com.app.SignCertificate keystore keystorepass signCertAlias signPrivateKeyPass signedCert newCert validity

--使用语法可以用 ”java com.app.SignCertificate /?“ 查询。

keystore:密锁库完整地址

keystorepass:打开密锁库的密码

signCertAlias:用于签名的证书别名

signPrivateKeyPass:提取签名证书私锁的密码

signedCert:待签名证书完整路径

newCert:被签名后的新证书保存路径全名

validity:被签名后的新证书有效期(天)

5)第4步完成后,会生成你指定的newCert证书,这个证书是被root签名过的。

6)验证证书是否有效:

在windows下你可以先导出root证书:c:\keytool -import -keystore .\serverstore -alias root -files .\root.cer

双击root.cer安装,在安装daniel.cer,你会发现daniel.cer是有效的。

具体签名后的证书用途可以参考相关资料,这里就不多说了。以上代码在jdk1.4.2.05下通过。

***********************************************************************************

程序的关键是使用了sun.security.x509.X509CertImpl和sun.security.x509.X509CertInfo类

X509CertImpl继承了java.security.cert.Certificate,主要实现了x509证书信息的设置、而

标准的java.security.cert.X509Certificate 有实现;X509CertInfo实现了x509证书信息封装,

在标准的java安全库里是没有的。


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用Java的KeyStore类来生成和管理证书。以下是一个简单的示例代码: ``` import java.io.FileOutputStream; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.cert.X509Certificate; import java.util.Date; import javax.security.auth.x500.X500Principal; import sun.security.x509.*; public class CertificateGenerator { public static void main(String[] args) throws Exception { // Generate a key pair KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); // Generate a self-signed X.509 certificate X500Name issuer = new X500Name("CN=My Company, O=My Organization, L=My City, ST=My State, C=My Country"); X500Name subject = issuer; Date startDate = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000); // Yesterday Date endDate = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000); // One year from now BigInteger serialNumber = new BigInteger(64, new SecureRandom()); X509CertInfo certInfo = new X509CertInfo(); certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber)); certInfo.set(X509CertInfo.SUBJECT, new CertificateSubjectName(subject)); certInfo.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuer)); certInfo.set(X509CertInfo.VALIDITY, new CertificateValidity(startDate, endDate)); certInfo.set(X509CertInfo.KEY, new CertificateX509Key(keyPair.getPublic())); certInfo.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(new AlgorithmId(AlgorithmId.sha256WithRSAEncryption_oid))); X509CertImpl cert = new X509CertImpl(certInfo); cert.sign(keyPair.getPrivate(), "SHA256withRSA"); // Save the certificate to a file FileOutputStream fos = new FileOutputStream("server.crt"); fos.write(cert.getEncoded()); fos.close(); // Save the private key to a file fos = new FileOutputStream("server.key"); fos.write(keyPair.getPrivate().getEncoded()); fos.close(); } } ``` 这个示例代码生成一个2048位的RSA密钥对,并使用SHA256withRSA签名算法生成一个自签名的X.509证书。证书的有效期为一年,保存在server.crt文件中,私钥保存在server.key文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值