• java加密,使用python解密 ,使用 pysm4 报 byte greater than 16的解决方法


    1,业务需要,对方需要用java进行参数加密,双方约定使用的加密方法是 SM4,对方给的key是32位,并且给出了加解密的java代码。

    1. import org.bouncycastle.jce.provider.BouncyCastleProvider;
    2. import java.security.Key;
    3. import java.security.NoSuchAlgorithmException;
    4. import java.security.NoSuchProviderException;
    5. import java.security.SecureRandom;
    6. import java.security.Security;
    7. import javax.crypto.Cipher;
    8. import javax.crypto.KeyGenerator;
    9. import javax.crypto.spec.SecretKeySpec;
    10. import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
    11. /**
    12. * sm4加密算法工具类
    13. */
    14. public class SM4Util {
    15. static {
    16. Security.addProvider(new BouncyCastleProvider());
    17. }
    18. private static final String ENCODING = "UTF-8";
    19. public static final String ALGORITHM_NAME = "SM4";
    20. // 加密算法/分组加密模式/分组填充方式
    21. // PKCS5Padding-以8个字节为一组进行分组加密
    22. // 定义分组加密模式使用:PKCS5Padding
    23. public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
    24. // 128-3216进制;256-6416进制
    25. public static final int DEFAULT_KEY_SIZE = 128;
    26. /**
    27. * 生成ECB暗号
    28. * @explain ECB模式(电子密码本模式:Electronic codebook)
    29. * @param algorithmName
    30. * 算法名称
    31. * @param mode
    32. * 模式
    33. * @param key
    34. * @return
    35. * @throws Exception
    36. */
    37. private static Cipher generateEcbCipher(String algorithmName, int mode, byte[] key) throws Exception {
    38. Cipher cipher = Cipher.getInstance(algorithmName, BouncyCastleProvider.PROVIDER_NAME);
    39. Key sm4Key = new SecretKeySpec(key, ALGORITHM_NAME);
    40. cipher.init(mode, sm4Key);
    41. return cipher;
    42. }
    43. /**
    44. * 自动生成密钥
    45. * @explain
    46. * @return
    47. * @throws NoSuchAlgorithmException
    48. * @throws NoSuchProviderException
    49. */
    50. public static String generateKey() throws Exception {
    51. return generateKey(DEFAULT_KEY_SIZE);
    52. }
    53. /**
    54. * @explain
    55. * @param keySize
    56. * @return
    57. * @throws Exception
    58. */
    59. public static String generateKey(int keySize) throws Exception {
    60. KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
    61. kg.init(keySize, new SecureRandom());
    62. return ByteUtils.toHexString(kg.generateKey().getEncoded());
    63. }
    64. /**
    65. * sm4加密
    66. * @explain 加密模式:ECB
    67. * 密文长度不固定,会随着被加密字符串长度的变化而变化
    68. * @param hexKey
    69. * 16进制密钥(忽略大小写)
    70. * @param paramStr
    71. * 待加密字符串
    72. * @return 返回16进制的加密字符串
    73. * @throws Exception
    74. */
    75. public static String encryptEcb(String hexKey, String paramStr) throws Exception {
    76. String cipherText = "";
    77. // 16进制字符串-->byte[]
    78. byte[] keyData = ByteUtils.fromHexString(hexKey);
    79. // String-->byte[]
    80. byte[] srcData = paramStr.getBytes(ENCODING);
    81. // 加密后的数组
    82. byte[] cipherArray = encryptEcbPadding(keyData, srcData);
    83. // byte[]-->hexString
    84. cipherText = ByteUtils.toHexString(cipherArray);
    85. return cipherText;
    86. }
    87. /**
    88. * 加密模式之Ecb
    89. * @explain
    90. * @param key
    91. * @param data
    92. * @return
    93. * @throws Exception
    94. */
    95. public static byte[] encryptEcbPadding(byte[] key, byte[] data) throws Exception {
    96. Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.ENCRYPT_MODE, key);
    97. return cipher.doFinal(data);
    98. }
    99. /**
    100. * sm4解密
    101. * @explain 解密模式:采用ECB
    102. * @param hexKey
    103. * 16进制密钥
    104. * @param cipherText
    105. * 16进制的加密字符串(忽略大小写)
    106. * @return 解密后的字符串
    107. * @throws Exception
    108. */
    109. public static String decryptEcb(String hexKey, String cipherText) throws Exception {
    110. // 用于接收解密后的字符串
    111. String decryptStr = "";
    112. // hexString-->byte[]
    113. byte[] keyData = ByteUtils.fromHexString(hexKey);
    114. // hexString-->byte[]
    115. byte[] cipherData = ByteUtils.fromHexString(cipherText);
    116. // 解密
    117. byte[] srcData = decryptEcbPadding(keyData, cipherData);
    118. // byte[]-->String
    119. decryptStr = new String(srcData, ENCODING);
    120. return decryptStr;
    121. }
    122. /**
    123. * 解密
    124. * @explain
    125. * @param key
    126. * @param cipherText
    127. * @return
    128. * @throws Exception
    129. */
    130. public static byte[] decryptEcbPadding(byte[] key, byte[] cipherText) throws Exception {
    131. Cipher cipher = generateEcbCipher(ALGORITHM_NAME_ECB_PADDING, Cipher.DECRYPT_MODE, key);
    132. return cipher.doFinal(cipherText);
    133. }
    134. public static void main(String[] args) {
    135. try {
    136. String generateKey = SM4Util.generateKey();
    137. System.out.println(generateKey);
    138. String json = "mate60 nb";
    139. // 自定义的3216进制密钥
    140. String key = "2c1f9b9388c5fc713c5ceab2af6f0f2d";
    141. String encrypted = SM4Util.encryptEcb(key, json);
    142. System.out.println(encrypted);
    143. json = SM4Util.decryptEcb(key, encrypted);
    144. System.out.println(json);
    145. } catch (Exception e) {
    146. e.printStackTrace();
    147. }
    148. }
    149. }

    2,这边用的后台程序python+flask只能用python去解密,先使用pysm4

    1. from pysm4 import encrypt_ecb, decrypt_ecb
    2. plain_text = '13800138000'
    3. key = '86C63*80C2806E*1F47B8*9DE501215*'
    4. cipher_text = encrypt_ecb(plain_text, key)
    5. plain_text == decrypt_ecb(cipher_text, key)

    报  Parameter key or iv:********* byte greater than 16的错误,应该是有个地方配置key的长度。

    3,但是对方也只能支持32位的方法,所以只能换方法,测试了一下,下面python方法可以完美支持32位,并且测试和java加密,python解密后也相同。

    python实现sm4,ecb模式加密_python sm4_pchaoda的博客-CSDN博客

  • 相关阅读:
    前端中常见概念对比
    HTML学习大纲
    微服务 高可用
    RedisInsight——redis的桌面UI工具使用实践
    30天工作量,推荐4个ai写作生成器工具,一键搞定!
    高等数学(第七版)同济大学 总习题三(前10题) 个人解答
    secureCRT打印机
    前端基础知识
    java基础10
    KubeCon热点报告:AIStation调度平台实现RoCE网络下大模型的高效稳定训练
  • 原文地址:https://blog.csdn.net/changdejie/article/details/132738990