Base64加密解密不一致导致AES加密报出javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 wh

Posted whalesea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Base64加密解密不一致导致AES加密报出javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 wh相关的知识,希望对你有一定的参考价值。

报错的意思的是使用该种解密方式出入长度应为16bit的倍数,但实际的错误却不是这个,错误原因根本上是因为在http请求是特殊字符编码错误,具体数就是base64生成的+号,服务器接收时成了空格,然后导致base64解码出的字节数组有改变。

下面来还原并分析一下具体原因:

请求代码:

    @Test
    public void testHttp() throws Exception 
        //16进制字节数组,单纯的为了生成含有+的base64位字符串,是在试了好多遍都没试到+,只能把我错误例子的byte数组转成16进制,为我的机智点个赞
        String src = "34aa8bc0adaccbe45ac8c7e43d25955f4d3b51a189339af3d5b968b49764f4def4b81ab285a461504a5cb930c08055f96e875e2b4be390f6708ae686b13e8ff3bed9e9455c638c3809e4c51db05ac3f496be28772829270998eddb9ec6c08c4a0cc1d23e59c6ebe8b73b75013ba9eee5";
        byte[] bytes = Hex.decodeHex(src);
        String base64Str = Base64.encodeBase64String(bytes);
        System.out.println("发送时的字符串:"+base64Str);
        for(int i=0;i<bytes.length;i++) 
            System.out.println(bytes[i]);
        
        String httpUrl = "http://10.20.20.184:10086/dbzx/hello?src="+base64Str;
        HttpRequest.doGet(httpUrl);
    

打印结果:

发送时的字符串:NKqLwK2sy+RayMfkPSWVX007UaGJM5rz1blotJdk9N70uBqyhaRhUEpcuTDAgFX5bodeK0vjkPZwiuaGsT6P877Z6UVcY4w4CeTFHbBaw/SWvih3KCknCZjt257GwIxKDMHSPlnG6+i3O3UBO6nu5Q==
52
-86
-117
-64
-83
-84
-53
-28
90
-56
-57
-28
61
37
-107
95
77
59
81
-95
-119
51
-102
-13
-43
-71
104
-76
-105
100
-12
-34
-12
-72
26
-78
-123
-92
97
80
74
92
-71
48
-64
-128
85
-7
110
-121
94
43
75
-29
-112
-10
112
-118
-26
-122
-79
62
-113
-13
-66
-39
-23
69
92
99
-116
56
9
-28
-59
29
-80
90
-61
-12
-106
-66
40
119
40
41
39
9
-104
-19
-37
-98
-58
-64
-116
74
12
-63
-46
62
89
-58
-21
-24
-73
59
117
1
59
-87
-18
-27

 

服务端代码:

package com.dbzx.controller;

import org.apache.commons.codec.binary.Base64;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dbzx.common.ResultModel;

@RestController
@RequestMapping("dbzx")
public class HelloController 
    
    @RequestMapping("/hello")
    public ResultModel hello(String src) 
        System.out.println("接收到的字符串:"+src);
        byte[] bytes = Base64.decodeBase64(src);
        for(int i=0;i<bytes.length;i++) 
            System.out.println(bytes[i]);
        
        return ResultModel.ok();
    

打印结果:

接收到的字符串:NKqLwK2sy RayMfkPSWVX007UaGJM5rz1blotJdk9N70uBqyhaRhUEpcuTDAgFX5bodeK0vjkPZwiuaGsT6P877Z6UVcY4w4CeTFHbBaw/SWvih3KCknCZjt257GwIxKDMHSPlnG6 i3O3UBO6nu5Q==
52
-86
-117
-64
-83
-84
-55
22
-78
49
-7
15
73
101
87
-45
78
-44
104
98
76
-26
-68
-11
110
90
45
37
-39
61
55
-67
46
6
-84
-95
105
24
84
18
-105
46
76
48
32
21
126
91
-95
-41
-118
-46
-8
-28
61
-100
34
-71
-95
-84
79
-93
-4
-17
-74
122
81
87
24
-29
14
2
121
49
71
108
22
-80
-3
37
-81
-118
29
-54
10
73
-62
102
59
118
-25
-79
-80
35
18
-125
48
116
-113
-106
113
-70
-117
115
-73
80
19
-70
-98
-18
80

通过两端的结果对比可以发现发送前是+,服务器接收的是空格,这是因为有些特殊字符在http请求时是无法编码的,其实base64就是解决类似问题得,只是越来越多的特殊字符,导致它出错。

有些人说base64会把+和空格转成相同的字节码,不会出错,但是我们来对比一下字节码。

技术图片

可以看到,在第7行是报错。

而原本字符串(NKqLwK2sy+)+在第10个位置,跟据base64的规则,4个base64转成的字符串,代表3个原本的字符串,而上图第七个字节,需要"y+"共同构造,这就是出错的原因。既是aes解码出错的原因。

至于16的倍数,理论上只用是偶数位的字节数都满足,显示错误出在其他方面,这个例子就是字节码出错了。

以上是关于Base64加密解密不一致导致AES加密报出javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 wh的主要内容,如果未能解决你的问题,请参考以下文章

python 加密解密(base64, AES)

java 怎么实现PHP的base64加密,两种语言的base64加密后的数据不一致

AES,Base64加密,解密

MD5加密,Base64加密/解密,AES加密/解密

实现 base64+gzip+AES-ECB加密解密

AES Base64 C++加密工具