目录

  • 流程说明:
  • DTO层
    • 生成证书密钥所需参数封装类
    • 最终密文封装类
  • controller层
  • service层
  • serviceImp层
  • 加密工具类
  • 测试
    • 发送生成证书请求
    • 发送生成密文请求
    • 发送解读密文请求

流程说明:

DTO层

生成证书密钥所需参数封装类


/*** 安全证书生成DTO** @author luce* @date 2021年08月30日 15:17*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CertificateCreate {/*** 国家代码*/private String countryCode;/*** 省份或州*/private String province;/*** 地区*/private String district;/*** 组织*/private String organization;/*** 通用名称*/private String commonName;/*** 证书存储路径*/private String certificateStoragePath;/*** 密钥存储路径*/private String secretKeyStoragePath;
}

最终密文封装类

/*** 密文文件** @author luce* @date 2021年08月31日 14:20*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Ciphertext {/*** 签文*/private String sigFile;/*** 加密密钥*/private String encryptionKey;/*** 加密密文*/private String encryptionFile;/*** 发送时间*/private String time;
}

controller层

@RestController
public class CipherController {@Autowiredprivate CipherService cipherService;/*** 生成证书和密钥文件** @param create 参数类* @return com.hb56.common.result.RestInfo<?>* @author luce* @date 2021/9/1 10:12*/@PostMapping("/cipher/certificatepath")public RestInfo<?> createCertificate(@RequestBody CertificateCreate create) throws Exception {return RestUtil.setSuccessMsg("生成成功!", cipherService.createCertificate(create));}/*** 读取证书** @return com.hb56.common.result.RestInfo<?>* @author luce* @date 2021/9/1 10:12*/@GetMapping("/cipher/certificate")public RestInfo<?> getCert() throws Exception {return RestUtil.setSuccessMsg("读取成功!", cipherService.getCert());}/*** 生成密文:path** @param str                报文* @param certFilePath       接收方证书文件路径* @param privateKeyFilePath 发送方密钥文件路径* @return com.hb56.common.result.RestInfo<?>* @author luce* @date 2021/9/1 10:17*/@PostMapping("/cipher/encryptedpath")public RestInfo<?> encrypted(String str, @RequestHeader("certFilePath") String certFilePath, @RequestHeader("privateKeyFilePath") String privateKeyFilePath) throws Exception {BCECPublicKey receivePublicKey = getPublicKeyByPath(certFilePath);BCECPrivateKey sendPrivateKey = getPrivateKeyByPath(privateKeyFilePath);return RestUtil.setSuccessMsg("生成成功!", cipherService.createCiphertext(str, receivePublicKey, sendPrivateKey));}/*** 生成密文* @author luce* @date 2021/9/3 10:23* @param map str:报文/cert:接收方证书* @return com.hb56.common.result.RestInfo<?>*/@PostMapping("/cipher/encrypted")public RestInfo<?> encrypted(@RequestBody Map<String, String> map) throws Exception {BCECPublicKey receivePublicKey = getPublicKey(map.get("cert"));BCECPrivateKey sendPrivateKey = cipherService.getPrivateKey();return RestUtil.setSuccessMsg("生成成功!", cipherService.createCiphertext(map.get("str"), receivePublicKey, sendPrivateKey));}/*** 解读密文:path** @param ciphertext         密文* @param certFilePath       发送方证书文件路径* @param privateKeyFilePath 接收方密钥文件路径* @return com.hb56.common.result.RestInfo<?>* @author luce* @date 2021/9/1 10:18*/@PostMapping("/cipher/unscrambledpath")public RestInfo<?> unscrambled(@RequestBody Ciphertext ciphertext, @RequestHeader("certFilePath") String certFilePath, @RequestHeader("privateKeyFilePath") String privateKeyFilePath) throws Exception {BCECPublicKey sendPublicKey = getPublicKeyByPath(certFilePath);BCECPrivateKey receivePrivateKey = getPrivateKeyByPath(privateKeyFilePath);return RestUtil.setSuccessMsg("读取成功!", cipherService.unscrambledCiphertext(ciphertext, sendPublicKey, receivePrivateKey));}/*** 解读密文** @param ciphertext 密文* @return com.hb56.common.result.RestInfo<?>* @author luce* @date 2021/9/1 10:18*/@PostMapping("/cipher/unscrambled")public RestInfo<?> unscrambled(@RequestBody Ciphertext ciphertext) throws Exception {BCECPublicKey sendPublicKey = getPublicKey(ciphertext.getCert());BCECPrivateKey receivePrivateKey = cipherService.getPrivateKey();return RestUtil.setSuccessMsg("读取成功!", cipherService.unscrambledCiphertext(ciphertext, sendPublicKey, receivePrivateKey));}}

