All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.shepherdviolet.glacimon.java.crypto.PKCS12KeyStoreUtils Maven / Gradle / Ivy

/*
 * Copyright (C) 2022-2022 S.Violet
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Project GitHub: https://github.com/shepherdviolet/glacimon
 * Email: [email protected]
 */

package com.github.shepherdviolet.glacimon.java.crypto;

import com.github.shepherdviolet.glacimon.java.misc.CloseableUtils;

import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;

/**
 * 

PKCS12密钥文件工具(p12/pfx)

* *

* OPENSSL查看p12文件信息: * openssl pkcs12 -in pkcs12-test.p12 -info -noout *

* *

* Windows查看证书信息: * certmgr.msc *

* *

* 可以用同样的代码操作 JKS 密钥文件, 只要 ALGORITHM = "JKS" 即可. * 没有把PKCS12和JKS整合是因为AdvancedPKCS12KeyStoreUtils中操作PKCS12的代码无法通用, 而JKS文件可以用keytool命令转PKCS12. * keytool -list -v -keystore name.jks * keytool -importkeystore -srckeystore name.jks -destkeystore name.p12 -deststoretype pkcs12 *

* * @author shepherdviolet */ public class PKCS12KeyStoreUtils { private static final String ALGORITHM = "PKCS12"; /** * 将证书和私钥保存到p12/pfx文件中, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *

{@code * //output user p12 * PKCS12KeyStoreUtils.storeCertificateAndKey( * "user-cert.p12", * "000000", * "Glacijava test user cert", * userPrivateKey, * userCertificate); * * ////output root p12 * PKCS12KeyStoreUtils.storeCertificateAndKey( * "root-cert.p12", * "000000", * "Glacijava test ca cert", * null, * caCertificate); * }

* * @param keyStorePath keyStore的文件路径 * @param keyStorePassword keyStore的密码 * @param alias 证书和私钥的别名 * @param privateKey 证书对应的私钥(如果为空, 则仅保存证书) * @param certificateChain 证书链, 通常传入一个证书即可, 用户证书/CA证书/根证书一般会分别导出独立的文件. 如果需要一次性导出整个 * 证书链到一个文件, 也可以传入多个证书, 顺序是个人证书->二级CA证书->根证书, {userCertificate, subCaCertificate, rootCertificate} */ public static void storeCertificateAndKey(String keyStorePath, String keyStorePassword, String alias, PrivateKey privateKey, Certificate... certificateChain) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { File keyStoreFile = new File(keyStorePath); File dirFile = keyStoreFile.getParentFile(); if (dirFile != null && !dirFile.exists()){ if (!dirFile.mkdirs()){ throw new IOException("Can not make directory for keyStore, path:" + dirFile.getAbsolutePath()); } } try (FileOutputStream keyStoreOutputStream = new FileOutputStream(keyStoreFile)) { storeCertificateAndKey(keyStoreOutputStream, keyStorePassword, alias, privateKey, certificateChain); } } /** * 将证书和私钥保存到p12/pfx文件中, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *

{@code * //output user p12 * PKCS12KeyStoreUtils.storeCertificateAndKey( * outputStream1, * "000000", * "Glacijava test user cert", * userPrivateKey, * userCertificate); * * ////output root p12 * PKCS12KeyStoreUtils.storeCertificateAndKey( * outputStream2, * "000000", * "Glacijava test ca cert", * null, * caCertificate); * }

* * @param keyStoreOutputStream keyStore的输出流, 完成后会关闭 * @param keyStorePassword keyStore的密码 * @param alias 证书和私钥的别名, 无私钥且证书不止一个时, 别名会变成0,1,2,... * @param privateKey 证书对应的私钥(如果为空, 则仅保存证书) * @param certificateChain 证书链, 通常传入一个证书即可, 用户证书/CA证书/根证书一般会分别导出独立的文件. 如果需要一次性导出整个 * 证书链到一个文件, 也可以传入多个证书, 顺序是个人证书->二级CA证书->根证书, {userCertificate, subCaCertificate, rootCertificate} */ public static void storeCertificateAndKey(OutputStream keyStoreOutputStream, String keyStorePassword, String alias, PrivateKey privateKey, Certificate... certificateChain) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { try { if (certificateChain == null || certificateChain.length <= 0){ throw new IllegalAccessError("Null or empty certificateChain"); } KeyStore keyStore = KeyStore.getInstance(ALGORITHM); keyStore.load(null, null); if (privateKey != null) { keyStore.setKeyEntry(alias, privateKey, keyStorePassword != null ? keyStorePassword.toCharArray() : null, certificateChain); } else if (certificateChain.length == 1) { keyStore.setCertificateEntry(alias, certificateChain[0]); } else { //无私钥且证书不止一个时, 别名改成0,1,2,... int i = 0; for (Certificate certificate : certificateChain){ keyStore.setCertificateEntry(String.valueOf(i++), certificate); } } keyStore.store(keyStoreOutputStream, keyStorePassword != null ? keyStorePassword.toCharArray() : null); } finally { CloseableUtils.closeQuiet(keyStoreOutputStream); } } /** * 从p12/pfx文件中遍历alias, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      Enumeration aliases = PKCS12KeyStoreUtils.loadAliases(
     *          "ca-cert.p12",
     *          "000000"
     *          );
     * }
* * @param keyStorePath keyStore路径 * @param keystorePassword keyStore密码 */ public static Enumeration loadAliases(String keyStorePath, String keystorePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { File keyStoreFile = new File(keyStorePath); if (!keyStoreFile.exists()){ throw new IOException("Can not find keyStore file, path:" + keyStoreFile.getAbsolutePath()); } return loadAliases(new FileInputStream(keyStoreFile), keystorePassword); } /** * 从p12/pfx文件中遍历alias, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      Enumeration aliases = PKCS12KeyStoreUtils.loadAliases(
     *          inputStream,
     *          "000000"
     *          );
     * }
* * @param inputStream keyStore输入流, 完成后会关闭 * @param keystorePassword keyStore密码 */ public static Enumeration loadAliases(InputStream inputStream, String keystorePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { try { KeyStore keyStore = KeyStore.getInstance(ALGORITHM); keyStore.load(inputStream, keystorePassword != null ? keystorePassword.toCharArray() : null); return keyStore.aliases(); } finally { CloseableUtils.closeQuiet(inputStream); } } /** * 从p12/pfx文件中读取证书和私钥, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      PKCS12KeyStoreUtils.CertificateChainAndKey certificateChainAndKey = PKCS12KeyStoreUtils.loadCertificateAndKey(
     *          "ca-cert.p12",
     *          "000000",
     *          "Glacijava test ca alias"
     *          );
     * }
* * @param keyStorePath keyStore路径 * @param keystorePassword keyStore密码 * @param alias 证书和私钥的别名 */ public static CertificateChainAndKey loadCertificateAndKey(String keyStorePath, String keystorePassword, String alias) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { File keyStoreFile = new File(keyStorePath); if (!keyStoreFile.exists()){ throw new IOException("Can not find keyStore file, path:" + keyStoreFile.getAbsolutePath()); } return loadCertificateAndKey(new FileInputStream(keyStoreFile), keystorePassword, alias); } /** * 从p12/pfx文件中读取证书和私钥, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      PKCS12KeyStoreUtils.CertificateChainAndKey certificateChainAndKey = PKCS12KeyStoreUtils.loadCertificateAndKey(
     *          inputStream,
     *          "000000",
     *          "Glacijava test ca alias"
     *          );
     * }
* * @param inputStream keyStore输入流, 完成后会关闭 * @param keystorePassword keyStore密码 * @param alias 证书和私钥的别名 */ public static CertificateChainAndKey loadCertificateAndKey(InputStream inputStream, String keystorePassword, String alias) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { try { KeyStore keyStore = KeyStore.getInstance(ALGORITHM); keyStore.load(inputStream, keystorePassword != null ? keystorePassword.toCharArray() : null); Certificate[] certificateChain = keyStore.getCertificateChain(alias); if (certificateChain == null){ Certificate certificate = keyStore.getCertificate(alias); if (certificate != null) { certificateChain = new Certificate[]{certificate}; } } return new CertificateChainAndKey(alias, certificateChain, (PrivateKey) keyStore.getKey(alias, keystorePassword != null ? keystorePassword.toCharArray() : null)); } finally { CloseableUtils.closeQuiet(inputStream); } } /** * 从p12/pfx文件中读取证书和私钥, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      List certificateChainAndKeyList = PKCS12KeyStoreUtils.loadAllCertificateAndKey(
     *          "ca-cert.p12",
     *          "000000"
     *          );
     * }
* * @param keyStorePath keyStore路径 * @param keystorePassword keyStore密码 */ public static List loadAllCertificateAndKey(String keyStorePath, String keystorePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { File keyStoreFile = new File(keyStorePath); if (!keyStoreFile.exists()){ throw new IOException("Can not find keyStore file, path:" + keyStoreFile.getAbsolutePath()); } return loadAllCertificateAndKey(new FileInputStream(keyStoreFile), keystorePassword); } /** * 从p12/pfx文件中读取证书和私钥, 本JDK版本较弱, 国密等算法请用glacijava-crypto的AdvancedPKCS12KeyStoreUtils * *
{@code
     *      List certificateChainAndKeyList = PKCS12KeyStoreUtils.loadAllCertificateAndKey(
     *          inputStream,
     *          "000000"
     *          );
     * }
* * @param inputStream keyStore输入流, 完成后会关闭 * @param keystorePassword keyStore密码 */ public static List loadAllCertificateAndKey(InputStream inputStream, String keystorePassword) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException { try { KeyStore keyStore = KeyStore.getInstance(ALGORITHM); keyStore.load(inputStream, keystorePassword != null ? keystorePassword.toCharArray() : null); List list = new ArrayList<>(1); Enumeration aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); Certificate[] certificateChain = keyStore.getCertificateChain(alias); if (certificateChain == null) { Certificate certificate = keyStore.getCertificate(alias); if (certificate != null) { certificateChain = new Certificate[]{certificate}; } } list.add(new CertificateChainAndKey(alias, certificateChain, (PrivateKey) keyStore.getKey(alias, keystorePassword != null ? keystorePassword.toCharArray() : null))); } return list; } finally { CloseableUtils.closeQuiet(inputStream); } } public static class CertificateChainAndKey { private String alias; private Certificate[] certificateChain; private PrivateKey privateKey; protected CertificateChainAndKey(String alias, Certificate[] certificateChain, PrivateKey privateKey) { this.alias = alias; this.certificateChain = certificateChain; this.privateKey = privateKey; } public String getAlias() { return alias; } /** * 获得证书链 */ public Certificate[] getCertificateChain() { return certificateChain; } /** * 获得私钥 */ public PrivateKey getPrivateKey() { return privateKey; } @Override public String toString() { return "CertificateChainAndKey{" + "alias='" + alias + '\'' + ", certificateChain=" + Arrays.toString(certificateChain) + ", privateKey=" + privateKey + '}'; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy