当前位置:   article > 正文

Java笔记-SM2(国密2)的调用及SM2、SM3、SM4使用场景_sm2加密

sm2加密

注意:本博文仅仅说明SM2的使用,应用场景等,不研究其算法。

SM2是非对称加密算法,对应应用层程序员来说,使用逻辑和RSA一样。

他的最主要的功能:

①非对称加密;

②签名和验签

对于应用层程序员来说,必须熟悉他的使用,以及他的应用领域,一般在写一个安全的应用时,如果单单使用SM2是不安全的,基本上SM2、SM3、SM4都会同时使用。一般都是用SM4对数据内容加密,使用SM3,对内容进行摘要,再使用SM2,对摘要进行签名。这个是数据发送端做的事情。接收端,先用SM2,对摘要进行验签,验签成功后,就做到了防抵赖,对发送过来的内容进行SM3摘要,看下生成的摘要和验签后的摘要是否一致,用于防篡改。

大体逻辑就是这样的。

另外SM4在加密解密需要相同的密钥,这个我们可以通过编写密钥交换模块实现生成相同的密钥。用于SM4对称加密。

对于应用层来说,说白了就是把RSA换成SM2、把MD5换成SM3,把AES换成SM4,这下大家明白了吧。

这里使用hutool这个库进行SM2的操作!

关于非对称加密的公钥和私钥,可以使用hutool生成,也可以使用openssl生成

openssl生成SM2公钥私钥:

  1. openssl ecparam -genkey -name SM2 -out priv.key
  2. openssl ec -in priv.key -pubout -out pub.key

生成的密钥如下:

  1. -----BEGIN PUBLIC KEY-----
  2. MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJ
  3. G9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==
  4. -----END PUBLIC KEY-----
  1. -----BEGIN EC PARAMETERS-----
  2. BggqgRzPVQGCLQ==
  3. -----END EC PARAMETERS-----
  4. -----BEGIN EC PRIVATE KEY-----
  5. MHcCAQEEIE8DQeWXexdeDsDh/e/SeZsT3SXFFxYTPvQrp2wO3Zc9oAoGCCqBHM9V
  6. AYItoUQDQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428
  7. SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==
  8. -----END EC PRIVATE KEY-----

关于非对称还要注意几点:

公钥是通过私钥产生的;

公钥加密,私钥解密是加密的过程

私钥加密,公钥解密是签名的过程;