service层

public interface CipherService {/*** 生成证书和密钥** @param create* @return 保存路径 -String* @author luce* @date 2021/9/1 10:00*/String createCertificate(CertificateCreate create) throws Exception;/*** 生成加密文件** @param str        报文* @param publicKey  接收方公钥* @param privateKey 发送方私钥* @return com.hb56.cipherclient.dto.Ciphertext* @author luce* @date 2021/9/3 8:45*/Ciphertext createCiphertext(String str, BCECPublicKey publicKey, BCECPrivateKey privateKey) throws Exception;/*** 解读密文* @param ciphertext 密文* @param publicKey  发送方公钥* @param privateKey 接收方私钥* @return 报文 -String* @author luce* @date 2021/9/3 9:53*/String unscrambledCiphertext(Ciphertext ciphertext, BCECPublicKey publicKey, BCECPrivateKey privateKey) throws Exception;/*** 读取证书** @return java.lang.String* @author luce* @date 2021/9/3 10:09*/Object getCert() throws Exception;/*** 读取私钥** @return org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey* @author luce* @date 2021/9/3 13:23*/BCECPrivateKey getPrivateKey() throws Exception;

serviceImp层

这层代码会比较多,不过都有注解

@Slf4j
@Service
public class CipherServiceImp implements CipherService {/*** 生成证书和密钥** @param create* @return 保存路径 -String* @author luce* @date 2021/8/31 14:56*/@Overridepublic String createCertificate(CertificateCreate create) throws Exception {//创建密钥KeyPair keyPair = SM2Util.generateKeyPair();Map<String, String> names = new HashMap<>();// 国家代码names.put(BCStyle.C.getId(), create.getCountryCode());// 省份或州names.put(BCStyle.ST.getId(), create.getProvince());// 地区names.put(BCStyle.L.getId(), create.getDistrict());// 组织names.put(BCStyle.O.getId(), create.getOrganization());// 通用名称names.put(BCStyle.CN.getId(), create.getCommonName());X500Name x500Name = CommonUtil.buildX500Name(names);SM2X509CertMaker sm2X509CertMaker = new SM2X509CertMaker(keyPair, 525600000, x500Name, new RandomSNAllocator());PKCS10CertificationRequest pkcs10CertificationRequest = CommonUtil.createCSR(x500Name, new SM2PublicKey((BCECPublicKey) keyPair.getPublic()), keyPair.getPrivate(), SIGN_ALGO_SM3WITHSM2);X509Certificate x509Certificate = sm2X509CertMaker.makeRootCACert(pkcs10CertificationRequest.getEncoded());String certStoragePath = "";String secretKeyStoragePath = "";if (StringUtils.hasText(create.getCertificateStoragePath())) {certStoragePath = create.getCertificateStoragePath() + "/safe/certificate.pem";} else {certStoragePath = acquireJarPath() + "safe/certificate.pem";}if (StringUtils.hasText(create.getSecretKeyStoragePath())) {secretKeyStoragePath = create.getCertificateStoragePath() + "/safe/private.key";} else {secretKeyStoragePath = acquireJarPath() + "safe/private.key";}//保存证书文件createCert(x509Certificate, certStoragePath);//保存密钥文件createKeyPair(keyPair, secretKeyStoragePath);return certStoragePath + " and " + secretKeyStoragePath;}/*** 生成密文文件** @param str        明文* @param publicKey  接收方公钥* @param privateKey 发送方私钥* @return com.hb56.cipherclient.dto.Ciphertext* @author luce* @date 2021/9/2 15:46*/@Overridepublic Ciphertext createCiphertext(String str, BCECPublicKey publicKey, BCECPrivateKey privateKey) throws Exception {Security.addProvider(new BouncyCastleProvider());String localDateTime = LocalDateTime.now().toString();//将报文转码 Base64String encodeStr = Base64Encoder.encode(str.getBytes(StandardCharsets.UTF_8));//将时间转码 Base64String encodeTime = Base64Encoder.encode(localDateTime.getBytes(StandardCharsets.UTF_8));//生成随机密钥byte[] key = SM4Util.generateKey();//加签:用发送方的私钥String sigFile = sign(encodeStr, privateKey, encodeTime);//加密:用随机 SM4keyString encodeCiphertext = encryptedDocument(key, encodeStr);//加密随机密钥:用接收方的公钥byte[] encryptsKey = SM2Util.encrypt(publicKey, key);String encodeKey = Base64Encoder.encode(encryptsKey);return new Ciphertext(sigFile, encodeKey, encodeCiphertext, localDateTime, null);}/*** 解读密文** @param ciphertext 密文* @param publicKey  发送方公钥* @param privateKey 接收方私钥* @return 报文 -String* @author luce* @date 2021/9/3 9:53*/@Overridepublic String unscrambledCiphertext(Ciphertext ciphertext, BCECPublicKey publicKey, BCECPrivateKey privateKey) throws Exception {Security.addProvider(new BouncyCastleProvider());//解密String encodeStr = decodeDocument(ciphertext, privateKey);System.out.println("解密后得到的报文:" + encodeStr);//在报文中加入发送时间一起验签String signStr = encodeStr + Base64Encoder.encode(ciphertext.getTime().getBytes(StandardCharsets.UTF_8));System.out.println("验签内容:" + signStr);//验签boolean result = SM2Util.verify(publicKey, signStr.getBytes(StandardCharsets.UTF_8), Base64Decoder.decode(ciphertext.getSignText()));if (!result) {throw new RuntimeException("验签失败!");}return new String(Base64Decoder.decode(encodeStr), StandardCharsets.UTF_8);}/*** 读取证书** @return java.lang.String* @author luce* @date 2021/9/3 10:09*/@Overridepublic String getCert() {File file = new File(acquireJarPath() + "safe/certificate.pem");long filelength = file.length();byte[] filecontent = new byte[(int) filelength];try {FileInputStream in = new FileInputStream(file);in.read(filecontent);in.close();} catch (IOException e) {e.printStackTrace();}return new String(filecontent);}/*** 读取私钥** @return org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey* @author luce* @date 2021/9/3 13:23*/@Overridepublic BCECPrivateKey getPrivateKey() throws Exception {String privateKey = FileUtil.readString(acquireJarPath() + "safe/private.key", CharsetUtil.CHARSET_UTF_8);return BCECUtil.convertPKCS8ToECPrivateKey(BCECUtil.convertECPrivateKeyPEMToPKCS8(privateKey));}/*** 获取jar包中的绝对路径* @author luce* @date 2021/9/7 15:24 * @return java.lang.String*/private String acquireJarPath() {String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getFile();try {path = java.net.URLDecoder.decode(path, "UTF-8");} catch (java.io.UnsupportedEncodingException ex) {log.error(ex.getLocalizedMessage());}java.io.File jarFile = new java.io.File(path);String jarFilepath = jarFile.getAbsolutePath();int end = jarFilepath.indexOf("target\\");String result = jarFilepath.substring(0, end + 7);return result;}
}

加密工具类

/*** 工具类** @author luce* @date 2021年09月01日 13:40*/
@Configuration
public class CipherTool {public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";public static final String END_CERT = "-----END CERTIFICATE-----";/*** 生成证书文件** @param x509Certificate 证书* @param certStoragePath 存储路径* @author luce* @date 2021/8/31 15:27*/public static void createCert(X509Certificate x509Certificate, String certStoragePath) throws CertificateEncodingException {FileUtil.del(certStoragePath);//在指定目录生成证书文件FileUtil.newFile(certStoragePath);//证书标题FileUtil.appendUtf8String(BEGIN_CERT, certStoragePath);//分割线FileUtil.appendUtf8String(System.getProperty("line.separator"), certStoragePath);//转Base64码的证书FileUtil.appendUtf8String(Base64Encoder.encode(x509Certificate.getEncoded()), certStoragePath);//分割线FileUtil.appendUtf8String(System.getProperty("line.separator"), certStoragePath);//尾文FileUtil.appendUtf8String(END_CERT, certStoragePath);}/*** 生成密钥文件** @param keyPair              密钥对* @param secretKeyStoragePath 存储路径* @author luce* @date 2021/8/31 15:30*/public static void createKeyPair(KeyPair keyPair, String secretKeyStoragePath) throws InvalidKeyException, IOException {FileUtil.del(secretKeyStoragePath);//生成私钥ECPrivateKeyParameters bcecPrivateKey = (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(keyPair.getPrivate());//生成公钥ECPublicKeyParameters bcecPublicKey = (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(keyPair.getPublic());//在指定目录生成密钥文件FileUtil.newFile(secretKeyStoragePath);//转PEM格式密钥FileUtil.appendUtf8String(BCECUtil.convertECPrivateKeyPKCS8ToPEM(BCECUtil.convertECPrivateKeyToPKCS8(bcecPrivateKey, bcecPublicKey)), secretKeyStoragePath);}/*** 从证书 Path 读取公钥** @param certFilePath 证书文件路径* @return org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey* @author luce* @date 2021/9/1 14:53*/public static BCECPublicKey getPublicKeyByPath(String certFilePath) throws Exception {X509Certificate sendCert = SM2CertUtil.getX509Certificate(certFilePath);return SM2CertUtil.getBCECPublicKey(sendCert);}/*** 读取公钥** @param receiveCert 证书* @return org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey* @author luce* @date 2021/9/1 14:53*/public static BCECPublicKey getPublicKey(String receiveCert) throws Exception {Security.addProvider(new BouncyCastleProvider());X509Certificate sendCert = SM2CertUtil.getX509Certificate(new ByteArrayInputStream(receiveCert.getBytes(StandardCharsets.UTF_8)));return SM2CertUtil.getBCECPublicKey(sendCert);}/*** 从 Path 读取私钥** @return org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey* @author luce* @date 2021/9/1 14:53*/public static BCECPrivateKey getPrivateKeyByPath(String privateKeyFilePath) throws Exception {String privateKey = FileUtil.readString(privateKeyFilePath, CharsetUtil.CHARSET_UTF_8);return BCECUtil.convertPKCS8ToECPrivateKey(BCECUtil.convertECPrivateKeyPEMToPKCS8(privateKey));}/*** 加签:用发送方的私钥进行加签** @param encodeStr      Base64码报文* @param sendPrivateKey 发送方私钥* @param encodeTime     发送时间* @return Base64格式签文 -String* @author luce* @date 2021/8/31 14:37*/public static String sign(String encodeStr, BCECPrivateKey sendPrivateKey, String encodeTime) throws CryptoException {String signStr = encodeStr + encodeTime;byte[] encodeSigFile = SM2Util.sign(sendPrivateKey, signStr.getBytes(StandardCharsets.UTF_8));return Base64Encoder.encode(encodeSigFile);}/*** 加密报文** @param key       SM4随机密钥* @param encodeStr Base64格式 报文* @return 密文 -String* @author luce* @date 2021/8/31 16:00*/public static String encryptedDocument(byte[] key, String encodeStr) throws Exception {byte[] ciphertext = SM4Util.encrypt_ECB_Padding(key, encodeStr.getBytes(StandardCharsets.UTF_8));return Base64Encoder.encode(ciphertext);}/*** 解密报文** @param ciphertext     加密文件* @param bcecPrivateKey 接收方密钥* @return 报文 -byte[]* @author luce* @date 2021/8/31 16:48*/public static String decodeDocument(Ciphertext ciphertext, BCECPrivateKey bcecPrivateKey) throws Exception {//解码密文byte[] decodeCiphertext = Base64Decoder.decode(ciphertext.getEncryptionFile());//解密随机密钥byte[] key = SM2Util.decrypt(SM2Engine.Mode.C1C3C2, bcecPrivateKey, Base64Decoder.decode(ciphertext.getEncryptionKey()));//解密密文byte[] encodeStr = SM4Util.decrypt_ECB_Padding(key, decodeCiphertext);return new String(encodeStr, StandardCharsets.UTF_8);}
}

测试

发送生成证书请求


结果

发送生成密文请求

发送解读密文请求

Java实现基于国密SM2、SM4生成证书密钥进行字串的加解密相关推荐

