当前位置:   article > 正文

Java 生成X.509 V3证书_java生成数字证书

java生成数字证书

使用Java语言生成X.509 V3证书

1. X.509 V3证书

X.509 是公钥证书的格式标准, 广泛用于 TLS/SSL 安全通信或者其他需要认证的环境中。
X.509 证书可以由 CA(Certificate Authority,数字证书认证机构)颁发,也可以自签名产生。

X.509 证书中主要含有公钥、身份信息、签名信息和有效性信息等信息。
这些信息用于构建一个验证公钥的体系,用来保证客户端得到的公钥正是它期望的公钥。

  • 公钥 : 非对称密码中的公钥。公钥证书的目的就是为了在互联网上分发公钥。
  • 身份信息 : 公钥对应的私钥持有者的信息,域名以及用途等。
  • 签名信息 : 对公钥进行签名的信息,提供公钥的验证链。可以是 CA
    的签名或者是自签名,不同之处在于CA证书的根证书大都内置于操作系统或者浏览器中,而自签名证书的公钥验证链则需要自己维护(手动导入到操作系统中或者再验证流程中单独提供自签名的根证书)。
  • 有效性信息:证书的有效时间区间,以及 CRL(证书吊销列表)等相关信息。
    X.509 证书的标准规范RFC5280中详细描述了证书的 Encoding Format(编码格式)和
    Structure(证书结构)。

1.1 编码格式

  • DER格式 : 二进制格式。
  • PEM格式 : ASCII 文本格式。在 DER 格式或者其他二进制数据的基础上,使用 base64 编码为 ASCII 文本,以便于在仅支持 ASCII
    的环境中使用二进制的 DER 编码的数据。

1.2 X.509证书结构

Certificate
  Version Number
  Serial Number
  Signature Algorithm ID
  Issuer Name
  Validity period
  Not Before
  Not After
  Subject name
  Subject Public Key Info
  Public Key Algorithm
  Subject Public Key
  Issuer Unique Identifier (optional)
  Subject Unique Identifier (optional)
  Extensions (optional)
...
Certificate Signature Algorithm
Certificate Signature
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

1.3 X.509 证书相关文件常见的扩展名

  • .pem : 隐私增强型电子邮件格式(缩写:PEM)格式,通常是由证书的 DER 二进制 Base64 编码得出。(最常用)。
  • .key : PEM 格式的私钥文件。
  • .pub : PEM 格式的公钥文件。
  • .crt : PEM 格式的公钥证书文件,也可能是 DER。
  • .cer : DER 格式的公钥证书文件,也可能是 PEM。
  • .crs : PEM 格式的 CSR 文件,也可能是 DER。
  • .p12 – PKCS#12 格式,包含证书的同时可能还包含私钥。
  • .pfx – PFX,PKCS#12 之前的格式(通常用PKCS#12格式,比如由互联网信息服务产生的 PFX 文件)。

提示:
目前一般使用pem格式的证书。
大多数系统会根据证书文件中的内容来识别具体的格式,而不依赖于扩展名。

更多信息请参考:维基百科X.509

2. 使用Java生成X.509 V3 证书

2.1 引入依赖

如果使用 Maven 项目,则需要在 pom.xml 中引入下面的依赖:


<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

bouncycastle 是一个 JCE Provider,实现了常用的加密算法,是一个加密算法库,同时提供了 X.509 证书生成的一些帮助类。

2.2 代码实现

下面是一个例子:

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.util.Base64;
import java.util.Date;

public class App {
    /**
     * 生成自签名的PEM格式的证书和私钥文件
     */
    public static void main(String[] args) throws OperatorCreationException, IOException {
        //生成主题信息
        X500Name subject = generateSubject("CN", "Beijing", "Beijing", "", "", "www.test.com");
        //生成RSA密钥对
        KeyPair keyPair = generateRsaKeyPair(2048);
        assert keyPair != null;
        PublicKey aPublic = keyPair.getPublic();
        PrivateKey aPrivate = keyPair.getPrivate();
        //下面是私钥key生成的过程
        byte[] privateKeyEncode = aPrivate.getEncoded();
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKeyEncode);
        String privateKeyFileContent = "" +
                "-----BEGIN RSA PRIVATE KEY-----\n" +
                lf(privateKeyStr, 64) +
                "-----END RSA PRIVATE KEY-----";
        FileUtils.write(new File("C:\\Users\\Administrator\\Desktop\\test1.key"), privateKeyFileContent,
                StandardCharsets.UTF_8);
        //下面是PEM格式的证书生成过程
        long currTimestamp = System.currentTimeMillis();
        X500Name issuer = subject;
        X509v3CertificateBuilder x509v3CertificateBuilder = new JcaX509v3CertificateBuilder(
                issuer, BigInteger.valueOf(System.currentTimeMillis()),
                new Date(currTimestamp), new Date(currTimestamp + (long) 365 * 24 * 60 * 60 * 1000),
                subject, aPublic);
        JcaContentSignerBuilder sha256WITHRSA = new JcaContentSignerBuilder("SHA256WITHRSA");
        ContentSigner contentSigner = sha256WITHRSA.build(aPrivate);
        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("C:\\Users\\Administrator\\Desktop\\test1.pem"), 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 (可以是公司名称),eg: 北京创新乐知网络技术有限公司
     * @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 KeyPair generateRsaKeyPair(int keySize) {
        try {
            KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
            rsa.initialize(keySize);
            return rsa.generateKeyPair();
        } catch (NoSuchAlgorithmException ignore) {
        }
        return null;
    }

    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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114

运行上面的代码,将生成两个文件:test1.pem(证书)和test1.key(私钥)。
如果使用 windows 系统,请更改 test1.pem 后缀为 .crt,然后双击该文件即可打开。

证书详情

可以看到证书中的一些信息。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/781354
推荐阅读
相关标签
  

闽ICP备14008679号