Bouncy Castle 密钥生成发放证书

每个人都有属于自己的一片森林,迷失的人迷失了,相逢的人会再相逢。

前言 

bouncy castle(轻量级密码术包)是一种用于 Java 平台的开放源码的轻量级密码术包;它支持大量的密码术算法,并提供JCE 1.2.1的实现。

官网地址: https://www.bouncycastle.org/documentation.html

中文文档: https://www.bouncycastle.org/docs/docs1.5to1.8/index.html

相关知识 

一、Java加密算法

Java加密的常用的加密算法类型有三种

1单向加密:也就是不可逆的加密,例如MD5,SHA,HMAC

2对称加密:也就是加密方和解密方利用同一个秘钥对数据进行加密和解密,例如DES,PBE等等

3非对称加密:非对称加密分为公钥和秘钥,二者是非对称的,例如用私钥加密的内容需要使用公钥来解密,使用公钥加密的内容需要用私钥来解密,DSA,RSA...

而keyGenerator,KeyPairGenerator,SecretKeyFactory的三种使用方法刚好和这三种加密算法类型对上

keyGenerator:秘钥生成器,也就是更具算法类型随机生成一个秘钥,例如HMAC,所以这个大部分用在非可逆的算法中

SecretKeyFactory:秘密秘钥工厂,言外之意就是需要根据一个秘密(password)去生成一个秘钥,例如DES,PBE,所以大部分使用在对称加密中

KeyPairGenerator:秘钥对生成器,也就是可以生成一对秘钥,也就是公钥和私钥,所以大部分使用在非对称加密中

二、CSR

CSR是Certificate Signing Request的英文缩写,即证书签名请求文件,是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书。

CSR是以-----BEGIN CERTIFICATE REQUEST-----开头,-----END CERTIFICATE REQUEST-----为结尾的base64格式的编码。将其保存为文本文件,就是所谓的CSR文件。

CSR生成工具非常多,比如openssl工具,keystore explore,XCA等   
在线工具:https://myssl.com/csr_create.html

这里有几个关键的要注意下:

域名必须正确输入(如果是非SSL证书,则输入相应的通用名)。

密钥算法选择RSA的话,密钥长度需要2048bit以上(这个默认是2048,没有特殊情况,不要特殊设置);ECC则是256bit以上。

摘要签名虽说目前可以任意,但建议是sha2-256以上。

CSR生成注意事项

匹配的KEY必须保存

有CSR必定有KEY,是成对的,CSR最终变成为证书,和私钥key配对使用。Key是以-----BEGIN RSA PRIVATE KEY-----开头的,-----END RSA PRIVATE KEY-----结尾的。
Key必须保存好。


CSR生命周期

证书下发后,CSR无需使用,仅提交时候需要。

在线校验csr:https://www.chinassl.net/ssltools/decoder-csr.html

生成csr:https://myssl.com/csr_create.html
一般的数字证书产品的主题通常含有如下字段:
公用名称 (Common Name) 简称:CN 字段,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端证书则为证书申请者的姓名;
单位名称 (Organization Name) :简称:O 字段,对于 SSL 证书,一般为网站域名;而对于代码签名证书则为申请单位名称;而对于客户端单位证书则为证书申请者所在单位名称;
证书申请单位所在地:
所在城市 (Locality) 简称:L 字段
所在省份 (State/Provice) 简称:S 字段
所在国家 (Country) 简称:C 字段,只能是国家字母缩写,如中国:CN
其他一些字段:
电子邮件 (Email) 简称:E 字段
多个姓名字段 简称:G 字段
介绍:Description 字段
电话号码:Phone 字段,格式要求 + 国家区号 城市区号 电话号码,如: +86 732 88888888
地址:STREET  字段
邮政编码:PostalCode 字段
显示其他内容 简称:OU 字段

三、 Bouncy Castle 工具类

1.pom.xml

        <!--bouncycastle Java 生成SSL证书-->
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.66</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.66</version>
        </dependency>

2.Bouncy Castle 生成密钥对、CSR、CERT证书

/**
 * BouncyCastle 工具类
 */