  1. vue前端国密SM2, SM4 算法实现

    vue前端国密SM2, SM4 算法实现 整体加密逻辑是,首先生成16位key值 用SM2 公钥加密该key值,后端用sm2私钥 解密出key值,然后采用sm4方法根据key值对返回值进行加密,前端采 ...

  2. Java中不依赖于第三方库使用OpenSSL生成的RSA公私钥进行数据加解密

    本文出处:http://blog.csdn.net/chaijunkun/article/details/7275632,转载请注明.由于本人不定期会整理相关博文,会对相应内容作出完善.因此强烈建议在 ...

  3. 国密(3)- 预主密钥/主密钥计算和Finished消息的加解密

    本文给的例子是ECC-SM3-SM4-CBC: GBT-38636-2020(传输层密码协议TLCP) 定义了pre-master key 和 master key: Pre- master Key ...

  4. 一文告诉你,国密SM2算法有多优秀

    可能很多人都想不到,密码技术是与核技术.航天技术并列的国家三大安全核心技术之一,在保障信息安全,建设行业网络安全环境,增强我国行业信息系统的"安全可控"能力等方面发挥着至为关键的作 ...

  5. 国密SM2,SM3,SM4的前后台(js和java)加解密写法

    目录 SM2加解密 js java SM3加密 js java sm3前后台(js/java)加密不一致原因 SM4加解密 js java 之前做一个项目的时候需要用到国密SM2,SM3,SM4的加解 ...

