通过Java和ECDSA生成X509版本的证书

发布时间 2023-11-26 17:00:29作者: Nichols1205

1.创新maven项目导入相关依赖

<dependencies>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-ext-jdk15on</artifactId>
            <version>1.70</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
    </dependencies>

2.通过ECDSA生成私钥和公钥信息

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
keyPairGenerator.initialize(ecSpec, new SecureRandom());
KeyPair keypair = keyPairGenerator.generateKeyPair();
PrivateKey priv = keypair.getPrivate();
PublicKey pub = keypair.getPublic();

3.设置证书相关信息

// 用户信息
X500Name subject = generateSubject("CN", "Beijing", "Beijing", "Nichols' company", "Nichols' org", "Nichols/UID=13336");
// 颁发机构信息
X500Name issuer = generateSubject("CN", "Beijing", "Beijing", "org1", "org1.depart1", "ca.org1");
long currentTime = System.currentTimeMillis();
X509v3CertificateBuilder x509v3CertificateBuilder
        = new JcaX509v3CertificateBuilder(issuer, BigInteger.valueOf(System.currentTimeMillis()),
           new Date(currentTime),new Date(currentTime + (long) 365 * 24 * 60 * 60 * 1000),subject,pub);
JcaContentSignerBuilder ecdsa = new JcaContentSignerBuilder("SHA256withECDSA");
ContentSigner contentSigner = ecdsa.build(priv);
X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(contentSigner);
Certificate certificate = x509CertificateHolder.toASN1Structure();

4.存储证书文件

byte[] encoded = certificate.getEncoded();
String certStr = Base64.getEncoder().encodeToString(encoded);
String certFileContent = "" +
          "-----BEGIN CERTIFICATE-----\n" +
          lf(certStr, 64) +
          "-----END CERTIFICATE-----";
// 这里存储为cer文件,也可存为pem文件
FileUtils.write(new File("D:\\testCert.cer"),certFileContent, StandardCharsets.UTF_8);

5.windows/linux查看cer文件

windows

linux

openssl x509 -in 文件名.cer -text -noout

6.完整Java代码

package org.nichols;

import org.apache.commons.io.FileUtils;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder;
import org.bouncycastle.asn1.x500.style.BCStyle;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;

import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
import java.util.Date;

/**
 * @author nichols
 * @date ${DATE} ${TIME}
 */
public class GenerateX509Cert {
    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, OperatorCreationException, IOException {
        X500Name subject = generateSubject("CN", "Beijing", "Beijing", "Nichols' company", "Nichols' org", "Nichols/UID=13336");
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
        ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1");
        keyPairGenerator.initialize(ecSpec, new SecureRandom());
        KeyPair keypair = keyPairGenerator.generateKeyPair();
        PrivateKey priv = keypair.getPrivate();
        PublicKey pub = keypair.getPublic();
        X500Name issuer = generateSubject("CN", "Beijing", "Beijing", "org1", "org1.depart1", "ca.org1");
        long currentTime = System.currentTimeMillis();
        X509v3CertificateBuilder x509v3CertificateBuilder
                = new JcaX509v3CertificateBuilder(issuer, BigInteger.valueOf(System.currentTimeMillis()),
                new Date(currentTime),new Date(currentTime + (long) 365 * 24 * 60 * 60 * 1000),subject,pub);
        JcaContentSignerBuilder ecdsa = new JcaContentSignerBuilder("SHA256withECDSA");
        ContentSigner contentSigner = ecdsa.build(priv);
        X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(contentSigner);
        Certificate certificate = x509CertificateHolder.toASN1Structure();
        byte[] encoded = certificate.getEncoded();
        String certStr = Base64.getEncoder().encodeToString(encoded);
        String certFileContent = "" +
                "-----BEGIN CERTIFICATE-----\n" +
                lf(certStr, 64) +
                "-----END CERTIFICATE-----";
        FileUtils.write(new File("D:\\testCert.cer"),certFileContent, StandardCharsets.UTF_8);
    }

    /**
     * 生成Subject信息
     *
     * @param C  Country Name (国家代号),eg: CN
     * @param ST State or Province Name (洲或者省份),eg: Beijing
     * @param L  Locality Name (城市名),eg: Beijing
     * @param O  Organization Name (可以是公司名称),
     * @param OU Organizational Unit Name (可以是单位部门名称)
     * @param CN Common Name (服务器ip或者域名),eg: 192.168.30.71 or www.baidu.com
     * @return X500Name Subject
     */
    public static X500Name generateSubject(String C, String ST, String L,
                                           String O, String OU, String CN) {
        X500NameBuilder x500NameBuilder = new X500NameBuilder();
        x500NameBuilder.addRDN(BCStyle.C, C);
        x500NameBuilder.addRDN(BCStyle.ST, ST);
        x500NameBuilder.addRDN(BCStyle.L, L);
        x500NameBuilder.addRDN(BCStyle.O, O);
        x500NameBuilder.addRDN(BCStyle.OU, OU);
        x500NameBuilder.addRDN(BCStyle.CN, CN);
        return x500NameBuilder.build();
    }
    public static String lf(String str, int lineLength) {
        assert str != null;
        assert lineLength > 0;
        StringBuilder sb = new StringBuilder();
        char[] chars = str.toCharArray();
        int n = 0;
        for (char aChar : chars) {
            sb.append(aChar);
            n++;
            if (n == lineLength) {
                n = 0;
                sb.append("\n");
            }
        }
        if (n != 0)
            sb.append("\n");
        return sb.toString();
    }
}

ok,本文到此结束。关注“李让行人软件开发分享”微信公众号,带你了解更有趣的知识!