源码如下:

  1. package cn.it1995;
  2. import cn.hutool.core.codec.Base64;
  3. import cn.hutool.core.util.HexUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import cn.hutool.crypto.SecureUtil;
  6. import cn.hutool.crypto.SmUtil;
  7. import cn.hutool.crypto.asymmetric.KeyType;
  8. import cn.hutool.crypto.asymmetric.SM2;
  9. import javax.swing.*;
  10. import java.security.KeyPair;
  11. public class Main {
  12. static String txt = "Hello World";
  13. /***
  14. * 随机生成的密钥对加密或解密
  15. */
  16. public static void test1(){
  17. SM2 sm2 = SmUtil.sm2();
  18. System.out.println("私钥:" + sm2.getPrivateKey());
  19. System.out.println("公钥:" + sm2.getPublicKey());
  20. String encryptStr = sm2.encryptBcd(txt, KeyType.PublicKey);
  21. String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  22. System.out.println("密文:" + encryptStr);
  23. System.out.println("明文:" + decryptStr);
  24. }
  25. /***
  26. * 自定义密钥对加密或解密
  27. */
  28. public static void test2(){
  29. KeyPair pair = SecureUtil.generateKeyPair("SM2");
  30. byte[] privateKey = pair.getPrivate().getEncoded();
  31. byte[] publicKey = pair.getPublic().getEncoded();
  32. System.out.println("私钥:");
  33. for(Integer i = 0; i < privateKey.length; i++){
  34. System.out.print(privateKey[i] + " ");
  35. }
  36. System.out.println();
  37. System.out.println("公钥:");
  38. for(Integer i = 0; i < publicKey.length; i++){
  39. System.out.print(publicKey[i] + " ");
  40. }
  41. System.out.println();
  42. SM2 sm2 = SmUtil.sm2(privateKey, publicKey);
  43. String encryptStr = sm2.encryptBcd(txt, KeyType.PublicKey);
  44. String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  45. System.out.println("密文:" + encryptStr);
  46. System.out.println("明文:" + decryptStr);
  47. }
  48. /***
  49. * 使用OpenSSL生成的SM2公钥和私钥加密或解密
  50. */
  51. public static void test3(){
  52. String privateKey = "MHcCAQEEIE8DQeWXexdeDsDh/e/SeZsT3SXFFxYTPvQrp2wO3Zc9oAoGCCqBHM9VAYItoUQDQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  53. String publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  54. SM2 sm2 = SmUtil.sm2(Base64.decode(privateKey), Base64.decode(publicKey));
  55. String encryptStr = sm2.encryptBcd(txt, KeyType.PublicKey);
  56. String decryptStr = StrUtil.utf8Str(sm2.decryptFromBcd(encryptStr, KeyType.PrivateKey));
  57. System.out.println("密文:" + encryptStr);
  58. System.out.println("明文:" + decryptStr);
  59. }
  60. /***
  61. * 随机密钥 签名和验签
  62. */
  63. public static void test4(){
  64. SM2 sm2 = SmUtil.sm2();
  65. String sign = sm2.signHex(HexUtil.encodeHexStr(txt));
  66. System.out.println("sign:" + sign);
  67. boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(txt), sign);
  68. System.out.println("verify:" + verify);
  69. }
  70. /***
  71. * 自定义密钥对 签名和验签
  72. */
  73. public static void test5(){
  74. KeyPair pair = SecureUtil.generateKeyPair("SM2");
  75. final SM2 sm2 = new SM2(pair.getPrivate(), pair.getPublic());
  76. byte[] sign = sm2.sign(txt.getBytes());
  77. System.out.println("sign");
  78. for(Integer i = 0; i < sign.length; i++){
  79. System.out.print(sign[i] + " ");
  80. }
  81. System.out.println();
  82. boolean verify = sm2.verify(txt.getBytes(), sign);
  83. System.out.print("verify:" + verify);
  84. }
  85. /**
  86. * OpenSSL密钥对 签名和验签
  87. */
  88. public static void test6(){
  89. String privateKey = "MHcCAQEEIE8DQeWXexdeDsDh/e/SeZsT3SXFFxYTPvQrp2wO3Zc9oAoGCCqBHM9VAYItoUQDQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  90. String publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  91. SM2 sm2 = SmUtil.sm2(Base64.decode(privateKey), Base64.decode(publicKey));
  92. byte[] sign = sm2.sign(txt.getBytes());
  93. System.out.println("sign");
  94. for(Integer i = 0; i < sign.length; i++){
  95. System.out.print(sign[i] + " ");
  96. }
  97. System.out.println();
  98. boolean verify = sm2.verify(txt.getBytes(), sign);
  99. System.out.print("verify:" + verify);
  100. }
  101. /***
  102. * 分开的:私钥签名,公钥验签
  103. * 密钥使用OpenSSL生成
  104. */
  105. public static void test7(){
  106. String privateKey = "MHcCAQEEIE8DQeWXexdeDsDh/e/SeZsT3SXFFxYTPvQrp2wO3Zc9oAoGCCqBHM9VAYItoUQDQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  107. String publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5SMhCzQHRkg5cjVY4NgnZbniyslJG9hsmcibn8Q/vpqUOV7jE428SuQ9qo/gH9US3oVoEC40xmmJ6yswZhG1GA==";
  108. SM2 sm2Sign = SmUtil.sm2(Base64.decode(privateKey), null);
  109. sm2Sign.usePlainEncoding();
  110. byte[] sign = sm2Sign.sign(txt.getBytes(), null);
  111. System.out.println("sign");
  112. for(Integer i = 0; i < sign.length; i++){
  113. System.out.print(sign[i] + " ");
  114. }
  115. System.out.println();
  116. SM2 sm2 = SmUtil.sm2(null, Base64.decode(publicKey));
  117. sm2.usePlainEncoding();
  118. boolean verify = sm2.verify(txt.getBytes(), sign);
  119. System.out.print("verify:" + verify);
  120. }
  121. public void test8(){
  122. }
  123. public static void main(String[] args) {
  124. test1();
  125. System.out.println("--------------------华丽的分割线------------------------");
  126. test2();
  127. System.out.println("--------------------华丽的分割线------------------------");
  128. test3();
  129. System.out.println("--------------------华丽的分割线------------------------");
  130. test4();
  131. System.out.println("--------------------华丽的分割线------------------------");
  132. test5();
  133. System.out.println("--------------------华丽的分割线------------------------");
  134. test6();
  135. System.out.println("--------------------华丽的分割线------------------------");
  136. test7();
  137. }
  138. }

