package org.liuy.bouncycastle;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Vector;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.DERBMPString;
import org.bouncycastle.asn1.DERIA5String;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.DistributionPoint;
import org.bouncycastle.asn1.x509.DistributionPointName;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.PrincipalUtil;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.jce.interfaces.PKCS12BagAttributeCarrier;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import org.liuy.certdn.form.KeyUseForm;
import org.liuy.conf.IConf;
import org.liuy.security.cert.KeyStoreSeal;
/**
*
* 创建p12证书文件。默认密码:123456
* @author Liuy
* @version 2010-07-19
*
*/
public class CretPKCS12 {
private static char[] passwd = "123456".toCharArray();
private static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
private final static Logger logger = Logger.getLogger(CretPKCS12.class.getName ());
/**
* 创建根证书
*/
private static Certificate createMasterCert(
PublicKey pubKey,
PrivateKey privKey)
throws Exception {
String subjectDN = "CN=FT_ROOT,O=ROOT,C=CN";
v3CertGen.reset();
v3CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
v3CertGen.setIssuerDN(new X509Principal(subjectDN));
v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + 1000L*60*60*24*30*12*10));
v3CertGen.setSubjectDN(new X509Principal(subjectDN));
v3CertGen.setPublicKey(pubKey);
v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
//使用者密钥标示符号
v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,false,
new SubjectKeyIdentifierStructure(pubKey));
//颁发机构密钥标示符
v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,false,
new AuthorityKeyIdentifierStructure(pubKey));
//基本路径限制
v3CertGen.addExtension(X509Extensions.BasicConstraints,true,
new BasicConstraints(true));
//密钥用法
v3CertGen.addExtension(X509Extensions.KeyUsage,true, new KeyUsage(
KeyUsage.keyCertSign | KeyUsage.cRLSign));
X509Certificate cert = v3CertGen.generate(privKey);
cert.checkValidity(new Date());
cert.verify(pubKey);
PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
//证书链名称
bagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,new DERBMPString("FT_ROOT"));
return cert;
}
/**
*
* 创建二级证书
* @param pubKey 二级证书公钥
* @param caPrivKey 根证书私钥
* @param caCert 根证书
*/
private static Certificate createIntermediateCert(
PublicKey pubKey,
PrivateKey caPrivKey,
X509Certificate caCert)
throws Exception {
String subjectDN = "CN=FT_CA,O=CA,C=CN";
v3CertGen.reset();
v3CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
v3CertGen.setIssuerDN(new X509Principal(PrincipalUtil.getSubjectX509Principal(caCert)));
v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
v3CertGen.setNotAfter(new Date(System.currentTimeMillis() + 1000L*60*60*24*30*12*5));
v3CertGen.setSubjectDN(new X509Principal(subjectDN));
v3CertGen.setPublicKey(pubKey);
v3CertGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
//使用者密钥标示符号
v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,false,
new SubjectKeyIdentifierStructure(pubKey));
//颁发机构密钥标示符
v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,false,
new AuthorityKeyIdentifierStructure(caCert));
//基本路径限制
v3CertGen.addExtension(X509Extensions.BasicConstraints,true,
new BasicConstraints(true));
//密钥用法
v3CertGen.addExtension(X509Extensions.KeyUsage,true, new KeyUsage(
KeyUsage.keyCertSign | KeyUsage.cRLSign));
X509Certificate cert = v3CertGen.generate(caPrivKey);
cert.checkValidity(new Date());
cert.verify(caCert.getPublicKey());
PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
//证书链名称
bagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,new DERBMPString("CFCA FEITIAN TEST"));
return cert;
}
/**
* 创建证书
* @param pubKey 证书公钥
* @param IntermePrivKey 二级证书私钥
* @param IntermeCert 二级证书对象
* @param subjectDN 证书DN项
* @param keyUseForm 证书的附属信息
*/
public static Certificate createCert(
PublicKey pubKey,
PrivateKey IntermePrivKey,
X509Certificate IntermeCert,
String subjectDN,KeyUseForm keyUseForm)
throws Exception {
//创建V3证书
v3CertGen.reset();
v3CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
v3CertGen.setIssuerDN(new X509Principal(PrincipalUtil.getSubjectX509Principal(IntermeCert)));
v3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
v3CertGen.setNotAfter(new Date(System.currentTimeMillis()+1000L*60*60*24*30*12));
// v3CertGen.setNotBefore(ProAssistant.getNormatTiem("2010-08-10 10:00:00"));
// v3CertGen.setNotAfter(ProAssistant.getNormatTiem("2010-09-10 10:00:00"));
v3CertGen.setSubjectDN(new X509Principal(subjectDN));
v3CertGen.setPublicKey(pubKey);
v3CertGen.setSignatureAlgorithm(keyUseForm.getCertSignAlgo());
//创建扩展项
/*
*SubjectKeyIdentifier:主体密钥标识符:
* 本项提供一种识别包含有一个特定公钥的证书的方法。
* 此扩展标识了被认证的公开密钥,它能够区分同一主体使用的不同密钥。
* 对于使用密钥标识符的主体的各个密钥标识符而言,每一个密钥标识符均应是唯一的。
* CA签发证书时必须把CA证书中本扩展的值赋给终端实体证书AuthorityKeyIdentifier扩展中的KeyIdentifier项。
* CA证书的主体密钥标识符应从公钥中或者生成唯一值的方法中导出。终端实体证书的主体密钥标识符应从公钥中导出。
* 所有的CA证书必须包括本扩展,此扩展项为非关键项。
*
*/
v3CertGen.addExtension(X509Extensions.SubjectKeyIdentifier,false,
new SubjectKeyIdentifierStructure(pubKey));
/*
*AuthorityKeyIdentifier:密钥扩展项
*
* 有多张根证书时区分签发证书
*
*/
v3CertGen.addExtension(X509Extensions.AuthorityKeyIdentifier,false,
new AuthorityKeyIdentifierStructure(IntermeCert));
/*
* 证书支持多域名
*
ASN1EncodableVector sanVector = new ASN1EncodableVector();
sanVector.add(new GeneralName(GeneralName.dNSName,"localhost"));
sanVector.add(new GeneralName(GeneralName.dNSName,"192.168.35.13"));
sanVector.add(new GeneralName(GeneralName.dNSName,"127.0.0.1"));
sanVector.add(new GeneralName(GeneralName.rfc822Name,"liuy@test.test"));
DERSequence san = new DERSequence(sanVector);
GeneralNames subjectAltName = new GeneralNames(san);
v3CertGen.addExtension(X509Extensions.SubjectAlternativeName,false,
subjectAltName);
*/
int keyUse=0;
if(keyUseForm.isSignUse())
{
//签名用法
keyUse=KeyUsage.digitalSignature | KeyUsage.nonRepudiation;
}
if(keyUseForm.isEncUse())
{
//加密用法
keyUse+=KeyUsage.keyEncipherment | KeyUsage.keyAgreement;
}
if(keyUse!=0)
{
v3CertGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage( keyUse ));
}
boolean flag=false;
/*
* 扩展密钥标识符
*
*/
Vector<DERObjectIdentifier> extendedKeyUsageV = new Vector<DERObjectIdentifier>();
// extendedKeyUsageV.add(KeyPurposeId.id_kp_serverAuth);
// extendedKeyUsageV.add(KeyPurposeId.id_kp_clientAuth);
//时间戳增强密钥用法
if(keyUseForm.isTsaUse())
{
extendedKeyUsageV.add(KeyPurposeId.id_kp_timeStamping);
flag=true;
}
//邮件证书
if(keyUseForm.isEMailUse())
{
extendedKeyUsageV.add(KeyPurposeId.id_kp_emailProtection);
flag=true;
}
// extendedKeyUsageV.add(new KeyPurposeId("1.2.840.113583.1.1.5"));
//代码签名证书
if(keyUseForm.isCodeSign())
{
extendedKeyUsageV.add(new KeyPurposeId("1.3.6.1.5.5.7.3.3"));
flag=true;
}
//加入扩展秘钥
if(flag)
{
v3CertGen.addExtension(X509Extensions.ExtendedKeyUsage, true,
new ExtendedKeyUsage(extendedKeyUsageV));
}
/*
* 证书基本限制
* 证书路径:
* new BasicConstraints(true, 0));
* 1 true代表该证书后 最多的证书链
* 2 false 公钥不能验证其他证书
*/
v3CertGen.addExtension(X509Extensions.BasicConstraints,true,
new BasicConstraints(false));
/*
* CRL发布点
*
*/
if(keyUseForm.getCrlDL()!=null)
{
GeneralName gn = new GeneralName(GeneralName.uniformResourceIdentifier, new DERIA5String(keyUseForm.getCrlDL()));
GeneralNames gns = new GeneralNames(new DERSequence(gn));
DistributionPointName dpn = new DistributionPointName(0, gns);
DistributionPoint distp = new DistributionPoint(dpn, null, null);
v3CertGen.addExtension(
X509Extensions.CRLDistributionPoints, false,
new DERSequence(distp));
}
// v3CertGen.addExtension(MiscObjectIdentifiers.netscapeCertType,false,
// new NetscapeCertType(NetscapeCertType.objectSigning | NetscapeCertType.smime));
//创建并验证信息
X509Certificate cert = v3CertGen.generate(IntermePrivKey,"BC");
cert.checkValidity(new Date());
cert.verify(IntermeCert.getPublicKey());
PKCS12BagAttributeCarrier bagAttr = (PKCS12BagAttributeCarrier) cert;
//创建证书链名称
bagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("User"));
// bagAttr.setBagAttribute(PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
// new SubjectKeyIdentifierStructure(pubKey));
return cert;
}
/**
* 创建root证书KeyStore
* @param outPath KeyStore输出路径
* @throws Exception
*/
private static void createRootKeyStore(String outPath) throws Exception
{
BC.setBC();
//ca keys
KeyPair capair = Utils.generateRSAKeyPair(2048);
//intermediate keys
KeyPair intermediatepair = Utils.generateRSAKeyPair(2048);
//根证书
PrivateKey caPrivKey = capair.getPrivate();
PublicKey caPubKey = capair.getPublic();
//二级证书
PrivateKey intPrivKey = intermediatepair.getPrivate();
PublicKey intPubKey = intermediatepair.getPublic();
//创建证书链
Certificate[] root = new Certificate[1];
Certificate[] Inter = new Certificate[1];
//根证书
root[0] = createMasterCert(caPubKey, caPrivKey);
//二级证书
Inter[0] = createIntermediateCert(intPubKey, caPrivKey, (X509Certificate) root[0]);
//输出根证书与二级证书
KeyStore store = KeyStore.getInstance("JKS");
store.load(null,null);
store.setKeyEntry("root", caPrivKey, passwd, root);
store.setKeyEntry("inter", intPrivKey, passwd, Inter);
FileOutputStream out = new FileOutputStream(outPath);
store.store(out, passwd);
out.close();
}
/**
* 创建 P12证书
* @param subjectDN 证书DN项,形式如:"C=CN,O=Test,OU=Liuy,oid.2.5.4.1=1234"
* @throws Exception
*/
public static byte[] createP12Cert(String subjectDN,KeyUseForm keyUseForm)
{
BC.setBC();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
KeyPair personalpair = Utils.generateRSAKeyPair(keyUseForm.getKeyLen());
//个人
PrivateKey privKey = personalpair.getPrivate();
PublicKey pubKey = personalpair.getPublic();
//通过配置文件找到root文件路径
String rootPath= IConf.getValue("rootPath");
//获取二级证书公钥和私钥
X509Certificate intCert = KeyStoreSeal.getX500Private(rootPath, "123456", "inter").getCertificate();
PrivateKey intPrivKey = KeyStoreSeal.getX500Private(rootPath, "123456", "inter").getPrivateKey();
//制作证书
Certificate user=createCert(pubKey, intPrivKey,intCert, subjectDN,keyUseForm);
Certificate[] chain = new Certificate[1];
chain[0]=user;
KeyStore store = KeyStore.getInstance("PKCS12", "BC");
store.load(null, null);
// String s=StringUtil.getOneKey(subjectDN, "CN");
store.setKeyEntry("", privKey, null, chain);
store.store(baos, passwd);
return baos.toByteArray();
} catch (Exception e) {
logger.error("参数证书错误",e);
}
finally
{
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public static void main(String[] args) throws Exception
{
// createRootKeyStore("d:/root");
String subjectDN="C=CN";
KeyUseForm keyUseForm =new KeyUseForm();
keyUseForm.setKeyLen(1024);
keyUseForm.setCrlDL("http://liuy/crl.crl");
keyUseForm.setSignUse(true);
keyUseForm.setEncUse(true);
keyUseForm.setTsaUse(true);
keyUseForm.setCertSignAlgo("SHA1WithRSAEncryption");
byte[] certBy=createP12Cert(subjectDN,keyUseForm);
File f=new File("d:/2.pfx");
FileUtils.writeByteArrayToFile(f, certBy);
}
}