赞
踩
开放签电子签章系统-开源版这周(2023-12-15)就要上线发布了,为了让开源版能够更好的服务广大研发工程师,接下来会详细的说说开源版从代码层面的具体实现,以便大家在工作过程中更好使用开放签电子签章系统。本文主要讲开放签开源电子签章系统Java后端代码中关于数字证书生成的Java代码。
bouncycastle
java.security
(1)生成数字证书主题信息
- import org.bouncycastle.asn1.x500.X500NameBuilder;
- import org.bouncycastle.asn1.x500.style.BCStyle;
-
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.security.Key;
- import java.security.KeyStore;
- import java.security.cert.Certificate;
- import java.util.Enumeration;
-
- public class CertificateUtils {
-
- /**
- * 生成证书主题信息
- *
- * @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: xxxxxx网络技术有限公司
- * @param OU Organizational Unit Name (可以是单位部门名称)
- * @param CN Common Name (服务器ip或者域名或者公司名称),eg: 192.168.30.71 or www.baidu.com or xxxxxx网络技术有限公司
- * @return X500Name Subject
- */
- public static String buildSubject(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);
- if(O != null)
- x500NameBuilder.addRDN(BCStyle.O, O);
- if(OU != null)
- x500NameBuilder.addRDN(BCStyle.OU, OU);
- x500NameBuilder.addRDN(BCStyle.CN, CN);
- System.out.println(x500NameBuilder.build().toASN1Primitive().toString());
- return x500NameBuilder.build().toString();
- }
-
- public static byte [] coverToPfx(byte [] jks, String password) {
- try {
-
- KeyStore inputKeyStore = KeyStore.getInstance("JKS");
- ByteArrayInputStream inputStream = new ByteArrayInputStream(jks);
- inputKeyStore.load(inputStream, password.toCharArray());
-
- KeyStore outputKeyStore = KeyStore.getInstance("PKCS12");
-
- outputKeyStore.load(null, password.toCharArray());
-
- Enumeration enums = inputKeyStore.aliases();
-
- while (enums.hasMoreElements()) { // we are readin just one certificate.
-
- String keyAlias = (String) enums.nextElement();
-
- if (inputKeyStore.isKeyEntry(keyAlias)) {
- Key key = inputKeyStore.getKey(keyAlias, password.toCharArray());
- Certificate[] certChain = inputKeyStore
- .getCertificateChain(keyAlias);
-
- outputKeyStore.setKeyEntry("", key, password
- .toCharArray(), certChain);
- }
- }
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- outputKeyStore.store(out, password.toCharArray());
- out.close();
- return out.toByteArray();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
-
- }
(2)数字证书生成过程信息
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- import java.util.Date;
-
-
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public class GenerateCertificateInfo {
-
- /**
- * 证书密码
- */
- private String password;
-
- /**
- * 证书类型 JKS PFX
- */
- private String certFileType;
-
- /**
- * 证书库
- */
- private byte [] jks;
-
-
- /**
- * 签名证书
- */
- private byte [] pfx;
-
- /**
- * 证书序列号
- */
- private String serial;
- /**
- * 证书签名算法 SHA1withRSA SHA256withRSA
- */
- private String algorithmSignature;
-
- /**
- * 证书算法类型: RSA、SM2
- */
- private String algorithm;
-
- /**
- * 证书有效期起始时间
- */
- private Date termOfValidityStartTime;
-
- /**
- * 证书有效期结束时间
- */
- private Date termOfValidityEndTime;
-
-
-
- }
(3)根证书类
- import java.security.KeyStore;
-
- public class BaseCertificateInfo {
-
- /**
- * 根证书
- */
- private KeyStore cert;
-
- /**
- * 证书别名
- */
- private String alias;
-
- /**
- * 证书密码
- */
- private String password;
-
- public KeyStore getCert() {
- return cert;
- }
-
- public void setCert(KeyStore cert) {
- this.cert = cert;
- }
-
- public String getAlias() {
- return alias;
- }
-
- public void setAlias(String alias) {
- this.alias = alias;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
- }
(4)数字证书类型枚举
- public enum CertificateType {
- RSA,SM2
- }
(5)生成数字证书
- import org.bouncycastle.asn1.x500.X500Name;
- import org.bouncycastle.asn1.x509.Extension;
- 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.*;
- import java.math.BigInteger;
- import java.security.*;
- import java.security.cert.Certificate;
- import java.security.cert.CertificateException;
- import java.security.cert.CertificateFactory;
- import java.security.cert.X509Certificate;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import java.util.UUID;
-
- public class GenerateRootCertificate {
-
- //SHA256WITHRSA
-
-
- private String subject;
-
- private String algorithmSignature = "SHA256withRSA";
-
- private CertificateType certificateType;
-
- private GenerateRootCertificate(String subject,CertificateType certificateType){
- this.subject = subject;
- this.certificateType = certificateType;
- }
-
-
- /**
- * @param subject 证书主题
- * 可通过 CertificateUtils.buildSubject进行生成
- */
- public static GenerateRootCertificate instance(String subject,CertificateType certificateType){
- return new GenerateRootCertificate(subject,certificateType);
- }
-
-
- /**
- * 设置证书签名算法 SHA1withRSA SHA256withRSA
- * @param algorithmSignature
- */
- public void setAlgorithmSignature(String algorithmSignature){
- this.algorithmSignature = algorithmSignature;
- }
-
-
- /**
- * 证书类型
- * @param password
- * @param lifespan 单位年
- *
- * @return
- */
- public GenerateCertificateInfo generateCertificate(BaseCertificateInfo root, String password, int lifespan) throws Exception {
- X500Name issuer = new X500Name(subject);
- KeyStore.PrivateKeyEntry rootPK = null;
- PrivateKey signPrivateKey = null;
- List<Certificate> chains = new ArrayList<>(5);
- if(root != null){
- rootPK = (KeyStore.PrivateKeyEntry) root.getCert().getEntry(root.getAlias(),
- new KeyStore.PasswordProtection(root.getPassword().toCharArray()));
- X509Certificate rootCert = (X509Certificate) rootPK.getCertificate();
-
- issuer = X500Name.getInstance(rootCert.getSubjectX500Principal().getEncoded());
-
- signPrivateKey = rootPK.getPrivateKey();
-
- Certificate [] rootChains = rootPK.getCertificateChain();
- for (int i=0;i<rootChains.length;i++){
- chains.add(rootChains[i]);
- }
- }
-
- KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
- kpg.initialize(2048);
- KeyPair keyPair = kpg.generateKeyPair();
-
- KeyStore keyStore = KeyStore.getInstance("JKS");
- keyStore.load(null, null);
-
- Date startDate = new Date(System.currentTimeMillis());
- Date expireDate = new Date(System.currentTimeMillis() + (86400000L * 365 * lifespan));
-
- String serial = UUID.randomUUID().toString().replaceAll("-","");
- BigInteger serialBig = str2BigInteger(serial);
-
- if(signPrivateKey == null){
- signPrivateKey = keyPair.getPrivate();
- }
- Certificate cert = generateV3(issuer, new X500Name(subject),serialBig, startDate,expireDate, keyPair.getPublic(),
- signPrivateKey
- , null);
-
- //用户证书要放在证书链的最前面
- chains.add(0,cert);
-
- keyStore.setKeyEntry("root", keyPair.getPrivate(), password.toCharArray(), chains.toArray(new Certificate[chains.size()]));
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- keyStore.store(outputStream,password.toCharArray());
-
-
- GenerateCertificateInfo certificateInfo = new GenerateCertificateInfo();
- certificateInfo.setAlgorithm(certificateType.name());
- certificateInfo.setAlgorithmSignature(algorithmSignature);
- certificateInfo.setPassword(password);
- certificateInfo.setCertFileType("jks");
- certificateInfo.setSerial(serial);
- certificateInfo.setJks(outputStream.toByteArray());
- certificateInfo.setPfx(CertificateUtils.coverToPfx(certificateInfo.getJks(),certificateInfo.getPassword()));
-
- certificateInfo.setTermOfValidityStartTime(startDate);
- certificateInfo.setTermOfValidityEndTime(expireDate);
-
- return certificateInfo;
- }
-
- public Certificate generateV3(X500Name issuer, X500Name subject,
- BigInteger serial, Date startDate, Date expireDate,
- PublicKey publicKey, PrivateKey privKey, List<Extension> extensions) throws IOException, CertificateException, OperatorCreationException {
-
- X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
- issuer, serial, startDate, expireDate,
- subject, publicKey);
- ContentSigner sigGen = new JcaContentSignerBuilder(algorithmSignature).build(privKey);
- //privKey是CA的私钥,publicKey是待签名的公钥,那么生成的证书就是被CA签名的证书。
- if (extensions != null){
- for (Extension ext : extensions) {
- builder.addExtension(ext.getExtnId(), ext.isCritical(),ext.getExtnValue());
- }
- }
- X509CertificateHolder holder = builder.build(sigGen);
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- InputStream is1 = new ByteArrayInputStream(holder.toASN1Structure()
- .getEncoded());
- X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);
- is1.close();
- return theCert;
- }
-
-
- public static void main(String[] args) throws Exception {
- //
- KeyStore store = loadJKS("Ting111");
- BaseCertificateInfo baseCertificateInfo = new BaseCertificateInfo();
- baseCertificateInfo.setAlias("root");
- baseCertificateInfo.setCert(store);
- baseCertificateInfo.setPassword("123456");
- String x500Name = "CN=Ting222,OU=研发部,O=资源律动,L=BeiJing,ST=BeiJing,C=CN";
-
- GenerateCertificateInfo certificateInfo = GenerateRootCertificate.instance(x500Name,CertificateType.RSA).generateCertificate(baseCertificateInfo,"123456",10);
- FileUtils.writeByteArrayToFile(new File("C:\\Users\\Administrator\\Desktop\\tem\\cert\\Ting222.jks"), certificateInfo.getJks());
-
- }
-
- private static BigInteger str2BigInteger(String str){
- StringBuffer sb = new StringBuffer();
- //将字符串转换为字符数组
- char ch[] = str.toCharArray();
- for(int i = 0; i < ch.length; i++) {
- String hexString = Integer.toHexString(ch[i]);
- sb.append(hexString);
- }
- return new BigInteger(sb.toString());
- }
-
- private static String big2String(String str){
- String result = new String();
- char[] charArray = str.toString().toCharArray();
- for(int i = 0; i < charArray.length; i=i+2) {
- String st = ""+charArray[i]+""+charArray[i+1];
- char ch1 = (char)Integer.parseInt(st, 16);
- result = result + ch1;
- }
- return result;
- }
-
-
-
- public static KeyStore loadJKS(String name) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
- KeyStore store = KeyStore.getInstance("JKS");
- File file = new File(""+name+".jks");
- store.load(new FileInputStream(file), "123456".toCharArray());
- return store;
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。