JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher
加密代码
/*** 加密* * @param content 需要加密的内容* @param password 加密密码* @return*/public static byte[] encrypt(String content, String password) {try { KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128, new SecureRandom(password.getBytes()));SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");Cipher cipher = Cipher.getInstance("AES");// 创建密码器byte[] byteContent = content.getBytes("utf-8");cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(byteContent);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}
解密代码
/**解密* 解密的时候要传入byte数组* @param content 待解密内容* @param password 解密密钥* @return*/public static byte[] decrypt(byte[] content, String password) {try {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128, new SecureRandom(password.getBytes()));SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 创建密码器cipher.init(Cipher.DECRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(content);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}
测试代码
String content = "test";String password = "12345678";//加密System.out.println("加密前:" + content);byte[] encryptResult = encrypt(content, password);//解密byte[] decryptResult = decrypt(encryptResult,password);System.out.println("解密后:" + new String(decryptResult));
输出结果如下:
加密前:test
解密后:test
容易出错的地方:
如果我们将测试代码修改一下,如下:
String content = "test";String password = "12345678";//加密System.out.println("加密前:" + content);byte[] encryptResult = encrypt(content, password);try {String encryptResultStr = new String(encryptResult,"utf-8");//解密byte[] decryptResult = decrypt(encryptResultStr.getBytes("utf-8"),password);System.out.println("解密后:" + new String(decryptResult));} catch (UnsupportedEncodingException e) {e.printStackTrace();}
则,系统会报出如下异常:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipherat com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)at javax.crypto.Cipher.doFinal(DashoA13*..)
这主要是因为加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;要避免这种情况,我们需要做一些修订,可以考虑将二进制数据转换成十六进制表示,主要有如下两个方法:
二进制转换成16进制
/**将二进制转换成16进制* @param buf* @return*/public static String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}
16进制转换为二进制
/**将16进制转换为二进制* @param hexStr* @return*/public static byte[] parseHexStr2Byte(String hexStr) {if (hexStr.length() < 1)return null;byte[] result = new byte[hexStr.length()/2];for (int i = 0;i< hexStr.length()/2; i++) {int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);result[i] = (byte) (high * 16 + low);}return result;}
然后,我们再修订以上测试代码,如下:
String content = "test";String password = "12345678";//加密System.out.println("加密前:" + content);byte[] encryptResult = encrypt(content, password);String encryptResultStr = parseByte2HexStr(encryptResult);System.out.println("加密后:" + encryptResultStr);//解密byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);byte[] decryptResult = decrypt(decryptFrom,password);System.out.println("解密后:" + new String(decryptResult));
测试结果如下:
加密前:test
加密后:73C58BAFE578C59366D8C995CD0B9D6D
解密后:test
另外一种加密方式
/*** 加密** @param content 需要加密的内容* @param password 加密密码* @return*/public static byte[] encrypt2(String content, String password) {try {SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");byte[] byteContent = content.getBytes("utf-8");cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(byteContent);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}
这种加密方式有两种限制
密钥必须是16位的
待加密内容的长度必须是16的倍数,如果不是16的倍数,就会出如下异常:
javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytesat com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)at javax.crypto.Cipher.doFinal(DashoA13*..)
要解决如上异常,可以通过补全传入加密内容等方式进行避免。
JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher相关推荐
- AES解密报错,Input length must be multiple of 16 when decrypting with padded cipher
项目场景:对登录用户名.密码前端加密,后端解密失败 问题描述 在做login登录页面的用户名和密码加密时,前端加密后端解密,但是抛出报错:Input length must be multiple o ...
- AES加密/解密报错,Input length must be multiple of 16 when decrypting with padded cipher
背景:需要存储一个类似密钥的字符串,密文存储,并要求能逆向解密出来. 问题描述:使用AES对该字符串进行加密后生成byte数组,使用new String()方法转为字符串后存储到数据库. 从数据库中取 ...
- AES解密报错:Given final block not properly padded. Such issues can arise if a bad key is used during dec
问题:系统登录账号密码密文传输,用AES加密之后:登录的时候抛出: javax.crypto.BadPaddingException: Given final block not properly p ...
- AES 解密报错:Given final block not properly padded. Such issues can arise if a bad key is used dur
问题:系统登录账号密码密文传输,用AES加密之后:登录的时候抛出:Given final block not properly padded. Such issues can arise if a b ...
- Linux环境AES解密报错:Given final block not properly padded. Such issues can arise if a bad key is used dur
将代码替换: String charset = "utf-8"; KeyGenerator kg = KeyGenerator.getInstance("AES" ...
- 微信小程序手机号解密报错:pad block corrupted 解决方法
微信小程序手机号解密报错:pad block corrupted 解决方法 微信小程序获取用户手机号,后端解密手机号的时候偶尔会报错 javax.crypto.BadPaddingException: ...
- 微信小程序获取手机号,java解密报错
临时帮朋友解决这个bug花了一下午时间,出坑以后赶紧给各位爷写一篇文章,心累.. 在此之前先测一下你的程序有没有问题,如果程序有问题,先去底部把我的代码拿走: String encryptedData ...
- java cipher用法_java使用Cipher 执行RSA解密报错
padding选取都是一样的,加密成功,解密失败,很奇怪. #主要代码 public static byte[] rsa_encrypt(byte[] bArr, byte[] bArr2) { tr ...
- AES加密报错:Illegal key size or default parameters或希望支持32位密钥
今天在接一个中·宣部文档时用到了AES128加密,对方给的密钥是32位的,方法写完运行时报该错误,如下: 问题原因jdk自带的加密包,不支持32位密钥加密,需要下载jar包替换掉 需要替换的jar包: ...
最新文章
- 格式化测试数据,组装用于插入表中的sql语句
- 第十二课:小信号分析 (二)
- Spring Boot + Mybatis + Shiro 后台权限管理系统
- 使用PLP特征训练crnn语音分类
- MyBatis及Spring事务初学总结
- 浏览器打不开html链接,win7系统ie浏览器打不开网站链接怎么办
- 多个iframe同时加载并动态调整大小
- 【NOIP2004】【Luogu1088】火星人(枚举排列)
- python 怎么调用 矩阵 第几行_python工厂第19层 多重列表1
- 揭秘云网络大会“网红”:阿里云自研高性能网关XGW
- 中文词语自动纠错_编辑距离
- java 二级联动实现
- 基于阿里云服务器使用宝塔面板进行Hexo建站
- 不加群提取群成员_快速提取PPT上的文字!
- 数据库原理课后作业答案 第七章
- WPF界面框架的设计
- sql——手机号码归属地、身份证前六位归属地、省市区级联
- 转发小程序php,微信小程序 转发功能的实现
- 远程控制计算机开关机
- 度量学习Metric Learning