Java生成p12证书

本文介绍了如何在Java中使用BouncyCastle库生成RSA密钥对,并利用这些密钥生成自签名的X.509证书,包括证书的签发过程和存储格式。
摘要由CSDN通过智能技术生成

本文章使用的环境

jdk1.8,spring-boot2.6.13

一、pom依赖

        <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 com.lift.bright.pkcs;

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 bao
 * @date 2024/3/20 16:10
 */
public class Pkcs {
    private static KeyPair getKey() throws NoSuchAlgorithmException {
        // 密钥对 生成器,RSA算法 生成的  提供者是 BouncyCastle
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA",  new BouncyCastleProvider());
        generator.initialize(1024);  // 密钥长度 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");
            SecureRandom secureRandom = new SecureRandom();
            jBuilder.setSecureRandom(secureRandom);
            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;
    }

    public class Extension {
        private String oid;
        private boolean critical;
        private byte[] value;

        public String getOid() {
            return oid;
        }
        public byte[] getValue() {
            return value;
        }
        public boolean isCritical() {
            return critical;
        }
    }

    public static void main(String[] args) throws Exception{
        // CN: 名字与姓氏    OU : 组织单位名称
        // O :组织名称  L : 城市或区域名称  E : 电子邮件
        // ST: 州或省份名称  C: 单位的两字母国家代码
        String issuerStr = "CN=ibright.com,OU=ibright.com,O=ibright.com,C=CN,E=bnmjstu@ibright.com,L=BeiJin,ST=BeiJin";
        String subjectStr = "CN=ibright.com,OU=ibright.com,O=ibright.com,C=CN,E=bnmjstu@ibright.com,L=BeiJin,ST=BeiJin";
        String certificateCRL  = "https://www.ibright.com/";

        //创建证书
        Map<String, byte[]> result = createCert("ibright2014", issuerStr, subjectStr, certificateCRL);

        //获取资源文件路径
        String resourcePath = "./src/main/resources/";

        FileOutputStream outPutStream = new FileOutputStream(resourcePath + "./ibright.p12"); // ca.jks
        outPutStream.write(result.get("keyStoreData"));
        outPutStream.close();

        FileOutputStream fos = new FileOutputStream(new File(resourcePath + "./ibright.cer"));
        fos.write(result.get("certificateData"));
        fos.flush();
        fos.close();
    }
}

三、生成结果

四、完整项目地址

bnmjstu / gen-pkcs · GitCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值