加密代码

        /*** 加密* * @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相关推荐

  1. AES解密报错,Input length must be multiple of 16 when decrypting with padded cipher

    项目场景:对登录用户名.密码前端加密,后端解密失败 问题描述 在做login登录页面的用户名和密码加密时,前端加密后端解密,但是抛出报错:Input length must be multiple o ...

  2. AES加密/解密报错,Input length must be multiple of 16 when decrypting with padded cipher

    背景:需要存储一个类似密钥的字符串,密文存储,并要求能逆向解密出来. 问题描述:使用AES对该字符串进行加密后生成byte数组,使用new String()方法转为字符串后存储到数据库. 从数据库中取 ...

  3. 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 ...

  4. 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 ...

  5. 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" ...

  6. 微信小程序手机号解密报错:pad block corrupted 解决方法

    微信小程序手机号解密报错:pad block corrupted 解决方法 微信小程序获取用户手机号,后端解密手机号的时候偶尔会报错 javax.crypto.BadPaddingException: ...

  7. 微信小程序获取手机号,java解密报错

    临时帮朋友解决这个bug花了一下午时间,出坑以后赶紧给各位爷写一篇文章,心累.. 在此之前先测一下你的程序有没有问题,如果程序有问题,先去底部把我的代码拿走: String encryptedData ...

  8. java cipher用法_java使用Cipher 执行RSA解密报错

    padding选取都是一样的,加密成功,解密失败,很奇怪. #主要代码 public static byte[] rsa_encrypt(byte[] bArr, byte[] bArr2) { tr ...

  9. AES加密报错:Illegal key size or default parameters或希望支持32位密钥

    今天在接一个中·宣部文档时用到了AES128加密,对方给的密钥是32位的,方法写完运行时报该错误,如下: 问题原因jdk自带的加密包,不支持32位密钥加密,需要下载jar包替换掉 需要替换的jar包: ...

最新文章

  1. 格式化测试数据,组装用于插入表中的sql语句
  2. 第十二课:小信号分析 (二)
  3. Spring Boot + Mybatis + Shiro 后台权限管理系统
  4. 使用PLP特征训练crnn语音分类
  5. MyBatis及Spring事务初学总结
  6. 浏览器打不开html链接,win7系统ie浏览器打不开网站链接怎么办
  7. 多个iframe同时加载并动态调整大小
  8. 【NOIP2004】【Luogu1088】火星人(枚举排列)
  9. python 怎么调用 矩阵 第几行_python工厂第19层 多重列表1
  10. 揭秘云网络大会“网红”:阿里云自研高性能网关XGW
  11. 中文词语自动纠错_编辑距离
  12. java 二级联动实现
  13. 基于阿里云服务器使用宝塔面板进行Hexo建站
  14. 不加群提取群成员_快速提取PPT上的文字!
  15. 数据库原理课后作业答案 第七章
  16. WPF界面框架的设计
  17. sql——手机号码归属地、身份证前六位归属地、省市区级联
  18. 转发小程序php,微信小程序 转发功能的实现
  19. 远程控制计算机开关机
  20. 度量学习Metric Learning

热门文章

  1. 谷歌核心算法大更新,如何趋利避害对电商网站排名影响?
  2. 博弈论:别人的想法(文末送书!)
  3. 这套网红试卷火了!数学老师您应该是文案出身吧?
  4. 那些女程序员们的故事
  5. 推荐系统--矩阵分解(1)
  6. 基于Curator实现dubbo服务自动注册发现
  7. C语言fgets函数了解
  8. 计算图像的直方图,求峰值点
  9. OAM创始团队:揭秘OAMKubernetes实现核心原理
  10. 阿里工程师养了只“二哈”,专治讨厌的骚扰电话