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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用 Java 中的 Bouncy Castle 库来生成证书和签名值,然后使用 gmssl 进行验证。下面是一个简单的示例: ```java import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Security; import java.security.Signature; import java.security.cert.Certificate; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; public class GmsslExample { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); // 加载证书和私钥 KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(new FileInputStream("path/to/certificate.p12"), "password".toCharArray()); String alias = keyStore.aliases().nextElement(); PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, "password".toCharArray()); Certificate cert = keyStore.getCertificate(alias); // 创建签名实例 Signature signature = Signature.getInstance("SM3withSM2", "BC"); signature.initSign(privateKey); // 添加待签名数据 byte[] data = "hello world".getBytes("UTF-8"); signature.update(data); // 生成签名值 byte[] signatureValue = signature.sign(); // 打印签名值 System.out.println("Signature Value: " + Hex.toHexString(signatureValue)); } } ``` 在这个例子中,我们使用了 Bouncy Castle 提供的 SM2 签名算法和 SM3 摘要算法来生成签名值,然后把签名值用十六进制的方式打印出来。 接下来,您可以使用 `openssl` 命令来验证签名值: ``` $ openssl sm2verify -cert path/to/certificate.crt -signature signature.hex -in data.txt ``` 其中,`path/to/certificate.crt` 是证书路径,`signature.hex` 是签名值的十六进制字符串,`data.txt` 是待签名数据的文件路径。如果签名值有效,`openssl` 命令会输出 `Verified OK`。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值