package com.qianwen.license.keystore;
|
|
import java.io.FileInputStream;
|
import java.io.FileOutputStream;
|
import java.io.FileReader;
|
import java.math.BigInteger;
|
import java.security.KeyFactory;
|
import java.security.KeyStore;
|
import java.security.PrivateKey;
|
import java.security.PublicKey;
|
import java.security.Security;
|
import java.security.cert.Certificate;
|
import java.security.cert.CertificateFactory;
|
import java.security.cert.X509Certificate;
|
|
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
import org.bouncycastle.asn1.x500.X500Name;
|
import org.bouncycastle.jce.provider.PEMUtil;
|
import org.bouncycastle.openssl.PEMParser;
|
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
import org.bouncycastle.util.io.pem.PemObject;
|
import org.bouncycastle.util.io.pem.PemReader;
|
|
import cn.hutool.core.date.DateField;
|
import cn.hutool.core.date.DateTime;
|
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.crypto.KeyUtil;
|
import cn.hutool.crypto.PemUtil;
|
|
public class PubKeyGenDemo {
|
static String root = "d:/cert";
|
/**
|
* 自签名根证书私钥保存路径 /ca/ca-private.key
|
*/
|
private static final String CA_PRIVATE_KEY_FILE_PATH = StrUtil.format("{}/ca/ca-private.key", root);
|
/**
|
* 自签名根证书公钥保存路径 /ca/ca-public.key
|
*/
|
private static final String CA_PUBLIC_KEY_FILE_PATH = StrUtil.format("{}/ca/ca-public.key", root);
|
/**
|
* 自签名根证书保存路径ca/ca.cer
|
*/
|
private static final String CA_CERTIFICATE_FILE_PATH = StrUtil.format("{}/ca/ca.cer", root);
|
/**
|
* 自签名证书私钥保存路径self/self-private.key
|
*/
|
private static final String SELF_SIGNED_PRIVATE_KEY_FILE_PATH = StrUtil.format("{}/self/self-private.key", root);
|
/**
|
* 自签名证书公钥保存路径self/self-public.key
|
*/
|
private static final String SELF_SIGNED_PUBLIC_KEY_FILE_PATH = StrUtil.format("{}/self/self-public.key", root);
|
/**
|
* 自签名证书保存路径 self/self.cer
|
*/
|
private static final String SELF_SIGNED_CERTIFICATE_FILE_PATH = StrUtil.format("{}/self/self.cer", root);
|
/**
|
* pkcs12 格式证书保存路径 self/self.p12
|
*/
|
private static final String SELF_SIGNED_PKCS12_FILE_PATH = StrUtil.format("{}/self/self.p12", root);
|
|
/**
|
* pkcs12 公钥库格式证书保存路径
|
*/
|
private static final String SELF_SIGNED_PUBLIC_PKCS12_FILE_PATH = StrUtil.format("{}/self/publicself.p12", root);
|
/**
|
* pkcs12 格式证书密码
|
*/
|
private static final String SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD = "a1b2c3";
|
|
public static void main(String[] args) throws Throwable {
|
|
//Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
|
|
toCaCertificate();
|
|
toSelfSignedCertificate();
|
|
toPrivatePkcs12Store();
|
|
toPublicPkcs12Store();
|
}
|
|
/**
|
* 生成根证书及其密钥对,保存位2个key文件和一个ca.cer,这个在后续只是一个颁发者的属性需要使用
|
* @throws Throwable
|
*/
|
public static void toCaCertificate() throws Throwable {
|
//根证书主题信息
|
X500Name subject = new SubjectBuilder()
|
.setCn("yangys")
|
.setO("My CA organization")
|
.setOu("My CA organizational unit name")
|
.setC("My CA country code")
|
.setSt("My CA state, or province name")
|
.setL("My CA locality name")
|
.build();
|
|
//根证书颁发者信息,即自身
|
X500Name issuer = subject;
|
|
//根证书有效期
|
DateTime notBefore = DateUtil.yesterday();
|
DateTime notAfter = DateUtil.offset(notBefore, DateField.YEAR, 10);
|
|
CertificateInfo certificateInfo = new CertificateInfo();
|
certificateInfo.setSerial(BigInteger.valueOf(RandomUtil.randomLong(1L, Long.MAX_VALUE)));
|
certificateInfo.setIssuer(issuer);
|
certificateInfo.setSubject(subject);
|
certificateInfo.setNotBefore(notBefore);
|
certificateInfo.setNotAfter(notAfter);
|
certificateInfo.setKeyAlgorithm(X509CertificateConstants.KEY_ALGORITHM);
|
certificateInfo.setSignAlgorithm(X509CertificateConstants.SIGN_ALGORITHM);
|
|
//生成根证书及其密钥对
|
KeyAndCertificate keyAndCertificate = CertificateUtils.generateCertificate(certificateInfo, null);
|
//保存根证书及其密钥对到磁盘
|
CertificateUtils.save(keyAndCertificate.getPrivateKey(), CA_PRIVATE_KEY_FILE_PATH);
|
CertificateUtils.save(keyAndCertificate.getPublicKey(), CA_PUBLIC_KEY_FILE_PATH);
|
CertificateUtils.save(keyAndCertificate.getCertificate(), CA_CERTIFICATE_FILE_PATH);
|
}
|
|
/**
|
* 生成自签名证书及其密钥对
|
* @throws Throwable
|
*/
|
|
public static void toSelfSignedCertificate() throws Throwable {
|
//根证书私钥
|
PrivateKey caPrivateKey;
|
//从磁盘加载根证书私钥
|
try(FileInputStream fileInputStream = new FileInputStream(CA_PRIVATE_KEY_FILE_PATH);) {
|
caPrivateKey = PemUtil.readPemPrivateKey(fileInputStream);
|
}
|
|
//从磁盘加载根证书
|
X509Certificate caCertificate;
|
try(FileInputStream fileInputStream = new FileInputStream(CA_CERTIFICATE_FILE_PATH);) {
|
caCertificate = (X509Certificate) KeyUtil.readX509Certificate(fileInputStream);
|
}
|
|
//证书颁发者信息
|
X500Name issuer = new X500Name(caCertificate.getIssuerX500Principal().getName());
|
|
//证书主题信息
|
X500Name subject = new SubjectBuilder()
|
.setCn("My common name")
|
.setO("My organization")
|
.setOu("My organizational unit name")
|
.setC("My country code")
|
.setSt("My state, or province name")
|
.setL("My locality name")
|
.build();
|
|
//证书有效期
|
DateTime notBefore = DateUtil.yesterday();
|
DateTime notAfter = DateUtil.offset(notBefore, DateField.YEAR, 10);
|
|
CertificateInfo certificateInfo = new CertificateInfo();
|
certificateInfo.setSerial(BigInteger.valueOf(RandomUtil.randomLong(1L, Long.MAX_VALUE)));
|
certificateInfo.setIssuer(issuer);
|
certificateInfo.setSubject(subject);
|
certificateInfo.setNotBefore(notBefore);
|
certificateInfo.setNotAfter(notAfter);
|
certificateInfo.setKeyAlgorithm(X509CertificateConstants.KEY_ALGORITHM);
|
certificateInfo.setSignAlgorithm(X509CertificateConstants.SIGN_ALGORITHM);
|
|
//生成自签名证书及其密钥对
|
KeyAndCertificate keyAndCertificate = CertificateUtils.generateCertificate(certificateInfo, caPrivateKey);
|
//保存自签名证书及其密钥对到磁盘
|
CertificateUtils.save(keyAndCertificate.getPrivateKey(), SELF_SIGNED_PRIVATE_KEY_FILE_PATH);
|
CertificateUtils.save(keyAndCertificate.getPublicKey(), SELF_SIGNED_PUBLIC_KEY_FILE_PATH);
|
CertificateUtils.save(keyAndCertificate.getCertificate(), SELF_SIGNED_CERTIFICATE_FILE_PATH);
|
}
|
|
/**
|
* 生成 pkcs12 格式证书,根据情况,可胜场公,私2中证书
|
* @throws Exception
|
*/
|
|
public static void toPrivatePkcs12Store() throws Exception {
|
char[] password = SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD.toCharArray();
|
//证书私钥
|
PrivateKey privateKey;
|
//从磁盘加载证书私钥
|
try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_PRIVATE_KEY_FILE_PATH)) {
|
privateKey = PemUtil.readPemPrivateKey(fileInputStream);
|
}
|
//证书
|
Certificate certificate;
|
//从磁盘加载证书
|
try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_CERTIFICATE_FILE_PATH)) {
|
certificate = KeyUtil.readX509Certificate(fileInputStream);
|
}
|
KeyStore pkcs12 = KeyStore.getInstance("pkcs12");
|
pkcs12.load(null, password);
|
pkcs12.setKeyEntry("myPrivate", privateKey, password, new Certificate[] {certificate});
|
try(FileOutputStream fileOutputStream = new FileOutputStream(SELF_SIGNED_PKCS12_FILE_PATH)) {
|
pkcs12.store(fileOutputStream, password);
|
}
|
}
|
|
|
public static void toPublicPkcs12Store() throws Exception {
|
char[] password = SELF_SIGNED_PKCS12_CERTIFICATE_PASSWORD.toCharArray();
|
// 加载证书
|
|
Certificate certificate;
|
//从磁盘加载证书,就是用keytool从私钥导出的证书
|
|
try(FileInputStream fileInputStream = new FileInputStream(SELF_SIGNED_CERTIFICATE_FILE_PATH)) {
|
certificate = KeyUtil.readX509Certificate(fileInputStream);
|
}
|
|
KeyStore pkcs12 = KeyStore.getInstance("pkcs12");//自己改的, "BC"
|
pkcs12.load(null, password);
|
|
String alias = "myPublicKey";
|
pkcs12.setCertificateEntry(alias, certificate);
|
//pkcs12.setKeyEntry("myPublicKey", publicKey, password, new Certificate[] {certificate});
|
try(FileOutputStream fileOutputStream = new FileOutputStream(SELF_SIGNED_PUBLIC_PKCS12_FILE_PATH)) {
|
pkcs12.store(fileOutputStream, password);
|
}
|
}
|
}
|