  6. php gmssl,支持国密SM2/SM3/SM4/SM9/ZUC/SSL的密码工具箱GmSSL

    GmSSL概述 GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法.SM2国密数字证书及基于SM2证书的SSL/TLS安全通信协议,支持国密硬件密码 ...

  7. 国密SM2电子签章JAVA实现

    本文默认所需的国密SM2证书已生成完成.基于BouncyCastle JAR包+itextpdf,利用itext提供的2个签名接口:ExternalDigest 及 ExternalSignature ...

  8. 基于mbedTLS算法库实现国密SM2签名和验签算法

    网上有大量的基于OpenSSL实现的国密算法库,比如著名的GmSSL,可以直接拿来用.我自己常用的是mbedTLS的算法库,比较小巧简单,在mbedTLS的大数算法的基础上实现了国密SM2的签名和验签 ...

  9. sm2 java 开源_SM2 国密算法被 Linux 内核社区接受

    原标题:SM2 国密算法被 Linux 内核社区接受 来自公众号: OSC开源社区 10 月 25 日,有开发者发文称,SM2 国密算法终于被 Linux 内核社区接受了.该作者表示,SM2 的补丁已 ...

最新文章

  1. 《jQuery权威指南》学习笔记——第二章
  2. 2021年北京高校数学建模校际联赛题目_B
  3. 【Servlet】Request/Response/Cookie/Session中常用方法
  4. KTV歌曲推荐-深入浅出协同过滤
  5. java jmenuitem重新渲染_的Java的JMenuItem添加邊框的第二菜單項
  6. 算法题12 数组中所有的逆序对
  7. ups容量计算和配置方法_UPS电路设计的空开、电缆及电池如何配置,计算依据是什么...
  8. 用sql语句也样创建oracle,Oracle中用sql语句创建数据库
  9. java游戏下载网址_手机java游戏下载网站
  10. 安徽省大数据比赛——数据可视化实战
  11. UniWebView3.8
  12. QQ机器人:群成员自我禁言管理【最新beta2版本】
  13. MAC 重置 MySql密码步骤
  14. codeforces1299C Water Balance
  15. SmartToast
  16. 多媒体技术计算机系统由组成,多媒体技术概述及多媒体计算机系统的组成
  17. 转载:Apache Ignite(一):简介以及和Coherence、Gemfire、Redis等的比较
  18. scipy csc csr到底是什么东西
  19. Adb文件及文件夹操作命令
  20. Go专家编程 timer、ticker

热门文章

  1. mw325r 服务器无响应),水星(MERCURY)MW325R路由器上不了网/连不上网怎么办?
  2. 基于32单片机的16通道ADC的数据采集
  3. mac mysql my.cnf 路径_my.cnf文件在macOS上的位置
  4. 写作副业怎么弄?写文章的副业应该怎么做?
  5. 浅谈Redis面试热点之工程架构篇[1]
  6. 心情不好 可以 看看冯巩的幽默语录
  7. 瀚高数据库日志挖掘方法
  8. [深度学习论文笔记]UNETR: Transformers for 3D Medical Image Segmentation
  9. CVPR2022 | 曾经火爆全网的算法!升级版来袭,支持卡通形象!
  10. 软件算法一些学习总结