AES/CBC模式Java加密代码运行报错:数组下标越界异常
问题排查与解决:AES加解密代码的数组越界异常
异常原因
抛出ArrayIndexOutOfBoundsException: Index out of bounds for length 0的直接原因是:运行代码时没有传入足够的命令行参数。
你的main方法直接通过args[0]、args[1]、args[2]读取密钥、IV和待加密数据,但如果运行时没有传参数或参数数量不足(少于3个),args数组的长度就会小于3,访问超出数组长度的索引就会触发这个异常。
直接解决步骤
1. 运行时传入正确参数
编译代码后,在命令行按以下格式运行:
java CryptAES <AES密钥> <CBC模式IV> <待加密数据>
示例:
java CryptAES "1234567890abcdef" "abcdef1234567890" "Hello AES"
注意:AES密钥必须是16位(128位)、24位(192位)或32位(256位);CBC模式的IV必须是16位(和AES块大小一致)。
2. 给代码增加参数校验
在main方法开头添加参数检查逻辑,避免无参数时崩溃,同时给出友好提示:
public static void main(String[] args) { if (args.length < 3) { System.err.println("用法: java CryptAES <AES密钥> <CBC模式IV> <待加密数据>"); System.err.println("注意: 密钥长度必须是16/24/32位,IV长度必须是16位"); System.exit(1); } // 原有的代码逻辑... }
额外优化:修复代码中的其他潜在问题
原代码还有几个容易导致异常或跨平台问题的点,建议一并修复:
1. 强制指定字符编码
getBytes()方法默认使用系统默认编码,跨平台可能出现乱码,统一指定UTF-8编码:
需要先导入java.nio.charset.StandardCharsets,然后把所有getBytes()替换为getBytes(StandardCharsets.UTF_8)。
2. 校验密钥和IV的长度
AES密钥和CBC模式IV有严格的长度要求,添加校验避免后续加密/解密时抛出异常:
在process方法开头添加:
byte[] keyBytes = skey.getBytes(StandardCharsets.UTF_8); if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) { throw new IllegalArgumentException("AES密钥长度必须是16/24/32位"); } byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8); if (ivBytes.length != 16) { throw new IllegalArgumentException("CBC模式IV长度必须是16位"); }
3. 优化异常处理
原代码的异常处理可以更清晰,避免直接抛出RuntimeException时丢失细节。
修改后的完整代码
import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.IvParameterSpec; import java.nio.charset.StandardCharsets; class CryptAES { static final String cipher_type = "AES/CBC/PKCS5Padding"; public static void main(String[] args) { if (args.length < 3) { System.err.println("用法: java CryptAES <AES密钥> <CBC模式IV> <待加密数据>"); System.err.println("注意: 密钥长度必须是16/24/32位,IV长度必须是16位"); System.exit(1); } String key = args[0]; String iv = args[1]; String data = args[2]; try { byte[] enc = encode(key, iv, data.getBytes(StandardCharsets.UTF_8)); byte[] dec = decode(key, iv, enc); for (int i = 0; i < enc.length; i++) { System.out.printf("%02x", enc[i]); } System.out.println(); System.out.println(new String(dec, StandardCharsets.UTF_8)); } catch (IllegalArgumentException e) { System.err.println("参数错误: " + e.getMessage()); } catch (Exception e) { System.err.println("加解密失败: " + e.getMessage()); } } public static byte[] encode(String skey, String iv, byte[] data) { return process(Cipher.ENCRYPT_MODE, skey, iv, data); } public static byte[] decode(String skey, String iv, byte[] data) { return process(Cipher.DECRYPT_MODE, skey, iv, data); } private static byte[] process(int mode, String skey, String iv, byte[] data) { // 校验密钥和IV长度 byte[] keyBytes = skey.getBytes(StandardCharsets.UTF_8); if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) { throw new IllegalArgumentException("AES密钥长度必须是16/24/32位"); } byte[] ivBytes = iv.getBytes(StandardCharsets.UTF_8); if (ivBytes.length != 16) { throw new IllegalArgumentException("CBC模式IV长度必须是16位"); } SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); AlgorithmParameterSpec param = new IvParameterSpec(ivBytes); try { Cipher cipher = Cipher.getInstance(cipher_type); cipher.init(mode, key, param); return cipher.doFinal(data); } catch (Exception e) { throw new RuntimeException("加解密操作失败", e); } } }
内容的提问来源于stack exchange,提问作者MAYO
相关产品推荐
相关产品推荐

