You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

图片解密时抛出IllegalArgumentException异常求助

问题分析与解决方案

问题根源

你遇到的IllegalArgumentException: Input byte array has incorrect ending byte错误,本质是二进制文件(图片)被当作字符串处理导致数据损坏:

  • 图片属于二进制数据,并非所有字节都对应合法的UTF-8字符。你用getFileContent读取图片为String,再通过text.getBytes(UTF_8)转回字节数组时,部分原始字节会被替换为UTF-8的替换字符(�),导致数据永久损坏。
  • 损坏后的字节再经过AES加密、Base64编码,最终写入文件的内容已经和真正的加密结果不符,解密时Base64解码器自然无法识别错误的字节序列。

解决方案

核心是全程用字节数组处理二进制数据,避免在二进制和String之间来回转换。具体需要修改以下几点:

  1. 加密/解密方法改为直接接收和返回byte[],不再用String作为中间载体。
  2. 读取文件时用字节流读取原始二进制数据,写入文件时直接写入字节数组。
  3. 加密后依然用Base64编码(方便存储为文本格式),但要确保Base64的编码和解密流程基于完整的字节数据。

修改后的代码示例

1. 修正后的加密方法

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public static byte[] cat_encrypt(byte[] data, String pass) {
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        SecretKey key = new SecretKeySpec(messageDigest.digest(pass.getBytes(StandardCharsets.UTF_8)), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] encrypted = cipher.doFinal(data);
        return Base64.getEncoder().encode(encrypted);

    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
             BadPaddingException e) {
        throw new RuntimeException("Cannot encrypt", e);
    }
}

2. 修正后的解密方法

public static byte[] cat_decrypt(byte[] encryptedData, String pass) {
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        SecretKey key = new SecretKeySpec(messageDigest.digest(pass.getBytes(StandardCharsets.UTF_8)), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, key);

        byte[] decoded = Base64.getDecoder().decode(encryptedData);
        return cipher.doFinal(decoded);

    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException |
             BadPaddingException e) {
        try {
            sendError(e.getClass().getSimpleName());
        } catch (Exception sE) {
            e.printStackTrace();
        }
        throw new RuntimeException("Cannot decrypt", e);
    }
}

3. 加密图片的调用代码

import java.nio.file.Files;
import java.nio.file.Path;

// 读取原始图片字节
byte[] fileBytes = Files.readAllBytes(jf.getSelectedFile().toPath());
// 加密并得到Base64编码的字节数组
byte[] encryptedBytes = encrypt.cat_encrypt(fileBytes, pass);
// 写入文件(直接写Base64字节)
Files.write(jf.getSelectedFile().toPath(), encryptedBytes);

4. 解密图片的调用代码

// 读取加密后的Base64字节
byte[] encryptedBytes = Files.readAllBytes(jf.getSelectedFile().toPath());
// 解密得到原始图片字节
byte[] decryptedBytes = encrypt.cat_decrypt(encryptedBytes, pass);
// 写入解密后的图片文件
Files.write(Path.of("解密后的图片路径.jpg"), decryptedBytes);

额外优化建议

  • AES默认的ECB模式安全性较低,建议改为CBC或GCM模式,并添加随机初始化向量(IV),避免相同明文加密后得到相同密文的问题。
  • MD5生成的16字节密钥对应AES-128,若需要更强加密,可改用SHA-256生成32字节密钥对应AES-256(Java 8u161+默认支持)。

内容的提问来源于stack exchange,提问作者AlexM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 19:20:47