远方蔚蓝
一刹那情真,相逢不如不见

文章数量 126

访问次数 199825

运行天数 1437

最近活跃 2024-10-04 23:36:48

进入后台管理系统

java使用SM2加解密及前端加密后端解密


1、实现前端加密,后端解密,前端需要引入js文件

  1. <script src="/business/libs/crypto-js.js"></script>
  2. // js调用方式
  3. var encryptData = sm2Encrypt('明文', '公钥', 0);

2、后端SM2生成公私钥及解密

  1. package wst.st.site.tools;
  2. import java.math.BigInteger;
  3. import java.nio.charset.StandardCharsets;
  4. import java.security.SecureRandom;
  5. import org.apache.commons.codec.binary.Base64;
  6. import org.bouncycastle.asn1.gm.GMNamedCurves;
  7. import org.bouncycastle.asn1.x9.X9ECParameters;
  8. import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
  9. import org.bouncycastle.crypto.engines.SM2Engine;
  10. import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
  11. import org.bouncycastle.crypto.params.ECDomainParameters;
  12. import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
  13. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
  14. import org.bouncycastle.crypto.params.ECPublicKeyParameters;
  15. import org.bouncycastle.crypto.params.ParametersWithRandom;
  16. import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
  17. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  18. import org.bouncycastle.jce.spec.ECParameterSpec;
  19. import org.bouncycastle.jce.spec.ECPrivateKeySpec;
  20. import org.bouncycastle.math.ec.ECPoint;
  21. import org.bouncycastle.util.encoders.Hex;
  22. import wst.st.site.constant.SiteWebConstant;
  23. /**
  24. * SM2工具类
  25. *
  26. * @author wst 2023年8月21日 上午10:32:33
  27. *
  28. */
  29. public class SM2Util {
  30. public static void main(String[] args) throws Exception {
  31. }
  32. /**
  33. * 生成密钥
  34. *
  35. * @author wst 2023年8月21日 上午10:37:37
  36. */
  37. public static void getPKs() {
  38. try {
  39. X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
  40. ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
  41. sm2ECParameters.getG(), sm2ECParameters.getN());
  42. ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
  43. keyPairGenerator
  44. .init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));
  45. AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
  46. // 私钥,16进制格式,自己保存
  47. BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
  48. String privateKeyHex = privatekey.toString(16);
  49. System.out.println("private Key :" + privateKeyHex);
  50. // 公钥,16进制格式,发给前端
  51. ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
  52. String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));
  53. System.out.println("public Key :" + publicKeyHex);
  54. } catch (Exception e) {
  55. e.printStackTrace();
  56. }
  57. }
  58. /**
  59. * 解密,前端登录信息解码及解码
  60. *
  61. * @author wst 2024年9月12日 下午1:41:47
  62. * @param cipherData
  63. * @return
  64. */
  65. public static String decrypt(String cipherData) {
  66. // 得到明文
  67. String data = null;
  68. try {
  69. byte[] cipherDataByte = Hex.decode(cipherData);
  70. // sm2私钥
  71. BigInteger privateKeyD = new BigInteger(SiteWebConstant.Common.Config.Sm2_Private_Key, 16);
  72. X9ECParameters sm2ECParameters1 = GMNamedCurves.getByName("sm2p256v1");
  73. ECDomainParameters domainParameters1 = new ECDomainParameters(sm2ECParameters1.getCurve(),
  74. sm2ECParameters1.getG(), sm2ECParameters1.getN());
  75. ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters1);
  76. // 用私钥解密
  77. SM2Engine sm2Engine = new SM2Engine();
  78. sm2Engine.init(false, privateKeyParameters);
  79. // 前端传入的密文解密后的processBlock得到Base64格式,记得解码
  80. // 如果只用下面给出的加密方法加密则不需要这个解码流程
  81. byte[] arrayOfBytes = Base64.decodeBase64(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));
  82. data = new String(arrayOfBytes);
  83. } catch (Exception e) {
  84. e.printStackTrace();
  85. }
  86. return data;
  87. }
  88. /**
  89. * 解密
  90. * @author wst 2024年9月12日 下午2:44:39
  91. * @param cipherData
  92. * @return
  93. */
  94. public static String sm2decrypt(String cipherData) {
  95. String result = null;
  96. try {
  97. // 加密算法
  98. String algorithm = "EC";
  99. // 私钥Hex,还原私钥
  100. BigInteger privateKeyD = new BigInteger(SiteWebConstant.Common.Config.Sm2_Private_Key, 16);
  101. // 使用标准名称创建EC参数生成的参数规范
  102. X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
  103. // 获取私钥的基本域参数
  104. ECParameterSpec ecParameterSpec = new ECParameterSpec(sm2ECParameters.getCurve(), sm2ECParameters.getG(),
  105. sm2ECParameters.getN());
  106. ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(privateKeyD, ecParameterSpec);
  107. // 获取私钥对象
  108. BCECPrivateKey bcecPrivateKey = new BCECPrivateKey(algorithm, ecPrivateKeySpec,
  109. BouncyCastleProvider.CONFIGURATION);
  110. byte[] cipherDataByte = Hex.decode(cipherData);
  111. ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
  112. ecParameterSpec.getG(), ecParameterSpec.getN());
  113. // 通过私钥值和私钥基本参数创建私钥参数对象
  114. ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
  115. ecDomainParameters);
  116. // 通过解密模式创建解密引擎并初始化
  117. SM2Engine sm2Engine = new SM2Engine();
  118. sm2Engine.init(false, ecPrivateKeyParameters);
  119. try {
  120. byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
  121. return new String(arrayOfBytes, StandardCharsets.UTF_8);
  122. } catch (Exception e) {
  123. }
  124. } catch (Exception e) {
  125. }
  126. return result;
  127. }
  128. /**
  129. * 加密
  130. * @author wst 2024年9月12日 下午2:42:21
  131. * @param data
  132. * @return
  133. */
  134. public static String encrypt(String data){
  135. // 获取一条SM2曲线参数
  136. X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
  137. // 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数N
  138. ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());
  139. //提取公钥点
  140. ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(SiteWebConstant.Common.Config.Sm2_Public_Key));
  141. // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
  142. ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);
  143. SM2Engine sm2Engine = new SM2Engine();
  144. sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
  145. byte[] arrayOfBytes = null;
  146. try {
  147. byte[] in = data.getBytes();
  148. arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
  149. } catch (Exception e) {
  150. e.printStackTrace();
  151. }
  152. return Hex.toHexString(arrayOfBytes);
  153. }
  154. }