java PKCS12 证书生成

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java PKCS12 证书生成相关的知识,希望对你有一定的参考价值。

引入依赖

                    <dependency>
                            <groupId>org.bouncycastle</groupId>
                            <artifactId>bcprov-jdk15on</artifactId>
                            <version>1.49</version>
                    </dependency>
                    <dependency>
                            <groupId>org.bouncycastle</groupId>
                            <artifactId>bcpkix-jdk15on</artifactId>
                            <version>1.49</version>
                    </dependency> 

直接上代码

package test;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 成都一方思致科技有限公司
 *
 * @author 蒋昌宝
 * @version 1.0
 * @date 2019/8/23 9:26
 * @description 证书生成工具类
 * =========================================================================
 * 变更履历:
 * -------------------------------------------------------------------------
 * 变更编号     变更时间    变更人   变更原因    变更内容
 * -------------------------------------------------------------------------
 */

public class GenerateCertificateUtil

private static KeyPair getKey() throws NoSuchAlgorithmException 
    // 密钥对 生成器,RSA算法 生成的  提供者是 BouncyCastle
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA",  new BouncyCastleProvider());
    // 密钥长度 1024
    generator.initialize(1024);
    // 证书中的密钥 公钥和私钥
    KeyPair keyPair = generator.generateKeyPair();
    return keyPair;


/**
 * @param password  密码
 * @param issuerStr 颁发机构信息
 * @param subjectStr 使用者信息
 * @param certificateCRL 颁发地址
 * @return
 */
public static Map<String, byte[]> createCert(String password, String issuerStr, String subjectStr, String certificateCRL) 

    Map<String, byte[]> result = new HashMap<String, byte[]>();
    ByteArrayOutputStream out = null;
    try 
        //  生成JKS证书
        //  KeyStore keyStore = KeyStore.getInstance("JKS");
        //  标志生成PKCS12证书
        KeyStore keyStore = KeyStore.getInstance("PKCS12",  new BouncyCastleProvider());
        keyStore.load(null, null);
        KeyPair keyPair = getKey();
        //  issuer与 subject相同的证书就是CA证书
        Certificate cert = generateCertificateV3(issuerStr, subjectStr,  keyPair, result, certificateCRL, null);
        // cretkey随便写,标识别名
        keyStore.setKeyEntry("cretkey",  keyPair.getPrivate(),  password.toCharArray(),  new Certificate[]  cert );
        out = new ByteArrayOutputStream();
        cert.verify(keyPair.getPublic());
        keyStore.store(out, password.toCharArray());
        byte[] keyStoreData = out.toByteArray();
        result.put("keyStoreData", keyStoreData);
        return result;
     catch (Exception e) 
        e.printStackTrace();
     finally 
        if (out != null) 
            try 
                out.close();
             catch (IOException e) 
            
        
    
    return result;


/**
 * @param issuerStr
 * @param subjectStr
 * @param keyPair
 * @param result
 * @param certificateCRL
 * @param extensions
 * @return
 */
