当前位置:   article > 正文

国密SM2: 加解密实现 java代码完整示例_java sm2解密

java sm2解密

国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证书。

基于ECC椭圆曲线算法的SM2算法,则普遍采用256位密钥长度,它的单位安全强度相对较高,在工程应用中比较难以实现,破译或求解难度基本上是指数级的。因此,SM2算法可以用较少的计算能力提供比RSA算法更高的安全强度,而所需的密钥长度却远比RSA算法低。 

pom依赖引入 :
  1. <dependency>
  2. <groupId>org.bouncycastle</groupId>
  3. <artifactId>bcprov-jdk15to18</artifactId>
  4. <version>1.68</version>
  5. </dependency>
 具体Java代码SM2算法加解密实现Demo:
  1. package com.xinan.security.sm2;
  2. import org.bouncycastle.asn1.gm.GMNamedCurves;
  3. import org.bouncycastle.asn1.x9.X9ECParameters;
  4. import org.bouncycastle.crypto.engines.SM2Engine;
  5. import org.bouncycastle.crypto.params.ECDomainParameters;
  6. import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
  7. import org.bouncycastle.crypto.params.ECPublicKeyParameters;
  8. import org.bouncycastle.crypto.params.ParametersWithRandom;
  9. import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
  10. import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
  11. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  12. import org.bouncycastle.jce.spec.ECParameterSpec;
  13. import org.bouncycastle.jce.spec.ECPrivateKeySpec;
  14. import org.bouncycastle.jce.spec.ECPublicKeySpec;
  15. import org.bouncycastle.util.encoders.Hex;
  16. import java.math.BigInteger;
  17. import java.security.*;
  18. import java.security.spec.ECGenParameterSpec;
  19. /**
  20. *SM2算法工具类
  21. * @version 1.0
  22. */
  23. public class SM2Utils {
  24. public static KeyPair createECKeyPair() {
  25. final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
  26. // 获取一个椭圆曲线类型的密钥对生成器
  27. final KeyPairGenerator kpg;
  28. try {
  29. kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
  30. kpg.initialize(sm2Spec, new SecureRandom());
  31. return kpg.generateKeyPair();
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. return null;
  35. }
  36. }
  37. public static String encrypt(String publicKeyHex, String data) {
  38. return encrypt(getECPublicKeyByPublicKeyHex(publicKeyHex), data, 1);
  39. }
  40. public static String encrypt(BCECPublicKey publicKey, String data, int modeType) {
  41. //加密模式
  42. SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
  43. if (modeType != 1) {
  44. mode = SM2Engine.Mode.C1C2C3;
  45. }
  46. ECParameterSpec ecParameterSpec = publicKey.getParameters();
  47. ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
  48. ecParameterSpec.getG(), ecParameterSpec.getN());
  49. ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
  50. SM2Engine sm2Engine = new SM2Engine(mode);
  51. sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
  52. byte[] arrayOfBytes = null;
  53. try {
  54. byte[] in = data.getBytes("utf-8");
  55. arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
  56. } catch (Exception e) {
  57. System.out.println("SM2加密时出现异常:" + e.getMessage());
  58. e.printStackTrace();
  59. }
  60. return Hex.toHexString(arrayOfBytes);
  61. }
  62. public static String decrypt(String privateKeyHex, String cipherData) {
  63. return decrypt(getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), cipherData, 1);
  64. }
  65. public static String decrypt(BCECPrivateKey privateKey, String cipherData, int modeType) {
  66. //解密模式
  67. SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
  68. if (modeType != 1) {
  69. mode = SM2Engine.Mode.C1C2C3;
  70. }
  71. byte[] cipherDataByte = Hex.decode(cipherData);
  72. ECParameterSpec ecParameterSpec = privateKey.getParameters();
  73. ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
  74. ecParameterSpec.getG(), ecParameterSpec.getN());
  75. ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
  76. ecDomainParameters);
  77. SM2Engine sm2Engine = new SM2Engine(mode);
  78. sm2Engine.init(false, ecPrivateKeyParameters);
  79. String result = null;
  80. try {
  81. byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
  82. result = new String(arrayOfBytes, "utf-8");
  83. } catch (Exception e) {
  84. System.out.println("SM2解密时出现异常" + e.getMessage());
  85. }
  86. return result;
  87. }
  88. private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
  89. private static ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
  90. public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
  91. if (pubKeyHex.length() > 128) {
  92. pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
  93. }
  94. String stringX = pubKeyHex.substring(0, 64);
  95. String stringY = pubKeyHex.substring(stringX.length());
  96. BigInteger x = new BigInteger(stringX, 16);
  97. BigInteger y = new BigInteger(stringY, 16);
  98. ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
  99. return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
  100. }
  101. public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
  102. BigInteger d = new BigInteger(privateKeyHex, 16);
  103. ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
  104. return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
  105. }
  106. public static void main(String[] args) {
  107. String publicKeyHex = null;
  108. String privateKeyHex = null;
  109. KeyPair keyPair = createECKeyPair();
  110. PublicKey publicKey = keyPair.getPublic();
  111. if (publicKey instanceof BCECPublicKey) {
  112. //获取65字节非压缩缩的十六进制公钥串(0x04)
  113. publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
  114. System.out.println("SM2公钥:" + publicKeyHex);
  115. }
  116. PrivateKey privateKey = keyPair.getPrivate();
  117. if (privateKey instanceof BCECPrivateKey) {
  118. //获取32字节十六进制私钥串
  119. privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
  120. System.out.println("SM2私钥:" + privateKeyHex);
  121. }
  122. /**
  123. * 公钥加密
  124. */
  125. String data = "=========需要加密的数据=========";
  126. //将十六进制公钥串转换为 BCECPublicKey 公钥对象
  127. String encryptData = encrypt(publicKeyHex, data);
  128. System.out.println("加密结果:" + encryptData);
  129. /**
  130. * 私钥解密
  131. */
  132. //将十六进制私钥串转换为 BCECPrivateKey 私钥对象
  133. data = decrypt(privateKeyHex, encryptData);
  134. System.out.println("解密结果:" + data);
  135. }
  136. }

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

闽ICP备14008679号