@Slf4j
public class BouncyCastleUtils {
    /**
     * 1.生成密匙对,存储KeyStore
     * 2.生成CSR证书请求文件
     * 3.生成CER证书
     */

    /**
     * 默认生成密钥算法
     */
    private static final String DEFAULT_KEY_ALGORITHM = "RSA";

    /**
     * 签名算法
     */
    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA";

    /**
     * 默认生成密钥长度
     */
    private static final int DEFAULT_KEY_SIZE = 2048;

    /**
     * JAVA KEY STORE JKS
     */
    private static final String KEY_STORE_JKS = "JKS";

    /**
     * JAVA KEY STORE PWD
     */
    private static final String KEY_STORE_PWD = "123456";

    /**
     * JAVA 证书格式
     */
    private static final String CERTFICATE_TYPE = "X.509";

    /**
     * 文件根路径
     */
    private static final String BASE_FILE_PATH = "/YlDream/Idea2022/ideaWorkMe/opFile/";

    /** 设置提供商 */
    static {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    /** =====================生成KeyPair,存储KeyStore================= */

    /**
     * RSA生成密匙对
     *
     * @return
     */
    @SneakyThrows
    public static KeyPair createKeyPair() {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(DEFAULT_KEY_ALGORITHM);
        generator.initialize(DEFAULT_KEY_SIZE, new SecureRandom());
        KeyPair keyPair = generator.generateKeyPair();
        return keyPair;
    }

    /**
     * 随机生成别名
     *
     * @return
     */
    public static String getKeyPairAlias() {
        return "__yl_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + "-" + DateUtil.now();
    }

    /**
     * 随机生成文件名
     *
     * @return
     */
    public static String getTempFileName() {
        return DateUtil.format(new Date(), "yyyyMMddHHmmss") + "-" + DateUtil.current();
    }


    /**
     * 构建X500格式
     *
     * @param country            国别
     * @param stateOrProvince    州或省的名称
     * @param locality           城市或区域
     * @param organization       组织
     * @param organizationalUnit 组织单位名称
     * @param commonName         常用名
     * @param emailAddress       Verisign证书中的电子邮件地址
     * @return
     */
    public static X500Name getX500Name(String country, String stateOrProvince, String locality, String organization,
                                       String organizationalUnit, String commonName, String emailAddress) {
        X500NameBuilder builder = new X500NameBuilder(X500Name.getDefaultStyle());
        builder.addRDN(BCStyle.C, country);
        builder.addRDN(BCStyle.ST, stateOrProvince);
        builder.addRDN(BCStyle.L, locality);
        builder.addRDN(BCStyle.O, organization);
        builder.addRDN(BCStyle.OU, organizationalUnit);
        builder.addRDN(BCStyle.CN, commonName);
        builder.addRDN(BCStyle.E, emailAddress);
        return builder.build();
    }

    /**
     * 获取签名内容?
     *
     * @param privateKey         私钥
     * @param signatureAlgorithm 签名算法
     * @return
     * @throws IOException
     * @throws OperatorCreationException
     */
    private static ContentSigner getContentSigner(PrivateKey privateKey, String signatureAlgorithm) throws IOException, OperatorCreationException {
        AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(signatureAlgorithm);
        AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
        AsymmetricKeyParameter keyParam = PrivateKeyFactory.createKey(privateKey.getEncoded());
        ContentSigner signer = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(keyParam);
        return signer;
    }


    /**
     * 生成签发证书的基础方法
     *
     * @param signatureAlgorithm 签名算法 SHA256WithRSA
     * @param privateKey         签发者私钥
     * @param publicKeyInfo       被签发者公钥信息
     * @param subjectDn           被签发者subject
     * @param issuerDn            签发者subject
     * @param notBefore          开始时间
     * @param notAfter            结束时间
     * @param extensions         扩展信息
     * @return
     * @throws Exception
     */
    public static X509Certificate generateCertifCate(String signatureAlgorithm, PrivateKey privateKey, SubjectPublicKeyInfo publicKeyInfo,
                                                     X500Name subjectDn, X500Name issuerDn, Date notBefore, Date notAfter, List<Extension> extensions) throws Exception {
        BigInteger serial = BigInteger.probablePrime(32, new Random());
        X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issuerDn, serial, notBefore, notAfter, subjectDn, publicKeyInfo);

        if (extensions != null && extensions.size() > 0) {
            for (Extension extension : extensions) {
                if (extension == null) {
                    continue;
                }
                builder.addExtension(extension.getExtnId(), extension.isCritical(), extension.getParsedValue());
            }
        }
        ContentSigner signer = getContentSigner(privateKey, signatureAlgorithm);
        X509CertificateHolder holder = builder.build(signer);
        // BC加密算法
        X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder);
        cert.verify(cert.getPublicKey());
        return cert;
    }

    /**
     * 公钥 - 包含存储在证书中的公钥的对象。
     *
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    public static SubjectPublicKeyInfo convert(PublicKey publicKey) throws Exception {
        // JCE中公钥中的getEncoded()方法生成一个对其中之一进行编码的DER。
        ASN1InputStream asn1InputStream = new ASN1InputStream(publicKey.getEncoded());
        try {
            SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(asn1InputStream.readObject());
            return publicKeyInfo;
        } finally {
            asn1InputStream.close();
        }
    }

    /**
     * 获取存储到磁盘的文件对象
     *
     * @param dbStoreName
     * @return
     */
    public static File getStoreFile(String dbStoreName) {
        File file = new File(BASE_FILE_PATH, dbStoreName);
        if (file.getParentFile().exists() == false) {
            file.getParentFile().mkdirs();
        }
        return file;
    }


    /**
     * 存储keyPair到KeyStore
     *
     * @param keyPair
     */
    @SneakyThrows
    public static Map<String, String> saveKeyStore(KeyPair keyPair) {
        Map<String, String> result = new HashMap<>();
        // 获取KeyStore
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_JKS);
        keyStore.load(null, KEY_STORE_PWD.toCharArray());
        // 密钥对以证书的形式存储
        // 别名
        String alias = getKeyPairAlias();
        // 生成X500Name
        X500Name subjectDn = getX500Name("CN", "Shanghai", "Shanghai", "dream", "dev", "dream-keyPair", "contactus@wdreaam.com");
        // 公钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 私钥
        PublicKey publicKey = keyPair.getPublic();
        // 构建证书
        X509Certificate cert = generateCertifCate(SIGNATURE_ALGORITHM, privateKey, convert(publicKey),
                subjectDn, subjectDn, new Date(), new Date(), null);
        // 设置到KeyEntry
        keyStore.setKeyEntry(alias, keyPair.getPrivate(), KEY_STORE_PWD.toCharArray(), new Certificate[]{cert});
        // keyStore存储文件地址
        String keyStorePath = "/keystore/" + getTempFileName() + ".jks";
        File keyStoreFile = getStoreFile(keyStorePath);
        System.out.println("keyStore存储文件地址===>" + keyStoreFile.getAbsolutePath());
        // 保存
        try (FileOutputStream out = new FileOutputStream(keyStoreFile)) {
            keyStore.store(out, KEY_STORE_PWD.toCharArray());
            try {
                out.close();
            } catch (Exception e) {
            }
        }
        result.put("alias", alias);
        result.put("keyStorePath", keyStorePath);
        System.out.println("存储keyPair到KeyStore Success");
        return result;
    }

    /**
     * 从keyStore获取密匙对
     *
     * @param alias        密钥别名
     * @param keyStoreFile 密钥存储文件File
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair(String alias, File keyStoreFile) throws Exception {
        // 获取KeyStore
        KeyStore keyStore = KeyStore.getInstance(KEY_STORE_JKS);
        keyStore.load(new FileInputStream(keyStoreFile), KEY_STORE_PWD.toCharArray());
        // 获取私钥
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, KEY_STORE_PWD.toCharArray());
        // 获取公钥
        X509Certificate x509Certificate = (X509Certificate) keyStore.getCertificate(alias);
        PublicKey publicKey = x509Certificate.getPublicKey();
        return new KeyPair(publicKey, privateKey);
    }


    /** =====================生成CSR请求文件,存储到本地================= */
    /**
     * 生成csr
     *
     * @param privateKey    私钥
     * @param publicKeyInfo 公钥
     * @param subject        主题
     * @param extensions     公钥信息
     * @return
     * @throws Exception
     */
    public static PKCS10CertificationRequest generateCsr(String signatureAlgorithm, PrivateKey privateKey, SubjectPublicKeyInfo publicKeyInfo,
                                                         X500Name subject, List<Extension> extensions) throws Exception {
        PKCS10CertificationRequestBuilder builder = new PKCS10CertificationRequestBuilder(subject, publicKeyInfo);

        if (extensions != null && extensions.size() > 0) {
            for (Extension extension : extensions) {
                if (extension == null) {
                    continue;
                }
                builder.addAttribute(extension.getExtnId(), extension.getParsedValue());
            }
        }
        ContentSigner signer = getContentSigner(privateKey, signatureAlgorithm);
        PKCS10CertificationRequest csr = builder.build(signer);
        return csr;
    }

    /**
     * 组装DN
     *
     * @param countryName            国家名称 C
     * @param stateOrProvinceName    省市名称 ST
     * @param localityName           城市名称 L
     * @param organizationName       组织名称 O
     * @param organizationalUnitName 组织单元名称 OU
     * @param commonName             常用名称 CN
     * @param emailAddress           邮件地址 emailAddress
     * @return
     */
    public static String generateDN(String countryName, String stateOrProvinceName, String localityName,
                                    String organizationName, String organizationalUnitName, String commonName, String emailAddress) {
        StringBuilder sb = new StringBuilder();
        sb.append("EMAILADDRESS=").append(emailAddress).append(",");
        sb.append("CN=").append(commonName).append(",");
        sb.append("OU=").append(organizationalUnitName).append(",");
        sb.append("O=").append(organizationName).append(",");
        sb.append("L=").append(localityName).append(",");
        sb.append("ST=").append(stateOrProvinceName).append(",");
        sb.append("C=").append(countryName);
        return sb.toString();
    }

    /**
     * 扩展
     **/
    private static final Map<String, Integer> KEY_USAGE = new HashMap<>();


    /**
     * 构建扩展
     *
     * @param basicConstraintsType
     * @param extensionsTypeCritical
     * @param keyUsage
     * @param keyUsageCritical
     * @return
     * @throws Exception
     */
    public static List<Extension> getExtensions(String basicConstraintsType, boolean extensionsTypeCritical,
                                                String[] keyUsage, boolean keyUsageCritical) throws Exception {
        List<Extension> extensions = new ArrayList<Extension>();
        if (StringUtils.isNotEmpty(basicConstraintsType) && !basicConstraintsType.equals("NotDefined")) {
            BasicConstraints basicConstraints = new BasicConstraints(basicConstraintsType.equals("CertificationAuthority"));
            Extension extension = new Extension(Extension.basicConstraints, extensionsTypeCritical, new DEROctetString(basicConstraints));
            extensions.add(extension);
        }
        if (keyUsage != null && keyUsage.length > 0) {
            int result = 0;
            if (keyUsage != null && keyUsage.length > 0) {
                for (String usage : keyUsage) {
                    if (usage == null || usage.length() < 1) {
                        continue;
                    }
                    result |= KEY_USAGE.get(usage.toLowerCase());
                }
            }
            KeyUsage keyUsage2 = new KeyUsage(result);
            Extension extension = new Extension(Extension.keyUsage, keyUsageCritical, new DEROctetString(keyUsage2));
            extensions.add(extension);
        }
        return extensions;
    }

    /**
     * 创建CSR证书请求文件
     *
     * @param alias
     * @param keyStorePath
     * @return
     */
    @SneakyThrows
    public static Map<String, Object> createCsr(String alias, String keyStorePath) {
        Map<String, Object> result = new HashMap<>();
        // 主题
        String subjectDn = generateDN("CN", "Shanghai",
                "Shanghai", "dream", "dev",
                "dream-keyPair", "contactus@wdreaam.com");
        // 公钥用途
        String keyUsage = "";
        String[] keyUsages = null;
        if (keyUsage != null) {
            keyUsages = keyUsage.split(",");
        }
        X500Name subject = new X500Name(subjectDn);
        KeyPair keyPair = getKeyPair(alias, getStoreFile(keyStorePath));
        // 公钥用途扩展
        List<Extension> extensions = getExtensions(null, false, keyUsages, true);
        // CSR证书请求文件
        PKCS10CertificationRequest certificationRequest = generateCsr(SIGNATURE_ALGORITHM,
                keyPair.getPrivate(),
                convert(keyPair.getPublic()),
                subject,
                extensions);
        // CSR文件写入到本地
        String csrPath = "/csr/" + getTempFileName() + ".csr";
        File csrFile = getStoreFile(csrPath);
        System.out.println("CSR存储文件地址===>" + csrFile.getAbsolutePath());
        byte[] bytes = certificationRequest.getEncoded();
        String s = Base64.getEncoder().encodeToString(bytes);
        System.out.println("-----BEGIN CSR-----");
        System.out.println(s);
        System.out.println("-----END CSR-----");
        OutputStream out = new FileOutputStream(csrFile);
        PemWriter writer = new PemWriter(new OutputStreamWriter(out));
        writer.writeObject(new JcaMiscPEMGenerator(certificationRequest));
        writer.close();
        result.put("csr", certificationRequest);
        result.put("csrPath", csrPath);
        return result;
    }

    /**
     * ======================生成/签发Certificate证书,存储到本地=================
     */

    /**
     * 判断文件格式pem(true)和der(false)
     *
     * @param file
     * @return
     */
    public static boolean isPemFormat(File file) {
        try {
            FileInputStream inStream = new FileInputStream(file);
            byte[] b = new byte[4];
            inStream.read(b);
            inStream.close();
            if (Arrays.equals(b, new byte[] {0x2D, 0x2D, 0x2D, 0x2D})) {
                return true;
            }
            return false;
        } catch (IOException e) {
            log.error("", e);
        }
        return false;
    }

    /**
     * 生成Certificate证书存储到本地
     *
     * @param alias 密钥别名
     * @param keyStorePath 密钥文件
     * @param parentCert 父级证书
     * @return
     */
    @SneakyThrows
    public static Map<String, Object> createCert(String alias, String keyStorePath, X509Certificate parentCert) {
        Map<String, Object> result = new HashMap<>();
        // X509格式证书
        X509Certificate cert = null;
        // 对应参数
        Date notBefore = DateUtil.date();
        Date notAfter = DateUtil.date();
        // 主题 || 父节点主题DN
        String subjectDn = generateDN("selfSubject-CN", "Shanghai",
                "Shanghai", "dream", "dev",
                "dream-keyPair", "contactus@wdreaam.com");
        // 子级节点
        X500Name selfSubject = new X500Name(subjectDn);
        String subjectParentDn = generateDN("subjectParent-CN", "Shanghai",
                "Shanghai", "dream", "dev",
                "dream-keyPair", "contactus@wdreaam.com");
        // 父级节点
        X500Name issuerSubject = new X500Name(subjectParentDn);
        // 密匙对 || 获取父级节点证书的密钥对
        KeyPair keyPair = getKeyPair(alias, getStoreFile(keyStorePath));
        // 公钥用途扩展
        String keyUsage = "";
        String[] keyUsages = null;
        if (keyUsage != null) {
            keyUsages = keyUsage.split(",");
        }
        List<Extension> extensions = getExtensions(null, false, keyUsages, true);
        // 文件存储地址
        String certPath = "/cert/" + getTempFileName() + ".cert";
        if (parentCert == null) {
            /**
             * 1.自签名证书
             */
            cert = generateCertifCate(SIGNATURE_ALGORITHM,
                    keyPair.getPrivate(),
                    convert(keyPair.getPublic()),
                    selfSubject,
                    selfSubject,
                    notBefore,
                    notAfter,
                    extensions);
        }else{
            /**
             * 2.利用父证书签发当前正在创建的证书
             * 密钥使用父级节点密钥
             * 主题使用父级节点主题
             */
            System.out.println("CertifCate父级节点主题===>" + parentCert.getSubjectDN().getName());
            certPath = "/cert/child-" + getTempFileName() + ".cert";
            cert = generateCertifCate(SIGNATURE_ALGORITHM,
                    keyPair.getPrivate(),
                    convert(keyPair.getPublic()),
                    selfSubject,
                    issuerSubject,
                    notBefore,
                    notAfter,
                    extensions);

        }
        // 证书以文件形式保存到磁盘
        File certFile = getStoreFile(certPath);
        System.out.println("CertifCate存储文件地址===>" + certFile.getAbsolutePath());
        FileOutputStream out = new FileOutputStream(certFile);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);
        PemWriter writer = new PemWriter(outputStreamWriter);
        writer.writeObject(new JcaMiscPEMGenerator(cert));
        writer.close();
        result.put("cert", cert);
        result.put("certPath", certPath);
        return result;
    }

    /**
     * 签发Certificate证书存储到本地(签发证书签名请求)
     *
     * @param alias 密钥别名
     * @param keyStorePath 密钥文件
     * @param certIssuerPath Certificate证书文件
     * @param csrIssuerFile CSR证书请求文件
     * @return
     */
    @SneakyThrows
    public static X509Certificate issuerCsr(String alias, String keyStorePath, String certIssuerPath, File csrIssuerFile) {
        // X509格式证书
        X509Certificate cert = null;
        /*********************************读取CSR文件*******************************/
        // 判断文件格式pem(true)和der(false)
        System.out.println("签发证书CSR请求文件地址===>" + csrIssuerFile.getAbsolutePath());
        PKCS10CertificationRequest csr = null;
        FileInputStream inStream = new FileInputStream(csrIssuerFile);
        if (isPemFormat(csrIssuerFile)) {
            PEMParser parser = new PEMParser(new InputStreamReader(inStream));
            csr = (PKCS10CertificationRequest) parser.readObject();
        }else{
            csr = new PKCS10CertificationRequest(IOUtils.toByteArray(inStream));
        }
        /*********************************读取Certificate文件*******************************/
        System.out.println("签发证书Certificate文件地址===>" + certIssuerPath);
        File certIssuerFile = getStoreFile(certIssuerPath);
        // 判断文件格式pem(true)和der(false)
        X509Certificate certIssuer = null;
        if (isPemFormat(certIssuerFile)) {
            PEMParser parser = new PEMParser(new FileReader(certIssuerFile));
            try {
                Object obj = parser.readObject();
                if (obj instanceof X509CertificateHolder) {
                    X509CertificateHolder holder = (X509CertificateHolder) obj;
                    byte[] certBuf = holder.getEncoded();
                    CertificateFactory certFactory = CertificateFactory.getInstance(CERTFICATE_TYPE, "BC");
                    certIssuer = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(certBuf));
                } else {
                    certIssuer = (X509Certificate) obj;
                }
            } finally {
                parser.close();
            }
        }else{
            inStream = new FileInputStream(certIssuerFile);
            CertificateFactory certFactory = CertificateFactory.getInstance(CERTFICATE_TYPE);
            certIssuer =  (X509Certificate) certFactory.generateCertificate(inStream);
        }
        // 获取父级主题
        X500Principal principal = certIssuer.getSubjectX500Principal();
        X500Name parentSubjectDn = X500Name.getInstance(principal.getEncoded());
        /*********************************签发证书*******************************/
        // 对应参数
        Date notBefore = DateUtil.date();
        Date notAfter = DateUtil.date();
        // 密匙对
        KeyPair keyPair = getKeyPair(alias, getStoreFile(keyStorePath));
        // 公钥用途扩展
        String keyUsage = "";
        String[] keyUsages = null;
        if (keyUsage != null) {
            keyUsages = keyUsage.split(",");
        }
        List<Extension> extensions = getExtensions(null, false, keyUsages, true);
        // 生成签发的证书文件
        cert = generateCertifCate(SIGNATURE_ALGORITHM,
                keyPair.getPrivate(),
                csr.getSubjectPublicKeyInfo(),
                csr.getSubject(),
                parentSubjectDn,
                notBefore,
                notAfter,
                extensions);
        // 证书以文件形式保存到磁盘
        String certPath = "/cert/issuer-" + getTempFileName() + ".cert";
        File certFile = getStoreFile(certPath);
        System.out.println("签发证书生成CertifCate存储文件地址===>" + certFile.getAbsolutePath());
        FileOutputStream out = new FileOutputStream(certFile);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);
        PemWriter writer = new PemWriter(outputStreamWriter);
        writer.writeObject(new JcaMiscPEMGenerator(cert));
        writer.close();

        String csrPath = "/csr/issuer-" + getTempFileName() + ".csr";
        File csrStoreFile = getStoreFile(csrPath);
        FileUtils.copyFile(csrIssuerFile, csrStoreFile);
        System.out.println("签发证书生成CSR存储文件地址===>" + csrStoreFile.getAbsolutePath());
        return cert;
    }


    @SneakyThrows
    public static void main(String[] args) {
        System.out.println("=====================生成KeyPair,存储KeyStore=================");
        Map<String, String> result = saveKeyStore(createKeyPair());
        KeyPair keyPair = getKeyPair(result.get("alias"), getStoreFile(result.get("keyStorePath")));
        System.out.println("private Key===>" + Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded()));
        System.out.println("public Key===>" + Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()));
        System.out.println("=====================生成CSR请求文件,存储到本地=================");
        Map<String, Object> csrResult = createCsr(result.get("alias"), result.get("keyStorePath"));
        String csrPath = (String) csrResult.get("csrPath");
        System.out.println("=====================生成Certificate证书,存储到本地=================");
        Map<String, Object> parentResult = createCert(result.get("alias"), result.get("keyStorePath"), null);
        X509Certificate parentCert = (X509Certificate) parentResult.get("cert");
        String certPath = (String) parentResult.get("certPath");
        createCert(result.get("alias"), result.get("keyStorePath"), parentCert);
        System.out.println("=====================签发Certificate证书,存储到本地=================");
        issuerCsr(result.get("alias"), result.get("keyStorePath"), certPath, getStoreFile(csrPath));
    }

}

