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*..)

要解决如上异常,可以通过补全传入加密内容等方式进行避免。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/520935.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 判断时间是否大于6点_python中判断时间间隔的问题

展开全部代码有点烂&#xff0c;不过还算能解决问题注释比较详细了# -*- coding: utf-8 -*-import datetime__author__ lpe234__date__ 2015-04-26f file(1.txt)file_content f.readlines()all_lines len(file_content)def get_(content):"""递归调用:para…

迁移学习让深度学习更容易

深度学习在一些传统方法难以处理的领域有了很大的进展。这种成功是由于改变了传统机器学习的几个出发点&#xff0c;使其在应用于非结构化数据时性能很好。如今深度学习模型可以玩游戏&#xff0c;检测癌症&#xff0c;和人类交谈&#xff0c;自动驾驶。 深度学习变得强大的同…

java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类&#xff0c;字面意思是可循环使用&#xff08;Cyclic&#xff09;的屏障&#xff08;Barrier&#xff09;&#xff0c;通过它可以实现让一组线程到达一个屏障&#xff08;也可以叫同步点&#xff09;时被阻塞&#xff0…

Wi-Fi 6到底有什么特别?

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | 甜草莓责编 | 阿秃▋ 什么是Wi-Fi 6 &#xff1f;Wi-Fi 6&#xff0c;是Wi-Fi联盟给IEEE Std. P802.11ax起的别名。众所周知&#xff0c;以前我们的Wi-Fi都是叫作802.11a/b/n/g/ac/ax之类的名字。这种命名方式实在容易让人…

matlab直流电机pid调速仿真,直流电机双闭环PID调速系统仿真设计

目录直流电机双闭环PID调速系统仿真1 转速、电流双闭环直流调速系统的组成及工作原理2 双闭环调速系统的动态数学模型3 调节器的设计3.1 电流调节器的设计3.2 转速调节器的设计4 搭建模型5 参数计算5.1 参数的直接计算5仿真具体参数6 仿真结果7 结束语8 参考文献摘要在工程的应…

【小技巧】桌面图标出现蓝色问号的怎么办?

【背景】 今天因为要联调前端所以用SVN更新了一下前端的代码&#xff0c;结果没想到桌面图标全部变成了带着蓝色问号的&#xff0c;吓了自己一跳。查了一下之后顺利解决了&#xff0c;不过以防万一记录一下解决方法。 【内容】 解决步骤&#xff1a;首先确定是SVN的问题导致了…

恒强制版系统980_速来围观 | 恒强制版小图高级功能讲解

点击蓝字关注我们 Spring comes小图是用自定义的动作来定义使用者色码(120-183)。小图的主要构成如下图&#xff1a;1. 模块色数属性模块色数有如下规则&#xff1a;(1) 小于100(一般填1)的小图为普通小图【980修改】&#xff1b;(2) 小于200大于100(一般填101)的小图为提花小图…

读懂这篇文章,你的阿里技术面就可以过关了 | Apache RocketMQ 101

在美国的大学课程中&#xff0c;101是所有课程中的第一门&#xff0c;是新生入学后的必修课程。阿里巴巴中间件技术专家刘振东在上周的Apache RocketMQ开发者沙龙北京站的活动上&#xff0c;进行了主题为《ApacheRocketMQ 101》的分享&#xff0c;帮助开发者从0开始学习 Apache…

HttpClient4.5 简单入门实例(一)

一、所需要的jar包 httpclient-4.5.jar httpcore-4.4.1.jar httpmime-4.5.jar 二、实例 package com.gblfy.test;import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util…

Nacos 计划发布v0.2版本,进一步融合Dubbo和SpringCloud生态

在近期的Aliware Open Source 成都站的活动上&#xff0c;阿里巴巴高级工程师邢学超&#xff08;于怀&#xff09;分享了Nacos v0.2的规划和进度&#xff0c;并对Nacos v0.3的控制台进行了预览。Nacos v0.2将进一步融入Duboo和Spring Cloud生态&#xff0c;帮助开发者更好的在微…

