当前位置:   article > 正文

国密算法篇_sm4 iv

sm4 iv

1.SM2 

        国密算法SM2是由国家密码管理局制定的一种非对称密码算法,包括SM2密钥交换、数字签名公钥加密(非对称加密,公钥加密,私钥解密)等三部分。它基于椭圆曲线(ECC)密码理论,具有较高的安全性效率(同RSA比较)

2.SM4

        SM4算法是对称加密算法,国标 GB/T 32907 对 SM4 对称加密算法进行了详细描述。SM4 算法密钥长度固定为128bit,加密解密采用相同的密钥,加解密速度较快,优于AES算法。

3.SM2和SM4加密使用示例

引入jar包

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.5</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
  1. public class SmEncryptUtil {
  2. private static final String IV = "0000000000000000";
  3. private static final String CHARSET_NAME = "UTF-8";
  4. static {
  5. Security.addProvider(new BouncyCastleProvider());
  6. }
  7. public static void main(String[] args) throws Exception {
  8. long startTime = System.currentTimeMillis();
  9. for (int i = 0; i < 10000; i++) {
  10. try {
  11. //测试参数
  12. String randomKey = "1234567812345678";
  13. String content = "hello world! 你好世界#~";
  14. //客户端请求
  15. String encryptKey = sm2Encrypt(randomKey, null);
  16. System.out.println("key sm2base64加密:" + encryptKey);
  17. String encryptContent = sm4Encrypt(randomKey, content, IV);
  18. System.out.println("content sm4base64加密:" + encryptContent);
  19. //服务端解析
  20. String decryptKey = sm2Decrypt(encryptKey, null);
  21. System.out.println("key sm2base64解密:" + decryptKey);
  22. String decryptContent = sm4Decrypt(decryptKey, encryptContent, IV);
  23. sm4Decrypt(decryptKey, encryptContent, IV);
  24. sm4Decrypt(decryptKey, encryptContent, IV);
  25. sm4Decrypt(decryptKey, encryptContent, IV);
  26. System.out.println(i + "content sm4base64解密:" + decryptContent);
  27. } catch (Exception ex) {
  28. System.out.println("加解密失败:" + ex.getMessage());
  29. break;
  30. }
  31. }
  32. long endTime = System.currentTimeMillis();
  33. System.out.println("总耗时ms:" + (endTime - startTime));
  34. }
  35. /**
  36. * sm2加密
  37. * 1.非对称加密 加密结果每次变化 C1C3C2模式
  38. * C1 生成随机数的计算出的椭圆曲线点
  39. * C3 SM3的摘要值
  40. * C2 密文数据
  41. * 2.base64格式:在ASCII码的可显示字符上选出一个子集,来表示所有的二进制流.
  42. * 避免软件和硬件对于某些二进制值不兼容的情况,将二进制数转换为6bit一组的base64编码格式(a~z,A~Z,0~9,/,+),可解决该问题
  43. *
  44. * @param sourceData 需要加密的明文
  45. * @param publicKey 加密使用的公钥 base64格式,为空使用默认公钥
  46. * @return 加密后密文,base64格式
  47. */
  48. public static String sm2Encrypt(String sourceData, String publicKey) {
  49. if (StringUtils.isBlank(publicKey)) {
  50. publicKey = ResponseBuilder.GATEWAY_PUBLIC_KEY_SM2;
  51. }
  52. SM2 sm2 = SmUtil.sm2(null, publicKey);
  53. return sm2.encryptBase64(sourceData, StandardCharsets.UTF_8, KeyType.PublicKey);
  54. }
  55. /**
  56. * sm2解密
  57. *
  58. * @param encryptData base64格式的密文
  59. * @param privateKey 解密使用的私钥,base64格式,为空使用默认私钥
  60. * @return 解密后的明文
  61. */
  62. public static String sm2Decrypt(String encryptData, String privateKey) {
  63. if (StringUtils.isBlank(privateKey)) {
  64. privateKey = ResponseBuilder.GATEWAY_PRIVATE_KEY_SM2;
  65. }
  66. SM2 sm2 = SmUtil.sm2(privateKey, null);
  67. return sm2.decryptStr(encryptData, KeyType.PrivateKey, StandardCharsets.UTF_8);
  68. }
  69. /**
  70. * sm4加密
  71. * 对称加密 加密结果不变 SM4/CBC/PKCS7Padding iv初始向量值为0
  72. *
  73. * @param randomKey 对称加密的密钥
  74. * @param sourceData 待加密的明文
  75. * @param iv 初始向量,为空则使用默认初始向量
  76. * @return 加密后的密文,base64格式
  77. */
  78. public static String sm4Encrypt(String randomKey, String sourceData, String iv) {
  79. try {
  80. if (StringUtils.isBlank(iv)) {
  81. iv = IV;
  82. }
  83. return Base64.encodeBase64String(sm4EncryptCBC(randomKey.getBytes(CHARSET_NAME),
  84. sourceData.getBytes(CHARSET_NAME), iv.getBytes(CHARSET_NAME)));
  85. } catch (Exception ex) {
  86. throw new BizException(BizRespCodeEnums.SENSITIVE_INFO_ENCRYPT_EXCEPTION.getCode(),
  87. BizRespCodeEnums.SENSITIVE_INFO_ENCRYPT_EXCEPTION.getMsg() + ex.getMessage());
  88. }
  89. }
  90. /**
  91. * sm4解密
  92. *
  93. * @param randomKey 对称加密的密钥
  94. * @param encryptData 待解密的密文
  95. * @param iv 初始向量,为空则使用默认初始向量
  96. * @return 解密后的明文
  97. */
  98. public static String sm4Decrypt(String randomKey, String encryptData, String iv) {
  99. try {
  100. if (StringUtils.isBlank(iv)) {
  101. iv = IV;
  102. }
  103. return new String(sm4DecryptCBC(randomKey.getBytes(CHARSET_NAME),
  104. Base64.decodeBase64(encryptData), iv.getBytes(CHARSET_NAME)));
  105. } catch (Exception ex) {
  106. throw new BizException(BizRespCodeEnums.SENSITIVE_INFO_DECRYPT_EXCEPTION.getCode(),
  107. BizRespCodeEnums.SENSITIVE_INFO_DECRYPT_EXCEPTION.getMsg() + ex.getMessage());
  108. }
  109. }
  110. private static byte[] sm4EncryptCBC(byte[] keyBytes, byte[] plain, byte[] iv) {
  111. if (keyBytes.length != 16) {
  112. throw new RuntimeException("err key length");
  113. }
  114. try {
  115. Key key = new SecretKeySpec(keyBytes, "SM4");
  116. Cipher out = Cipher.getInstance("SM4/CBC/PKCS7Padding", "BC");
  117. IvParameterSpec ivSpec = new IvParameterSpec(iv);
  118. out.init(Cipher.ENCRYPT_MODE, key, ivSpec);
  119. return out.doFinal(plain);
  120. } catch (Exception e) {
  121. throw new RuntimeException(e);
  122. }
  123. }
  124. private static byte[] sm4DecryptCBC(byte[] keyBytes, byte[] cipher, byte[] iv) {
  125. if (keyBytes.length != 16) {
  126. throw new RuntimeException("err key length");
  127. }
  128. try {
  129. Key key = new SecretKeySpec(keyBytes, "SM4");
  130. Cipher in = Cipher.getInstance("SM4/CBC/PKCS7Padding", "BC");
  131. IvParameterSpec ivSpec = new IvParameterSpec(iv);
  132. in.init(Cipher.DECRYPT_MODE, key, ivSpec);
  133. return in.doFinal(cipher);
  134. } catch (Exception e) {
  135. throw new RuntimeException(e);
  136. }
  137. }
  138. }

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

闽ICP备14008679号