欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用JAVA签发数字证书

程序员文章站 2024-01-10 23:49:51
...

前一篇http://zhuyuehua.iteye.com/blog/1101041 说到创建TOMCAT下HTTPS项目,现在接着说,如何签发证书。

打开cmd

1.输入D:

 

2.输入cd keys

 

3.输入命令查看创建的密钥库的证书列表

keytool -list -v -keystore mykey.keystore -storepass 123456

如下图:

 


用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
 4. 之前导出过server.cer文件,把这个文件安装到操作系统,过程默认。

 

5.创建一个密钥对,和之前一样,输入如下命令:

 

--创建密钥对

keytool -genkey -dname "CN=tmp, OU=NC, O=Shanghai University, L=ZB, ST=Shanghai,C=CN" -alias client  -keyalg RSA -keystore myclientkey.store -keypass 654321 -storepass 654321 -validity 1000

 

--导出公钥

keytool -export -trustcacerts -alias client  -file client.cer -keystore  myclientkey.store -storepass 654321

 

双击client.cer可以看到:


用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
 该证书不被系统信任,且颁发者和颁发给都是tmp

 

5.签发证书,这里采用的是JAVA程序来签发。可以用OPENSSL签发或者到正式CA机构签发。

 

由于已经把server.cer安装到客户机电脑上,所以客户机操作系统会信任server.cer中的机构签发的证书。

 

这里就用server.cer中的机构来签发client.cer

 

签发代码:

package com.syspro.test;

import java.io.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import java.math.*;
import sun.security.x509.*;
public class SignCert {
	
	private String mKeystore = "D:/keys/mykey.keystore"; // 密锁库路径
	private char[] mKeystorePass = "123456".toCharArray();// 密锁库密码
	private char[] mSignPrivateKeyPass = "123456".toCharArray();// 取得签发者私锁所需的密码
	private String mSignCertAlias = "keytest";// 签发者别名
	private String mSignedCert = "D:/keys/client.cer"; // 被签证书
	private String mNewCert = "D:/keys/clientSignKey.cer"; // 签发后的新证书全名
	private int mValidityDay = 3000; // 签发后的新证书有效期(天)

	private PrivateKey mSignPrivateKey = null;// 签发者的私锁
	private X509CertInfo mSignCertInfo = null;// 签发证书信息
	private X509CertInfo mSignedCertInfo = null;// 被签证书信息
	   
	 public void  Sign() throws Exception{
			try {
				/**
				 * 证书签名
				 */
				getSignCertInfo(); // 获取签名证书信息
				signCertificate(); // 用签名证书信息签发待签名证书
				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 );
 		// 保存为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;
 	}
 	
 	public static void main(String args[]) throws UnsupportedEncodingException
	{
		SignCert s = new SignCert();
		try {
			s.Sign();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

} 

 打开签名完成后的新证书clientSignKey.cer,如下图:

 


用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
 会看到此时,操作系统会信任该证书,而且颁发者变成了server.cer中的localhost

 

再将签名后的数字证书clientSignKey.cer和CA证书server.cer导入myclientkey.store库中,命令如下:注意先后顺序

先倒入CA证书
keytool -import -alias ca -keystore D:\keys\myclientkey.store  -trustcacerts -file D:\keys\server.cer -storepass 654321

注意-alias 和之前的不一样。

再导入签名后的证书:

keytool -import -alias client -keystore D:\keys\myclientkey.store  -trustcacerts -file D:\keys\

clientSignKey.cer -storepass 654321

 

注意-alias 和之前的一样。

 

操作完后修改tomcat的server.xml文件,如下:

  <Connector protocol="org.apache.coyote.http11.Http11NioProtocol" 
				port="8443"  enableLookups="true" 
				disableUploadTimeout="true" acceptCount="100" 
				maxThreads="200" scheme="https" secure="true" 
				SSLEnabled="true"  sslProtocol="TLS" 
				clientAuth="false"
				keystoreFile="D:\keys\myclientkey.store" 
				keystorePass="654321" />

 然后启动tomcat,就会发现不会再提示了。

 

注:由于myclientkey.store的cn不是localhost,所以之前那样的设置打开网站时还是会提示不信任的证书。解决办法是将

myclientkey.store的cn写成localhost(你需要访问的网站地址),当然之前那个CA的密钥库的CN就不要写成localhost了,

随便写个别的就好。

 

 

注意,这样之后httpclient还是不会信任该证书,可以这样操作:

切换到<java-home>\jar\lib\security\目录下:

keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file

clientSignKey.cer

  • 用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
  • 大小: 54.7 KB
  • 用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
  • 大小: 29.9 KB
  • 用JAVA签发数字证书
            
    
    博客分类: JAVA JavaTomcatSecuritySchemeITeye 
  • 大小: 28.2 KB