你还在疯狂加班打码?兄dei,不如跟我学做超融合吧!

纵观过去十年&#xff0c;媒体、娱乐、交通、银行、保险、医疗、旅游、物流等行业&#xff0c;无一不打上了数字化的烙印。据统计&#xff0c;一百多年前&#xff0c;公司的平均寿命是67年&#xff1b;而在当今的数字化时代&#xff0c;则锐减至15年。 除此之外&#xff0c;更有…

apache禁止多目录运行php文件下载,Nginx Apache下如何禁止指定目录运行PHP脚本

网站程序的上传目录通常是不需要PHP执行权限&#xff0c;通过限制目录的PHP执行权限可以提网站的安全性&#xff0c;减少被攻击的机率。下面和大家一起分享下如何在Apache和Nginx禁止上传目录里PHP的执行权限。Apache下禁止指定目录运行PHP脚本在虚拟主机配置文件中增加php_fla…

python加载模型包占用内存多大_如何保持Keras模型加载到内存中并在需要时使用它? - python...

我正在阅读Keras blog讲解如何使用Flask创建简单的图像分类器Restful API。我想知道如何在不使用python的其他Web框架中实现加载模型的相同方法。在下面的代码中&#xff0c;将在服务器启动之前将模型加载到内存中&#xff0c;直到服务器处于活动状态&#xff0c;它才会运行&am…

你只差这两步 | 将Sentinel 控制台应用于生产环境

这是围绕 Sentinel 的使用场景、技术对比和实现、开发者实践等维度推出的系列文章的第四篇。 第一篇回顾&#xff1a; Dubbo 的流量防卫兵 | Sentinel如何通过限流实现服务的高可用性 - 传送门 第二篇回顾&#xff1a; RocketMQ 的保险丝| Sentinel 如何通过匀速请求和冷启动…

win10日常操作

C:\Windows\System32\drivers\etc

eclipse分级,分级列表显示 - bieshixuan的个人博客 - OSCHINA - 中文开源技术交流社区...

这是个效果图设计思想是&#xff0c;使用左右两个tableview分别展示NSArray * _allArr;NSMutableArray * _rightArr;UITableView * _leftTableView;UITableView * _rightTableView;初始化_arr [{"全部":[ "棉花", "小麦", "水稻", &q…

python如何实时捕捉cmd显示_如何从Python脚本中捕获Python解释器和/或CMD.EXE的输出? -问答-阿里云开发者社区-阿里云...

如果您正在谈论python解释器或CMD.exe&#xff0c;它是您脚本的“父”&#xff0c;那么不可能。在每个类似POSIX的系统中(现在你正在运行Windows&#xff0c;看起来可能有一些我不知道的怪癖&#xff0c;YMMV)每个进程都有三个流&#xff0c;标准输入&#xff0c;标准输出和标准…

分布式消息规范 OpenMessaging 1.0.0-preview 发布

OpenMessaging 是由阿里巴巴牵头发起&#xff0c;由 Yahoo、滴滴、Streamlio、微众银行、Datapipeline 等公司共同发起创建的分布式消息规范&#xff0c;其目标在于打造厂商中立&#xff0c;面向 Cloud Native &#xff0c;同时对流计算以及大数据生态友好的下一代分布式消息标…

腾讯云重磅发布系列自研产品,自研服务器星星海为云而生

今日在腾讯全球数字生态大会成都峰会上&#xff0c;腾讯云重磅发布系列自研产品&#xff0c;包括腾讯自研第四代数据中心T-block产品家族、第一款真正为云而生的自研服务器“星星海”等基础产品&#xff0c;结合现场发布的弹性容器服务、无服务器等自研产品&#xff0c;腾讯云正…

wsimport将wsdl生成java 调用时碰到的一个问题Could not initialize Service

在一个采用了XFire作为WebService框架Web项目中&#xff0c;添加由JDK1.6 wsimport命令生成的一个WebService客户端调用&#xff0c;在客户端调用时出现了如下问题 log4j:WARN No appenders could be found for logger (org.codehaus.xfire.jaxws.Provider). log4j:WARN Pleas…