当前位置:   article > 正文

java后端工具类之从0到1生成数字证书(RSA)_java 生成rsa的证书

java 生成rsa的证书

开放签电子签章系统-开源版这周(2023-12-15)就要上线发布了,为了让开源版能够更好的服务广大研发工程师,接下来会详细的说说开源版从代码层面的具体实现,以便大家在工作过程中更好使用开放签电子签章系统。本文主要讲开放签开源电子签章系统Java后端代码中关于数字证书生成的Java代码。

一、需要引用的jar包:

bouncycastle

java.security

二、核心代码:

(1)生成数字证书主题信息

  1. import org.bouncycastle.asn1.x500.X500NameBuilder;
  2. import org.bouncycastle.asn1.x500.style.BCStyle;
  3. import java.io.ByteArrayInputStream;
  4. import java.io.ByteArrayOutputStream;
  5. import java.security.Key;
  6. import java.security.KeyStore;
  7. import java.security.cert.Certificate;
  8. import java.util.Enumeration;
  9. public class CertificateUtils {
  10. /**
  11. * 生成证书主题信息
  12. *
  13. * @param C Country Name (国家代号),eg: CN
  14. * @param ST State or Province Name (洲或者省份),eg: Beijing
  15. * @param L Locality Name (城市名),eg: Beijing
  16. * @param O Organization Name (可以是公司名称),eg: xxxxxx网络技术有限公司
  17. * @param OU Organizational Unit Name (可以是单位部门名称)
  18. * @param CN Common Name (服务器ip或者域名或者公司名称),eg: 192.168.30.71 or www.baidu.com or xxxxxx网络技术有限公司
  19. * @return X500Name Subject
  20. */
  21. public static String buildSubject(String C, String ST, String L,
  22. String O, String OU, String CN) {
  23. X500NameBuilder x500NameBuilder = new X500NameBuilder();
  24. x500NameBuilder.addRDN(BCStyle.C, C);
  25. x500NameBuilder.addRDN(BCStyle.ST, ST);
  26. x500NameBuilder.addRDN(BCStyle.L, L);
  27. if(O != null)
  28. x500NameBuilder.addRDN(BCStyle.O, O);
  29. if(OU != null)
  30. x500NameBuilder.addRDN(BCStyle.OU, OU);
  31. x500NameBuilder.addRDN(BCStyle.CN, CN);
  32. System.out.println(x500NameBuilder.build().toASN1Primitive().toString());
  33. return x500NameBuilder.build().toString();
  34. }
  35. public static byte [] coverToPfx(byte [] jks, String password) {
  36. try {
  37. KeyStore inputKeyStore = KeyStore.getInstance("JKS");
  38. ByteArrayInputStream inputStream = new ByteArrayInputStream(jks);
  39. inputKeyStore.load(inputStream, password.toCharArray());
  40. KeyStore outputKeyStore = KeyStore.getInstance("PKCS12");
  41. outputKeyStore.load(null, password.toCharArray());
  42. Enumeration enums = inputKeyStore.aliases();
  43. while (enums.hasMoreElements()) { // we are readin just one certificate.
  44. String keyAlias = (String) enums.nextElement();
  45. if (inputKeyStore.isKeyEntry(keyAlias)) {
  46. Key key = inputKeyStore.getKey(keyAlias, password.toCharArray());
  47. Certificate[] certChain = inputKeyStore
  48. .getCertificateChain(keyAlias);
  49. outputKeyStore.setKeyEntry("", key, password
  50. .toCharArray(), certChain);
  51. }
  52. }
  53. ByteArrayOutputStream out = new ByteArrayOutputStream();
  54. outputKeyStore.store(out, password.toCharArray());
  55. out.close();
  56. return out.toByteArray();
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. return null;
  61. }
  62. }

(2)数字证书生成过程信息

  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. import java.util.Date;
  5. @Data
  6. @AllArgsConstructor
  7. @NoArgsConstructor
  8. public class GenerateCertificateInfo {
  9. /**
  10. * 证书密码
  11. */
  12. private String password;
  13. /**
  14. * 证书类型 JKS PFX
  15. */
  16. private String certFileType;
  17. /**
  18. * 证书库
  19. */
  20. private byte [] jks;
  21. /**
  22. * 签名证书
  23. */
  24. private byte [] pfx;
  25. /**
  26. * 证书序列号
  27. */
  28. private String serial;
  29. /**
  30. * 证书签名算法 SHA1withRSA SHA256withRSA
  31. */
  32. private String algorithmSignature;
  33. /**
  34. * 证书算法类型: RSA、SM2
  35. */
  36. private String algorithm;
  37. /**
  38. * 证书有效期起始时间
  39. */
  40. private Date termOfValidityStartTime;
  41. /**
  42. * 证书有效期结束时间
  43. */
  44. private Date termOfValidityEndTime;
  45. }

(3)根证书类

  1. import java.security.KeyStore;
  2. public class BaseCertificateInfo {
  3. /**
  4. * 根证书
  5. */
  6. private KeyStore cert;
  7. /**
  8. * 证书别名
  9. */
  10. private String alias;
  11. /**
  12. * 证书密码
  13. */
  14. private String password;
  15. public KeyStore getCert() {
  16. return cert;
  17. }
  18. public void setCert(KeyStore cert) {
  19. this.cert = cert;
  20. }
  21. public String getAlias() {
  22. return alias;
  23. }
  24. public void setAlias(String alias) {
  25. this.alias = alias;
  26. }
  27. public String getPassword() {
  28. return password;
  29. }
  30. public void setPassword(String password) {
  31. this.password = password;
  32. }
  33. }

(4)数字证书类型枚举

  1. public enum CertificateType {
  2. RSA,SM2
  3. }

(5)生成数字证书

  1. import org.bouncycastle.asn1.x500.X500Name;
  2. import org.bouncycastle.asn1.x509.Extension;
  3. import org.bouncycastle.cert.X509CertificateHolder;
  4. import org.bouncycastle.cert.X509v3CertificateBuilder;
  5. import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
  6. import org.bouncycastle.operator.ContentSigner;
  7. import org.bouncycastle.operator.OperatorCreationException;
  8. import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
  9. import java.io.*;
  10. import java.math.BigInteger;
  11. import java.security.*;
  12. import java.security.cert.Certificate;
  13. import java.security.cert.CertificateException;
  14. import java.security.cert.CertificateFactory;
  15. import java.security.cert.X509Certificate;
  16. import java.util.ArrayList;
  17. import java.util.Date;
  18. import java.util.List;
  19. import java.util.UUID;
  20. public class GenerateRootCertificate {
  21. //SHA256WITHRSA
  22. private String subject;
  23. private String algorithmSignature = "SHA256withRSA";
  24. private CertificateType certificateType;
  25. private GenerateRootCertificate(String subject,CertificateType certificateType){
  26. this.subject = subject;
  27. this.certificateType = certificateType;
  28. }
  29. /**
  30. * @param subject 证书主题
  31. * 可通过 CertificateUtils.buildSubject进行生成
  32. */
  33. public static GenerateRootCertificate instance(String subject,CertificateType certificateType){
  34. return new GenerateRootCertificate(subject,certificateType);
  35. }
  36. /**
  37. * 设置证书签名算法 SHA1withRSA SHA256withRSA
  38. * @param algorithmSignature
  39. */
  40. public void setAlgorithmSignature(String algorithmSignature){
  41. this.algorithmSignature = algorithmSignature;
  42. }
  43. /**
  44. * 证书类型
  45. * @param password
  46. * @param lifespan 单位年
  47. *
  48. * @return
  49. */
  50. public GenerateCertificateInfo generateCertificate(BaseCertificateInfo root, String password, int lifespan) throws Exception {
  51. X500Name issuer = new X500Name(subject);
  52. KeyStore.PrivateKeyEntry rootPK = null;
  53. PrivateKey signPrivateKey = null;
  54. List<Certificate> chains = new ArrayList<>(5);
  55. if(root != null){
  56. rootPK = (KeyStore.PrivateKeyEntry) root.getCert().getEntry(root.getAlias(),
  57. new KeyStore.PasswordProtection(root.getPassword().toCharArray()));
  58. X509Certificate rootCert = (X509Certificate) rootPK.getCertificate();
  59. issuer = X500Name.getInstance(rootCert.getSubjectX500Principal().getEncoded());
  60. signPrivateKey = rootPK.getPrivateKey();
  61. Certificate [] rootChains = rootPK.getCertificateChain();
  62. for (int i=0;i<rootChains.length;i++){
  63. chains.add(rootChains[i]);
  64. }
  65. }
  66. KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
  67. kpg.initialize(2048);
  68. KeyPair keyPair = kpg.generateKeyPair();
  69. KeyStore keyStore = KeyStore.getInstance("JKS");
  70. keyStore.load(null, null);
  71. Date startDate = new Date(System.currentTimeMillis());
  72. Date expireDate = new Date(System.currentTimeMillis() + (86400000L * 365 * lifespan));
  73. String serial = UUID.randomUUID().toString().replaceAll("-","");
  74. BigInteger serialBig = str2BigInteger(serial);
  75. if(signPrivateKey == null){
  76. signPrivateKey = keyPair.getPrivate();
  77. }
  78. Certificate cert = generateV3(issuer, new X500Name(subject),serialBig, startDate,expireDate, keyPair.getPublic(),
  79. signPrivateKey
  80. , null);
  81. //用户证书要放在证书链的最前面
  82. chains.add(0,cert);
  83. keyStore.setKeyEntry("root", keyPair.getPrivate(), password.toCharArray(), chains.toArray(new Certificate[chains.size()]));
  84. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  85. keyStore.store(outputStream,password.toCharArray());
  86. GenerateCertificateInfo certificateInfo = new GenerateCertificateInfo();
  87. certificateInfo.setAlgorithm(certificateType.name());
  88. certificateInfo.setAlgorithmSignature(algorithmSignature);
  89. certificateInfo.setPassword(password);
  90. certificateInfo.setCertFileType("jks");
  91. certificateInfo.setSerial(serial);
  92. certificateInfo.setJks(outputStream.toByteArray());
  93. certificateInfo.setPfx(CertificateUtils.coverToPfx(certificateInfo.getJks(),certificateInfo.getPassword()));
  94. certificateInfo.setTermOfValidityStartTime(startDate);
  95. certificateInfo.setTermOfValidityEndTime(expireDate);
  96. return certificateInfo;
  97. }
  98. public Certificate generateV3(X500Name issuer, X500Name subject,
  99. BigInteger serial, Date startDate, Date expireDate,
  100. PublicKey publicKey, PrivateKey privKey, List<Extension> extensions) throws IOException, CertificateException, OperatorCreationException {
  101. X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
  102. issuer, serial, startDate, expireDate,
  103. subject, publicKey);
  104. ContentSigner sigGen = new JcaContentSignerBuilder(algorithmSignature).build(privKey);
  105. //privKey是CA的私钥,publicKey是待签名的公钥,那么生成的证书就是被CA签名的证书。
  106. if (extensions != null){
  107. for (Extension ext : extensions) {
  108. builder.addExtension(ext.getExtnId(), ext.isCritical(),ext.getExtnValue());
  109. }
  110. }
  111. X509CertificateHolder holder = builder.build(sigGen);
  112. CertificateFactory cf = CertificateFactory.getInstance("X.509");
  113. InputStream is1 = new ByteArrayInputStream(holder.toASN1Structure()
  114. .getEncoded());
  115. X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);
  116. is1.close();
  117. return theCert;
  118. }
  119. public static void main(String[] args) throws Exception {
  120. //
  121. KeyStore store = loadJKS("Ting111");
  122. BaseCertificateInfo baseCertificateInfo = new BaseCertificateInfo();
  123. baseCertificateInfo.setAlias("root");
  124. baseCertificateInfo.setCert(store);
  125. baseCertificateInfo.setPassword("123456");
  126. String x500Name = "CN=Ting222,OU=研发部,O=资源律动,L=BeiJing,ST=BeiJing,C=CN";
  127. GenerateCertificateInfo certificateInfo = GenerateRootCertificate.instance(x500Name,CertificateType.RSA).generateCertificate(baseCertificateInfo,"123456",10);
  128. FileUtils.writeByteArrayToFile(new File("C:\\Users\\Administrator\\Desktop\\tem\\cert\\Ting222.jks"), certificateInfo.getJks());
  129. }
  130. private static BigInteger str2BigInteger(String str){
  131. StringBuffer sb = new StringBuffer();
  132. //将字符串转换为字符数组
  133. char ch[] = str.toCharArray();
  134. for(int i = 0; i < ch.length; i++) {
  135. String hexString = Integer.toHexString(ch[i]);
  136. sb.append(hexString);
  137. }
  138. return new BigInteger(sb.toString());
  139. }
  140. private static String big2String(String str){
  141. String result = new String();
  142. char[] charArray = str.toString().toCharArray();
  143. for(int i = 0; i < charArray.length; i=i+2) {
  144. String st = ""+charArray[i]+""+charArray[i+1];
  145. char ch1 = (char)Integer.parseInt(st, 16);
  146. result = result + ch1;
  147. }
  148. return result;
  149. }
  150. public static KeyStore loadJKS(String name) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
  151. KeyStore store = KeyStore.getInstance("JKS");
  152. File file = new File(""+name+".jks");
  153. store.load(new FileInputStream(file), "123456".toCharArray());
  154. return store;
  155. }
  156. }

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

闽ICP备14008679号