我在人间贩卖黄昏 只为收集世间温柔去见你

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Bouncy Castle是一个Java加库,它提供了许多加算法、生成证书管理以及其他安全功能的实现。它是开源的,并且在许多项目中被广泛使用。 使用Bouncy Castle,首先需要将其添加到项目的依赖项中。可以通过在构建工具(如Maven或Gradle)中添加相应的依赖来实现。然后,可以在代码中引入Bouncy Castle的各种类和函数。 一些常用功能的使用示例如下: 1. 对称加算法:可以使用Bouncy Castle实现常见的对称加算法(如AES、DES)进行加解操作。首先需要创建加器或解器对象,并为其提供和其他必要的参数。然后可以调用相应的方法来对数据进行加或解。 2. 非对称加算法:Bouncy Castle支持常见的非对称加算法(如RSA、DSA、ECC)。可以使用Bouncy Castle生成对,对数据进行签名和验证,以及进行交换等操作。 3. 消息摘要算法:Bouncy Castle提供了各种安全哈希算法(如MD5、SHA-1、SHA-256)的实现。可以使用Bouncy Castle计算数据的哈希值,并进行数字签名和验证等操作。 4. 数字证书管理:Bouncy Castle提供了一套用于数字证书管理的API。可以使用Bouncy Castle创建、读取和验证数字证书,以及进行生成和管理。 总之,Bouncy Castle是一个功能强大的加库,可以用于实现各种加和安全相关的功能。它的使用方法多种多样,需要根据具体的需求选择合适的API和方法进行调用。在使用Bouncy Castle时,应注意遵循相关的安全最佳实践,以确保数据的机性和完整性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值