public static Certificate generateCertificateV3(String issuerStr, String subjectStr, KeyPair keyPair, Map<String, byte[]> result,
                                                String certificateCRL, List<Extension> extensions) 

    ByteArrayInputStream bout = null;
    X509Certificate cert = null;
    try 
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        Date notBefore = new Date();
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(notBefore);
        // 日期加1年
        rightNow.add(Calendar.YEAR, 1);
        Date notAfter = rightNow.getTime();
        // 证书序列号
        BigInteger serial = BigInteger.probablePrime(256, new Random());
        X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
                new X500Name(issuerStr), serial, notBefore, notAfter,new X500Name(subjectStr), publicKey);
        JcaContentSignerBuilder jBuilder = new JcaContentSignerBuilder( "SHA1withRSA");
        Secur删除eRandom secur删除eRandom = new Secur删除eRandom();
        jBuilder.setSecur删除eRandom(secur删除eRandom);
        ContentSigner singer = jBuilder.setProvider(  new BouncyCastleProvider()).build(privateKey);
        // 分发点
        ASN1ObjectIdentifier cRLDistributionPoints = new ASN1ObjectIdentifier( "2.5.29.31");
        GeneralName generalName = new GeneralName( GeneralName.uniformResourceIdentifier, certificateCRL);
        GeneralNames seneralNames = new GeneralNames(generalName);
        DistributionPointName distributionPoint = new DistributionPointName( seneralNames);
        DistributionPoint[] points = new DistributionPoint[1];
        points[0] = new DistributionPoint(distributionPoint, null, null);
        CRLDistPoint cRLDistPoint = new CRLDistPoint(points);
        builder.addExtension(cRLDistributionPoints, true, cRLDistPoint);
        // 用途
        ASN1ObjectIdentifier keyUsage = new ASN1ObjectIdentifier( "2.5.29.15");
        // | KeyUsage.nonRepudiation | KeyUsage.keyCertSign
        builder.addExtension(keyUsage, true, new KeyUsage( KeyUsage.digitalSignature | KeyUsage.keyEncipherment));
        // 基本限制 X509Extension.java
        ASN1ObjectIdentifier basicConstraints = new ASN1ObjectIdentifier("2.5.29.19");
        builder.addExtension(basicConstraints, true, new BasicConstraints(true));
        // privKey:使用自己的私钥进行签名,CA证书
        if (extensions != null)
            for (Extension ext : extensions) 
                builder.addExtension(
                        new ASN1ObjectIdentifier(ext.getOid()),
                        ext.isCritical(),
                        ASN1Primitive.fromByteArray(ext.getValue()));
            
        
        X509CertificateHolder holder = builder.build(singer);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        bout = new ByteArrayInputStream(holder.toASN1Structure() .getEncoded());
        cert = (X509Certificate) cf.generateCertificate(bout);
        byte[] certBuf = holder.getEncoded();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        // 证书数据
        result.put("certificateData", certBuf);
        //公钥
        result.put("publicKey", publicKey.getEncoded());
        //私钥
        result.put("privateKey", privateKey.getEncoded());
        //证书有效开始时间
        result.put("notBefore", format.format(notBefore).getBytes("utf-8"));
        //证书有效结束时间
        result.put("notAfter", format.format(notAfter).getBytes("utf-8"));
     catch (Exception e) 
        e.printStackTrace();
     finally 
        if (bout != null) 
            try 
                bout.close();
             catch (IOException e) 
            
        
    
    return cert;


class Extension 

    private String oid;
    private boolean critical;
    private byte[] value;

    public String getOid() 
        return oid;
    

    public void setOid(String oid) 
        this.oid = oid;
    

    public boolean isCritical() 
        return critical;
    

    public void setCritical(boolean critical) 
        this.critical = critical;
    

    public byte[] getValue() 
        return value;
    

    public void setValue(byte[] value) 
        this.value = value;
    

/**

  • 测试证书生成
  • @throws Exception
    */
    public static void main(String[] args) throws Exception
    // CN: 名字与姓氏 OU : 组织单位名称
    // O :组织名称 L : 城市或区域名称 E : 电子邮件
    // ST: 州或省份名称 C: 单位的两字母国-家代码
    String issuerStr = "CN=jcb凭证,OU=研发部,O=jcb有限公司,C=CN,E=jcb@sina.com,L=北京,ST=北京";
    String subjectStr = "CN=jcb有限公司,OU=用户,O=test,C=CN,E=jcb@sina.com,L=北京,ST=北京";
    String certificateCRL = "https://jcb.cn";
    Map<String, byte[]> result = GenerateCertificateUtil.createCert("123456", issuerStr, subjectStr, certificateCRL);
    // 生成.p12
    FileOutputStream outPutStream = new FileOutputStream("d:/keystore_jcb.p12");
    outPutStream.write(result.get("keyStoreData"));
    outPutStream.flush();
    outPutStream.close();
    //生成.cer颁发给用户的证书
    // FileOutputStream fos = new FileOutputStream(new File("d:/zheng.cer"));
    // fos.write(result.get("certificateData"));
    // fos.flush();
    // fos.close();

以上是关于java PKCS12 证书生成的主要内容,如果未能解决你的问题,请参考以下文章

PKCS12 证书的生成及验证

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

使用OpenSSL创建多级CA证书链签发证书并导出为pkcs12/p12/pfx文件

来自 CA 的 PKCS12 Java 密钥库和 Java 中的用户证书

SaltStack-OpenSSL-Pkcs12:如何使用saltStack转换生成的letsencrypt证书