解决IllegalBlockSizeException:last block incomplete in decryption异常
解决IllegalBlockSizeException:last block incomplete in decryption异常
分类: webkit android
最近做个加解密的实现,虽然实现了,但是发现还有如下的异常出现:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
at org.bouncycastle.jce.provider.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:711)
at javax.crypto.Cipher.doFinal(Cipher.java:1090)
问题原因:
可能是因为直接将一个string的byte []字符串直接加密成密文,在传输过程中,由于默认的编码方式的问题可能会造成数据的丢失。(如果有更好的解释,欢迎指出)
解决方法:
将加密后的密文再进行整体的base64加密,解码时先对其进行base64解密再进DES/AES解密,这样就能保证接受数据的正确性并且不会缺失。
Base64Utils加密工具
package test;
import it.sauronsoftware.base64.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/** *//**
* <p>
* BASE64编码解码工具包
* </p>
* <p>
* 依赖javabase64-1.3.1.jar
* </p>
*
* @author IceWee
* @date 2012-5-19
* @version 1.0
*/
public class Base64Utils {
private static String SF_DF_BASE64= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";//自定义时解码使用
/** *//**
* 文件读取缓冲区大小
*/
private static final int CACHE_SIZE = 1024; /** *//**
* <p>
* BASE64字符串解码为二进制数据
* </p>
*
* @param base64
* @return
* @throws Exception
*/
public static byte[] decode(String base64) throws Exception {
return Base64.decode(base64.getBytes());
}
/**
* 自定义的解码实现
* @param base64
* @return
* @throws Exception
*/
public static byte[] selfDecode1(String base64)throws Exception {
int n,i,j,pad;
byte [] dst;
char [] src;
int len = 0;
pad=0;
n = base64.length();
src = new char [n];
for(i=0;i<n;i++){//复制到src中
src[i] = base64.charAt(i);
}
while(n>0&&src[n-1]=='=') {
src[n-1]=0;
pad++;
n--;
} for(i=0;i<n;i++) { //map base64 ASCII character to 6 bit value
int iTt = SF_DF_BASE64.indexOf(src[i]);
if(iTt<0)
break;
src[i] = (char)iTt;
}
dst = new byte[n*3/4+1];
for(i=0,j=0;i<n;i+=4,j+=3) {
dst[j] = (byte)((src[i]<<2) + ((src[i+1]&0x30)>>4));
dst[j+1] = (byte)(((src[i+1]&0x0F)<<4) + ((src[i+2]&0x3C)>>2));
dst[j+2] = (byte)(((src[i+2]&0x03)<<6) + src[i+3]);
len+=3;
}
len-=pad;
return dst;
}
/** *//**
* <p>
* 二进制数据编码为BASE64字符串
* </p>
*
* @param bytes
* @return
* @throws Exception
*/
public static String encode(byte[] bytes) throws Exception {
return new String(Base64.encode(bytes));
} /** *//**
* <p>
* 二进制数据编码为BASE64字符串
* </p>
*
* @param buf
* @return
* @throws Exception
*/
public static String selfEncode1(byte[] buf) throws Exception {
int n,buflen,i,j;
byte []dst = null;
//CString buf = src;
buflen=n=buf.length;
dst = new byte[buflen/3*4+3];
for(i=0,j=0;i<=buflen-3;i+=3,j+=4) {
dst[j] = (byte)((buf[i]&0xFC)>>2);
dst[j+1] = (byte)(((buf[i]&0x03)<<4) + ((buf[i+1]&0xF0)>>4));
dst[j+2] = (byte)(((buf[i+1]&0x0F)<<2) + ((buf[i+2]&0xC0)>>6));
dst[j+3] = (byte)(buf[i+2]&0x3F);
}
if(n%3==1) {
dst[j] = (byte)((buf[i]&0xFC)>>2);
dst[j+1] = (byte)(((buf[i]&0x03)<<4));
dst[j+2]=64;
dst[j+3]=64;
j+=4;
}
else if(n%3==2) {
dst[j] = (byte)((buf[i]&0xFC)>>2);
dst[j+1] = (byte)(((buf[i]&0x03)<<4)+((buf[i+1]&0xF0)>>4));
dst[j+2] = (byte)(((buf[i+1]&0x0F)<<2));
dst[j+3]=64;
j+=4;
}
for(i=0;i<j;i++) /* map 6 bit value to base64 ASCII character */
dst[i] = (byte)SF_DF_BASE64.charAt((int)dst[i]);
dst[j]=0;
return new String(dst);
} /** *//**
* <p>
* 将文件编码为BASE64字符串
* </p>
* <p>
* 大文件慎用,可能会导致内存溢出
* </p>
*
* @param filePath 文件绝对路径
* @return
* @throws Exception
*/
public static String encodeFile(String filePath) throws Exception {
byte[] bytes = fileToByte(filePath);
return encode(bytes);
} /** *//**
* <p>
* BASE64字符串转回文件
* </p>
*
* @param filePath 文件绝对路径
* @param base64 编码字符串
* @throws Exception
*/
public static void decodeToFile(String filePath, String base64) throws Exception {
byte[] bytes = decode(base64);
byteArrayToFile(bytes, filePath);
} /** *//**
* <p>
* 文件转换为二进制数组
* </p>
*
* @param filePath 文件路径
* @return
* @throws Exception
*/
public static byte[] fileToByte(String filePath) throws Exception {
byte[] data = new byte[0];
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
data = out.toByteArray();
}
return data;
} /** *//**
* <p>
* 二进制数据写文件
* </p>
*
* @param bytes 二进制数据
* @param filePath 文件生成目录
*/
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
InputStream in = new ByteArrayInputStream(bytes);
File destFile = new File(filePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
} // 加密
public static String getBase64(String str) {
byte[] b = null;
String s = null;
try {
b = str.getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (b != null) {
s = new BASE64Encoder().encode(b);
}
return s;
} // 解密
public static String getFromBase64(String s) {
byte[] b = null;
String result = null;
if (s != null) {
BASE64Decoder decoder = new BASE64Decoder();
try {
b = decoder.decodeBuffer(s);
result = new String(b, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
} }
TestWebService
package test; import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.jws.WebService;
import javax.xml.ws.Endpoint; @WebService
public class TestWebService { //解密
public String executeDe(String content){ String password = "1234567890123456";
byte[] decryptResult;
String decrypt;
try {
//base64解密(后加!!)
String decodeBase64 = Base64Utils.getFromBase64(content); decryptResult = Base64Utils.decode(decodeBase64);
decrypt = new String(decrypt(decryptResult,password,16));
return decrypt;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
} return null;
} //加密
public String executeEn(String content){ System.out.println(System.getProperty("file.encoding"));
//加密内容
//String content = "密码学中的高级加密标准(AdvancedEncryptionStandard,AES)";
//String content = "rowvin";
//String content = "test123456";
//为与Delphi编码统一,将字符转为UTF8编码(其他语言也相同)
//String ss=new String(content.getBytes(),"UTF-8");
//密钥
String password = "1234567890123456";
System.out.println("加密前:" + content);
byte[] encryptResult;
String encrypt;
try {
encryptResult = encrypt(content, password,16);//16位密钥长度128位、24位密钥长度192、32位密钥长度256(在delphi中对应kb128、kb192、快播56)
//System.out.println("加密后:" + parseByte2HexStr(encryptResult));//将加密后编码二进制转为16进制编码
System.out.println(Base64Utils.encode(encryptResult));//二进制转Hbase64
encrypt = Base64Utils.encode(encryptResult);
//base64加密(后加!)
String encodeAfterBase64 = Base64Utils.getBase64(encrypt);
StringBuffer AesBuff = new StringBuffer(); /*decrypt = new String(decrypt(encryptResult,password,16));
System.out.println("解密后:" + decrypt);*/
AesBuff.append("{");
AesBuff.append("\"encrypt\":" + "\"" + encrypt + "\",");
AesBuff.append("\"encodeAfterBase64\":" + "\"" + encodeAfterBase64 + "\"}");
//System.out.println(json.toString());
return AesBuff.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
} return null;
} /**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密码
* @param keySize 密钥长度16,24,32
* @return
* @throws UnsupportedEncodingException
* @throws InvalidAlgorithmParameterException
*/ public byte[] encrypt(String content, String password, int keySize) throws UnsupportedEncodingException, InvalidAlgorithmParameterException {
try {
//密钥长度不够用0补齐。
SecretKeySpec key = new SecretKeySpec(ZeroPadding(password.getBytes(), keySize), "AES");
//定义加密算法AES、算法模式ECB、补码方式PKCS5Padding
//Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//定义加密算法AES 算法模式CBC、补码方式PKCS5Padding
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//CBC模式模式下初始向量 不足16位用0补齐
IvParameterSpec iv = new IvParameterSpec(ZeroPadding("1234567890123456".getBytes(),16));
byte[] byteContent = content.getBytes();
//初始化加密
//ECB
//cipher.init(Cipher.ENCRYPT_MODE, key);
//CBC
cipher.init(Cipher.ENCRYPT_MODE, key,iv);
byte[] result = cipher.doFinal(byteContent);
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;
} /**解密
* @param content 待解密内容
* @param password 解密密钥
* @param keySize 密钥长度16,24,32
* @return
* @throws InvalidAlgorithmParameterException
*/
public byte[] decrypt(byte[] content, String password, int keySize) throws InvalidAlgorithmParameterException {
try {
//密钥长度不够用0补齐。
SecretKeySpec key = new SecretKeySpec(ZeroPadding(password.getBytes(), keySize), "AES");
//定义加密算法AES、算法模式ECB、补码方式PKCS5Padding
//Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
//定义加密算法AES 算法模式CBC、补码方式PKCS5Padding
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//CBC模式模式下初始向量 不足16位用0补齐
IvParameterSpec iv = new IvParameterSpec(ZeroPadding("1234567890123456".getBytes(),16));
// 初始化解密
//ECB
//cipher.init(Cipher.DECRYPT_MODE, key);
//CBC
cipher.init(Cipher.DECRYPT_MODE, key,iv); 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;
} /**将二进制转换成16进制
* @param buf
* @return
*/
public 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进制转换为二进制
* @param hexStr
* @return
*/
public 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;
} public byte[] ZeroPadding(byte[] in,Integer blockSize){
Integer copyLen = in.length;
if (copyLen > blockSize) {
copyLen = blockSize;
}
byte[] out = new byte[blockSize];
System.arraycopy(in, 0, out, 0, copyLen);
return out;
} public static void main(String[] args) {
Endpoint.publish("http://10.80.3.51:9999/Service/TestWebService", new TestWebService());
System.out.println("服务已启动~~~~");
} }
解决IllegalBlockSizeException:last block incomplete in decryption异常的更多相关文章
- 如何解决结果由block返回情况下的同步问题(转)
开发中经常会遇到一种简单的同步问题: 系统在获取资源时,采用了block写法,外部逻辑需要的结果是在block回调中返回的 举个例子: 请求获取通讯录权限的系统弹窗 调用系统方法请求通讯录权限: AB ...
- CSS开发技巧(四):解决flex多行布局的行间距异常、子元素高度拉伸问题
在使用flex布局时,若出现换行,有两种较为特殊的现象是值得我们研究的: 子元素高度被拉伸,其实际高度大于它的内容高度. 各行子元素之间的行间距过大,甚至我们根本没有给子元素设置margin. 现在我 ...
- .NET WebAPI 自定义 NullableConverter 解决请求入参 “”空字符触发转换异常问题
最近在项目中启用了Nullable 可为空的类型,这个特性确实很好用,在 WebAPI 的入参上可以直接采用 ? 来标记一个字段是否允许为空,但是使用过程中遇到了如下一个问题,比如创建部门接口 我们定 ...
- 使用AFNetworking时, 控制器点击返回销毁了, 但还是会执行请求成功或失败的block, 导致野指针异常
原本我以为是我程序框架有问题...后来才知道, 无知真可怕... __unsafe_unretained __block typeof(self) weakSelf = self; AFHTTPSes ...
- 解决Entity Framework中DateTime类型字段异常
从 datetime2 数据类型到 datetime 数据类型的转换产生一个超出范围的值 具体的错误原因是:C#中的DateTime类型比SqlServer中的datetime范围大.SqlServe ...
- 解决eclipse报PermGen space内存溢出异常的问题
异常问题如下所示: 1.点击Eclipse->Window->Preferences,如下所示: 2.点击Server->Runtime Environments,选择Apache ...
- hadoop异常: 到目前为止解决的最牛逼的一个异常(java.io.IOException: Incompatible clusterIDs)
(注意: 本人用的版本为hadoop2.2.0, 旧的版本和此版本的解决方法不同) 异常为: 9 (storage id DS-2102177634-172.16.102.203-50010-1384 ...
- 解决Kubelet Pod启动CreatePodSandbox或RunPodSandbox异常方法
新装Kubernetes,创建一个新Pod,启动Pod遇到CreatePodSandbox或RunPodSandbox异常.查看日志 # journalctl --since :: -u kubele ...
- 【手记】解决“未能创建 SSL/TLS 安全通道”异常
之前写了一个桌面程序,程序会间歇性访问某个https接口,一直用的好好的,今天突然报错了,异常就发生在访问接口的地方,曰“请求被中止,未能创建 SSL/TLS 安全通道.”,另外有台电脑也有跑该程序, ...
随机推荐
- SQL——基础概念
服务器登录名:指有权限登录到某服务器的用户:如sa 服务器角色:指一组固定的服务器用户,默认有9组: 登录名一定属于某些角色,默认为public 服务器角色不容许更改 登录后也不一定有权限操作数据库 ...
- Job for mysqld.service failed because the control process exited with error code. See "systemctl status mysqld.service" and "journalctl -xe" for details.
一.前言 Job for mysqld.service failed because the control process exited with error code. See "sys ...
- E20190226-hm
shallow adj. 浅的,肤浅的; 表面的,皮毛的; (水,器物等) 浅的; (呼吸) 浅的; n. 浅处; 浅滩;
- 洛谷 - UVA11346 - 概率 Probability - 积分
要是没学过高等数学的积分怎么办呢?可以求助于自适应辛普森法. 容易发现其实这个图形是对称的,我们只要求第一象限就可以了,第一象限如上图. 由于取点是在面积内等概率的,由高中的几何概型可知,所求概率为: ...
- 怎样让自定义Cell的图片和文本自适应高度
Let's do it! 首先创建一个Model类 包括一个图片名称属性 还有文字内容属性 #import <Foundation/Foundation.h> @interface Mod ...
- [Xcode 实际操作]二、视图与手势-(3)UIView视图的基本操作
目录:[Swift]Xcode实际操作 本文将实现视图的添加与删除,以及切换视图在父视图中的层次. import UIKit class ViewController: UIViewControlle ...
- IT兄弟连 JavaWeb教程 El基本语法
EL(Expression Language)表达式语言是在JSP 2.0版本中引入的新特性,它用于JSP文件中的数据访问.这种表达式语言能简化JSP文件中数据访问的代码,可用来替代传统的基于&quo ...
- Mysql相关函数使用和总结(cast、convert)
一.类型转换 1.获取一个类型的值,并产生另一个类型的值,CAST()和CONVERT()函数. 用法: CAST(value as type); CONVERT(value, type); 解释:C ...
- css文本之蛇
文本之蛇 css把文本当做一行来处理,把他们放在一个看不见的盒子里面.盒子遇到容器的外边界会折行.所有的文本属性都应用于这个盒子,而不是包含文本的容器. 最有用的8个文本属性 文本缩进(text-in ...
- Cannot convert value '0000-00-00 00:00:00' TIMESTAMP
MySql Timestamp 类型的字段 '0000-00-00 00:00:00' 转换成Java Timestamp 时会抛出 Cannot convert value '0000-00-00 ...