AES 加密中文,加密前不是乱码,加密后密文解密中文乱码

该博客探讨了使用AES加密中文字符串时遇到的问题,主要涉及AES的CBC模式、NoPadding填充以及Base64编码。在加密和解密过程中,由于编码处理不当导致解密后的中文出现乱码。示例代码提供了加密和解密的方法,但存在潜在的编码错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import com.qiniu.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.spec.AlgorithmParameterSpec;

/**

  • AES 是一种可逆加密算法,对用户的敏感信息加密处理
  • 对原始数据进行AES加密后,在进行Base64编码转化;
  • @author
  • @time 2017/11/27 15:54
  • 填充:zeropadding 128位
  • 模式:CBC
  • 密码:Kbj.543Lbwb5kNbP
  • 偏移量:B*L032Ykls9-g858

/ public class AesCBCUtil { //私钥 AES固定格式为128/192/256 bits.即:16/24/32bytes public static final String APP_LOGIN_IN_KEY = "Kbj.543Lbwb5kNbP"; //初始化向量参数,AES 为16bytes public static final String GIV = "BL032Ykls9-g858";

/**
 * CBC
 *
 * @param data
 * @param key
 * @return
 * @throws Exception
 */
public static String encrypt(String data, String key) {
复制代码

// Logger.getInstace().i("[Data-Original]", data); try { Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); int blockSize = cipher.getBlockSize();

        byte[] dataBytes = data.getBytes();
    
### AES加密密钥乱码解决方案 AES加密过程中出现乱码通常是由以下几个原因引起的: #### 1. 编码不一致 在不同平台之间传输数据时,编码方式可能不统一。例如,在Windows环境下使用的默认编码可能是GBK,而在Linux环境下则通常是UTF-8。如果未指定字符集,则可能导致中文或其他特殊字符被错误解析为不可识别的符号。 解决办法是在加密解密的过程中显式指定字符集。例如,可以使用`StandardCharsets.UTF_8`来确保一致性[^2]。 ```java String plaintext = "这是测试字符串"; byte[] encryptedBytes = encrypt(plaintext.getBytes(StandardCharsets.UTF_8), key); ``` --- #### 2. 加密模式与填充方式的选择不当 某些加密模式(如CBC)需要配合特定的填充方式才能正确工作。如果没有设置合适的填充方式或者选择了无填充的方式(如NoPadding),可能会导致部分数据无法正确填充而产生乱码。 推荐使用带有PKCS5Padding或PKCS7Padding的加密模式,比如`AES/CBC/PKCS5Padding`[^3]。 ```java Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); ``` --- #### 3. Base64编解码问题 Base64是一种常用的二进制到文本的转换算法,用于将字节数组表示为可打印字符形式。然而,不同的库实现可能存在细微差异,尤其是在处理换行符等方面。因此,建议始终采用标准的Base64工具类来进行操作。 以下是基于Java的标准Base64编码示例[^4]: ```java import java.util.Base64; public static String encodeToBase64(byte[] data) { return Base64.getEncoder().encodeToString(data); } public static byte[] decodeFromBase64(String base64Data) { return Base64.getDecoder().decode(base64Data); } ``` --- #### 4. 密钥长度不足或格式错误 AES支持多种密钥长度(128位、192位、256位)。如果提供的密钥不符合这些规格,将会引发异常甚至造成乱码现象。此外,密钥应由随机数生成器创建并存储为字节数组而非简单字符串。 下面是一个安全生成AES密钥的方法: ```java KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); // 设置密钥长度为256位 SecretKey secretKey = keyGen.generateKey(); byte[] rawKey = secretKey.getEncoded(); // 获取原始密钥字节 ``` --- #### 综合案例分析 假设存在如下场景:一段程序在Windows上运行正常但在Linux环境中却出现了乱码。经过排查发现是因为没有明确指定位移向量IV以及忽略了跨平台间的字符集兼容性问题。最终通过调整参数解决了该难题[^1]。 完整代码片段展示如下: ```java import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; public class AESEncryptionExample { private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; // 使用带填充的CBC模式 private static final String KEY = "0123456789abcdef0123456789abcdef"; // 16字节密钥 (128-bit) private static final String IV = "fedcba9876543210"; // 初始化向量 (同样需满足16字节) public static void main(String[] args) throws Exception { String originalText = "你好世界"; SecretKeySpec secretKeySpec = new SecretKeySpec(KEY.getBytes(StandardCharsets.UTF_8), "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes(StandardCharsets.UTF_8)); // 加密过程 Cipher cipherEncrypt = Cipher.getInstance(ALGORITHM); cipherEncrypt.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] encryptedBytes = cipherEncrypt.doFinal(originalText.getBytes(StandardCharsets.UTF_8)); String encodedEncryptedText = Base64.getEncoder().encodeToString(encryptedBytes); System.out.println("加密后: " + encodedEncryptedText); // 解密过程 Cipher cipherDecrypt = Cipher.getInstance(ALGORITHM); cipherDecrypt.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); byte[] decodedBytes = Base64.getDecoder().decode(encodedEncryptedText); byte[] decryptedBytes = cipherDecrypt.doFinal(decodedBytes); System.out.println("解密后: " + new String(decryptedBytes, StandardCharsets.UTF_8)); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值