程序运行如下:

  1. D:\java8\content\bin\java.exe -javaagent:D:\idea\content\lib\idea_rt.jar=50163:D:\idea\content\bin -Dfile.encoding=UTF-8 -classpath D:\java8\content\jre\lib\charsets.jar;D:\java8\content\jre\lib\deploy.jar;D:\java8\content\jre\lib\ext\access-bridge-64.jar;D:\java8\content\jre\lib\ext\cldrdata.jar;D:\java8\content\jre\lib\ext\dnsns.jar;D:\java8\content\jre\lib\ext\jaccess.jar;D:\java8\content\jre\lib\ext\jfxrt.jar;D:\java8\content\jre\lib\ext\localedata.jar;D:\java8\content\jre\lib\ext\nashorn.jar;D:\java8\content\jre\lib\ext\sunec.jar;D:\java8\content\jre\lib\ext\sunjce_provider.jar;D:\java8\content\jre\lib\ext\sunmscapi.jar;D:\java8\content\jre\lib\ext\sunpkcs11.jar;D:\java8\content\jre\lib\ext\zipfs.jar;D:\java8\content\jre\lib\javaws.jar;D:\java8\content\jre\lib\jce.jar;D:\java8\content\jre\lib\jfr.jar;D:\java8\content\jre\lib\jfxswt.jar;D:\java8\content\jre\lib\jsse.jar;D:\java8\content\jre\lib\management-agent.jar;D:\java8\content\jre\lib\plugin.jar;D:\java8\content\jre\lib\resources.jar;D:\java8\content\jre\lib\rt.jar;D:\IDEAProject\SM2Demo\target\classes;D:\newGenRepository\repository\cn\hutool\hutool-all\5.7.6\hutool-all-5.7.6.jar;D:\newGenRepository\repository\org\bouncycastle\bcprov-jdk15to18\1.68\bcprov-jdk15to18-1.68.jar cn.it1995.Main
  2. 私钥:EC Private Key [69:a6:2d:32:b5:e8:19:e0:69:a8:a1:f4:ad:2e:60:eb:9d:49:b2:2a]
  3. X: 8b9cd15f1f6cc97674c0f0dd1613890700805ecbfb7368eade20fa91565c1d49
  4. Y: 7ca52554e76f04471b69ef8b042080e596937d4d7fd3311c642d5b6a2b2c781d
  5. 公钥:EC Public Key [69:a6:2d:32:b5:e8:19:e0:69:a8:a1:f4:ad:2e:60:eb:9d:49:b2:2a]
  6. X: 8b9cd15f1f6cc97674c0f0dd1613890700805ecbfb7368eade20fa91565c1d49
  7. Y: 7ca52554e76f04471b69ef8b042080e596937d4d7fd3311c642d5b6a2b2c781d
  8. 密文:043AB278DCB9C19E64251B406DB855873AB65BD302CD321ACB509A12449559AD67C7EB8CA0FBE290D06BA9750D38EB70A69DC14C0ECF01803DA4971D471F0C3303D0C69A1001DACC048AECAA0F191196041DA367BBEB100F7C02506B57F51568F17A7C1024E90D30F7D20006
  9. 明文:Hello World
  10. --------------------华丽的分割线------------------------
  11. 私钥:
  12. 48 -127 -109 2 1 0 48 19 6 7 42 -122 72 -50 61 2 1 6 8 42 -127 28 -49 85 1 -126 45 4 121 48 119 2 1 1 4 32 -88 107 3 126 93 -49 -79 -127 52 60 55 125 -50 38 78 68 -34 81 -84 -97 -82 69 0 3 -72 40 23 15 -41 112 -96 -97 -96 10 6 8 42 -127 28 -49 85 1 -126 45 -95 68 3 66 0 4 -35 21 15 107 92 -61 82 34 -25 34 24 42 122 -18 88 117 -49 -20 50 -92 -10 -99 77 46 -80 -20 -121 99 13 -114 54 -105 34 -1 -72 77 7 -87 -112 84 -91 64 71 91 40 -78 -126 119 10 -113 97 6 94 -47 12 -8 37 -11 -61 81 96 14 -51 -97
  13. 公钥:
  14. 48 89 48 19 6 7 42 -122 72 -50 61 2 1 6 8 42 -127 28 -49 85 1 -126 45 3 66 0 4 -35 21 15 107 92 -61 82 34 -25 34 24 42 122 -18 88 117 -49 -20 50 -92 -10 -99 77 46 -80 -20 -121 99 13 -114 54 -105 34 -1 -72 77 7 -87 -112 84 -91 64 71 91 40 -78 -126 119 10 -113 97 6 94 -47 12 -8 37 -11 -61 81 96 14 -51 -97
  15. 密文:049625A78A0D48E6C41F55A097E6039C84EE6EF402477A2ACB9FF3D319913731750F3ADAB9186190F0B9EDFBC91B66867A323FFE1C01B5F543ED52D27CFAFBE6E9D37FF3B698D4931196D8D68E81A70726DA67F4C4E59F0007AAA06459704DB40DF8E21E81A9970D35EFD0ED
  16. 明文:Hello World
  17. --------------------华丽的分割线------------------------
  18. 密文:04D10EE79A33A1A8CE7407544908732F039C244C6FD04D59D5586B701455432209FA93B57142410E69B2BF1B8C8F8176FBDC8AB92FE07BD8C67F3FB121E10E58F1D66AD53E8FDB9408E9CF86E0B463F2968A166BF8F53D8EBEF97E37A325BD49C5F4D6A2AD06851F7DC7E158
  19. 明文:Hello World
  20. --------------------华丽的分割线------------------------
  21. sign:3044022025d780da4e9e9756966a5f9bfcfac402bd23fed5ef8e7430605aa409fbddf5ae0220230d911af4bfac036641968fffb7e4fabb17b7e40e85f506bffb8b67932139bf
  22. verify:true
  23. --------------------华丽的分割线------------------------
  24. sign
  25. 48 70 2 33 0 -69 -7 -33 44 122 -10 73 60 14 7 -64 58 77 -57 6 -17 16 16 -78 6 114 -80 -100 -118 102 -70 -38 -90 26 -74 -118 91 2 33 0 -127 119 -13 -46 75 27 -52 79 98 42 -68 -44 35 7 -28 -128 -65 84 74 120 -116 -65 -97 77 32 -21 -7 23 -17 59 -84 124
  26. verify:true--------------------华丽的分割线------------------------
  27. sign
  28. 48 68 2 32 42 -28 -26 -47 -126 -12 81 -47 68 -80 62 106 -114 -96 -121 -117 -36 -76 77 -35 -106 4 15 103 67 28 -40 -11 -61 26 -96 31 2 32 87 97 -38 20 -111 33 -73 87 100 31 -123 71 110 -118 4 -32 -67 -35 -52 50 -66 -100 99 -83 4 -39 -64 -73 -97 -31 71 67
  29. verify:true--------------------华丽的分割线------------------------
  30. sign
  31. -100 16 -120 93 -98 -23 -87 8 112 75 107 -14 -103 19 -38 -76 115 -86 -128 -120 -95 -20 97 64 123 11 125 -114 18 21 -48 6 87 15 -74 -23 -89 -3 -87 81 -35 0 7 -123 -71 106 8 -31 -96 -12 -49 -70 120 115 -116 47 114 30 6 75 -120 78 117 78
  32. verify:true
  33. Process finished with exit code 0

程序打包下载地址:

https://github.com/fengfanchen/Java/tree/master/SM2Demo

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

闽ICP备14008679号