AES hex 解密报 Given final block not properly padded 的解决方案
Given final block not properly padded 的解决方法上游给了一串密文,告诉我用aes解密 (十六进制的那种) 然后怎么也解密不了,后来了解了下,AES 加解密 有两种格式, 一种是 base64 的情况, 一种是 hex 的情况于是在网上找了AES hex类型解密 的代码,使用了hex解密方式去解密,结果解密方法报错 Given final bl...
Given final block not properly padded 的解决方法
上游给了一串密文,告诉我用aes解密 (十六进制的那种) 然后怎么也解密不了,后来了解了下,
AES 加解密 有两种格式, 一种是 base64 的情况, 一种是 hex 的情况
于是在网上找了AES hex类型解密 的代码,
使用了hex解密方式去解密,结果解密方法报错 Given final block not properly padded
这个错误有两种问题,
1 你的密钥不对
2 填充位数不对, AES 密钥有16 ,24,32 等 位数的字节, 密钥有多少位就应该用多大的填充字节,比如密钥是32位,你这边用了16位的解密方式,
// 密钥补位
int plus= 16-key.length();
byte[] data = key.getBytes("utf-8");
byte[] raw = new byte[16];
byte[] plusbyte={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
for(int i=0;i<16;i++)
{
if (data.length > i)
raw[i] = data[i];
else
raw[i] = plusbyte[plus];
}
这样就会报 Given final block not properly padded (鉴于最终块未正确填充) 字面意思很清楚, 就是未正确填充,
将填充代码修改成
// 密钥补位
int plus= 32-key.length();
byte[] data = key.getBytes("utf-8");
byte[] raw = new byte[32];
byte[] plusbyte={ 0x08, 0x08, 0x04, 0x0b, 0x02, 0x0f, 0x0b, 0x0c,0x01, 0x03, 0x09, 0x07, 0x0c, 0x03, 0x07, 0x0a, 0x04, 0x0f,0x06, 0x0f, 0x0e, 0x09, 0x05, 0x01, 0x0a, 0x0a, 0x01, 0x09,0x06, 0x07, 0x09, 0x0d };
for(int i=0;i<32;i++)
{
if (data.length > i)
raw[i] = data[i];
else
raw[i] = plusbyte[plus];
}
就可以解决问题
最后贴上解密方面的代码,
/**
* 解密
* @param String src 解密字符串
* @param String key 密钥
* @return 解密后的字符串
*/
public static String Decrypt(String src, String key) throws Exception {
try {
// 判断Key是否正确
if (key == null) {
System.out.print("Key为空null");
return null;
}
// 密钥补位
int plus= 32-key.length();
byte[] data = key.getBytes("utf-8");
byte[] raw = new byte[32];
byte[] plusbyte={ 0x08, 0x08, 0x04, 0x0b, 0x02, 0x0f, 0x0b, 0x0c,0x01, 0x03, 0x09, 0x07, 0x0c, 0x03, 0x07, 0x0a, 0x04, 0x0f,0x06, 0x0f, 0x0e, 0x09, 0x05, 0x01, 0x0a, 0x0a, 0x01, 0x09,0x06, 0x07, 0x09, 0x0d };
for(int i=0;i<32;i++)
{
if (data.length > i)
raw[i] = data[i];
else
raw[i] = plusbyte[plus];
}
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
//byte[] encrypted1 = new Base64().decode(src);//base64
byte[] encrypted1 = toByteArray(src);//十六进制
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original,"utf-8");
return originalString;
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
} catch (Exception ex) {
System.out.println(ex.toString());
return null;
}
}
/**
* 将byte[]转为各种进制的字符串
* @param bytes byte[]
* @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
* @return 转换后的字符串
*/
public static String binary(byte[] bytes, int radix){
return new BigInteger(1, bytes).toString(radix); // 这里的1代表正数
}
/**
* 16进制的字符串表示转成字节数组
*
* @param hexString 16进制格式的字符串
* @return 转换后的字节数组
**/
public static byte[] toByteArray(String hexString) {
if (hexString.isEmpty())
throw new IllegalArgumentException("this hexString must not be empty");
hexString = hexString.toLowerCase();
final byte[] byteArray = new byte[hexString.length() / 2];
int k = 0;
for (int i = 0; i < byteArray.length; i++) {//因为是16进制,最多只会占用4位,转换成字节需要两个16进制的字符,高位在先
byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
byteArray[i] = (byte) (high << 4 | low);
k += 2;
}
return byteArray;
}
更多推荐
所有评论(0)