记AES加密在linux系统每次都不一样的问题

蔚落 2023-07-15 13:04 61阅读 0赞

记AES加密在linux系统每次都不一样的问题

在项目中通常会用到AES的加密方法,具体代码如下

  1. package com.mt.demo.client.utils;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  4. import org.springframework.stereotype.Component;
  5. import javax.crypto.*;
  6. import javax.crypto.spec.SecretKeySpec;
  7. import java.io.UnsupportedEncodingException;
  8. import java.nio.charset.StandardCharsets;
  9. import java.security.*;
  10. import java.util.Base64;
  11. /**
  12. * AESUtils
  13. *
  14. * @author mt.luo
  15. * @description: AES加密
  16. */
  17. @Slf4j
  18. @Component
  19. public class AESUtils {
  20. private final String aesSeed = "ada46ab5da824b96a18409c49dc91dc2";
  21. private final String algorithm = "SHA-256";
  22. private final String AES = "AES";
  23. private final String cipher = "AES/ECB/PKCS7Padding";
  24. private final String provider = "BC";
  25. /**
  26. * convert to byte[]
  27. *
  28. * @param key key
  29. * @return byte[]
  30. * @throws NoSuchAlgorithmException
  31. */
  32. private byte[] toHash256(String key) throws NoSuchAlgorithmException {
  33. MessageDigest messageDigest = MessageDigest.getInstance(this.algorithm);
  34. messageDigest.update(key.getBytes());
  35. return messageDigest.digest();
  36. }
  37. /**
  38. * parseHexStrToByte
  39. *
  40. * @param hexStr hexStr
  41. * @return byte
  42. */
  43. private byte[] parseHexStrToByte(String hexStr) {
  44. if (hexStr.length() < 1) {
  45. return null;
  46. }
  47. byte[] result = new byte[hexStr.length() / 2];
  48. for (int i = 0; i < hexStr.length() / 2; i++) {
  49. int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
  50. int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
  51. result[i] = (byte) (high * 16 + low);
  52. }
  53. return result;
  54. }
  55. /**
  56. * parseByteToHexStr
  57. *
  58. * @param bytes bytes
  59. * @return String
  60. */
  61. private String parseByteToHexStr(byte[] bytes) {
  62. StringBuilder stringBuilder = new StringBuilder();
  63. for (byte b : bytes) {
  64. String hex = Integer.toHexString(b & 0xFF);
  65. if (hex.length() == 1) {
  66. hex = '0' + hex;
  67. }
  68. stringBuilder.append(hex.toUpperCase());
  69. }
  70. return stringBuilder.toString();
  71. }
  72. /**
  73. * 获取密钥
  74. *
  75. * @param seed seed
  76. * @return SecretKeySpec
  77. * @throws NoSuchAlgorithmException NoSuchAlgorithmException
  78. */
  79. private SecretKeySpec getSecretKeySpec(String seed) throws NoSuchAlgorithmException {
  80. KeyGenerator keyGenerator = KeyGenerator.getInstance(this.AES);
  81. SecureRandom secureRandom = new SecureRandom(this.toHash256(seed));
  82. keyGenerator.init(256, secureRandom);
  83. SecretKey secretKey = keyGenerator.generateKey();
  84. byte[] encode = secretKey.getEncoded();
  85. SecretKeySpec secretKeySpec = new SecretKeySpec(encode, this.AES);
  86. Security.addProvider(new BouncyCastleProvider());
  87. return secretKeySpec;
  88. }
  89. /**
  90. * 加密
  91. *
  92. * @param data data
  93. * @return String
  94. * @throws NoSuchAlgorithmException
  95. * @throws NoSuchProviderException
  96. * @throws NoSuchPaddingException
  97. * @throws UnsupportedEncodingException
  98. * @throws BadPaddingException
  99. * @throws IllegalBlockSizeException
  100. */
  101. public String encrypt(String data) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException,
  102. UnsupportedEncodingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
  103. SecretKeySpec secretKeySpec = this.getSecretKeySpec(this.aesSeed);
  104. Cipher cipher = Cipher.getInstance(this.cipher, this.provider);
  105. cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
  106. return this.parseByteToHexStr(Base64.getEncoder().encode(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8.name()))));
  107. }
  108. }

然后这样使用在windows系统的时候没有问题,而将程序部署到Linux则发现每次加密之后获取的加密字符串都不同,也无法解密,重写获取密钥部分的代码

  1. /**
  2. * 获取密钥
  3. *
  4. * @param seed seed
  5. * @return SecretKeySpec
  6. * @throws NoSuchAlgorithmException NoSuchAlgorithmException
  7. */
  8. private SecretKeySpec getSecretKeySpec(String seed) throws NoSuchAlgorithmException {
  9. KeyGenerator keyGenerator = KeyGenerator.getInstance(this.AES);
  10. SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
  11. secureRandom.setSeed(this.toHash256(seed));
  12. keyGenerator.init(256, secureRandom);
  13. SecretKey secretKey = keyGenerator.generateKey();
  14. byte[] encode = secretKey.getEncoded();
  15. SecretKeySpec secretKeySpec = new SecretKeySpec(encode, this.AES);
  16. Security.addProvider(new BouncyCastleProvider());
  17. return secretKeySpec;
  18. }

主要原因是SecureRandom 实现完全隨操作系统本身的内部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 linux 系统上则不同。

欢迎关注微信交流
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,61人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AES加密

    一、AES是什么 AES高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府

    相关 AES加密

     AES技术是一种对称的分组加密技术,使用128位分组加密数据,提供比WEP/TKIPS的RC4算法更高的加密强度。AES的加密码表和解密码表是分开的,并且支持子密钥加密,这种