php base64_decode与java base64解密结果不匹配问题

1.正常的字符串base64加密后,php和java都可以正常解析

例如:

原文:

this is a test

java代码:

String test = "this is a test";
System.out.println(new String(java.util.Base64.getEncoder().encode(test.getBytes())));
System.out.println(org.apache.commons.codec.binary.Base64.encodeBase64String(test.getBytes()));

java代码结果:

dGhpcyBpcyBhIHRlc3Q=
dGhpcyBpcyBhIHRlc3Q=

php代码:

<?php
        echo base64_encode('this is a test')."\n";
?>

php代码结果:

dGhpcyBpcyBhIHRlc3Q=

解析过程就不再列举了,解析结果都是可以还原原字符串。

 

2.特殊字符串(非base64加密的字符串结果)进行base64 decode解析结果不同

场景:公司某个业务的手机号php系统加密算法传输(涉及到base64加密),对端java系统进行解密(涉及到base64解密)


加密流程暂不列举,直接列举base64解密结果


加密原文:

MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA

php代码:

<?php
        $string = base64_decode('MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA');
        echo $string."\n";
        echo strlen($string)."\n";
?>

php代码结果:

33Z��0~(%i�A��W�uϞ�\����V�hK�(�
37

java代码:

String test = "MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA";
String result1 = new String(java.util.Base64.getDecoder().decode(test.getBytes()));
System.out.println(result1);
System.out.println(result1.length());
String result2 = new String(org.apache.commons.codec.binary.Base64.decodeBase64(test));
System.out.println(result2);
System.out.println(result2.length());

java代码结果:

33Z��0~(%i�A�W�uϞ�\����V�hK�(�
35
33Z��0~(%i�A�W�uϞ�\����V�hK�(�
35

很明显,php解密的结果文本和字符串长度都与java不同


java解决问题:

1.查看解密后字节长度


java代码:

String test = "MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA";
byte[] result1 = java.util.Base64.getDecoder().decode(test.getBytes());
System.out.println(result1.length);
byte[] result2 = org.apache.commons.codec.binary.Base64.decodeBase64(test);
System.out.println(result2.length);

java代码结果:

37
37

结论:字节长度相符,所以最终得到的字符串,并不是通过new String()生成。

 

2.查看php解密后ASCII码与java字节码的对比


php代码:

<?php
        $string = base64_decode('MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA');
        for($i = 0; $i < strlen($string); $i++) {
            echo ord($string[$i])." ";
        }
?>

php代码结果:

51 51 29 90 150 175 48 23 126 20 21 40 37 105 157 65 230 170 87 146 117 207 158 243 92 178 128 159 163 86 180 104 75 215 40 21 180

java代码:

String test = "MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA";
byte[] result1 = java.util.Base64.getDecoder().decode(test.getBytes());
for (int i = 0; i < result1.length; i++) {
    System.out.print(result1[i] + " ");
}
System.out.println();
byte[] result2 = org.apache.commons.codec.binary.Base64.decodeBase64(test);
for (int i = 0; i < result2.length; i++) {
    System.out.print(result2[i] + " ");
}

java代码结果:

51 51 29 90 -106 -81 48 23 126 20 21 40 37 105 -99 65 -26 -86 87 -110 117 -49 -98 -13 92 -78 -128 -97 -93 86 -76 104 75 -41 40 21 -76
51 51 29 90 -106 -81 48 23 126 20 21 40 37 105 -99 65 -26 -86 87 -110 117 -49 -98 -13 92 -78 -128 -97 -93 86 -76 104 75 -41 40 21 -76

对比后发现:

java的负数字节码与php的字节码结果相差256


ok,修改java解密逻辑,新增256的计算

 


java代码:

String test = "MzMdWpavMBd+FBUoJWmdQeaqV5J1z57zXLKAn6NWtGhL1ygVtA";
byte[] result1 = java.util.Base64.getDecoder().decode(test.getBytes());
StringBuffer sb1 = new StringBuffer();
for (int i = 0; i < result1.length; i++) {
    if (result1[i] > 0) {
        sb1.append((char) result1[i]);
    } else {
        sb1.append((char) (result1[i] + 256));
    }
}
System.out.println(sb1.toString());
System.out.println(sb1.length());
byte[] result2 = org.apache.commons.codec.binary.Base64.decodeBase64(test);
StringBuffer sb2 = new StringBuffer();
for (int i = 0; i < result2.length; i++) {
    if (result2[i] > 0) {
        sb2.append((char) result2[i]);
    } else {
        sb2.append((char) (result2[i] + 256));
    }
}
System.out.println(sb2.toString());
System.out.println(sb2.length());

String str3 = new String(result1, java.nio.charset.StandardCharsets.ISO_8859_1);
System.out.println(str3);
System.out.println(str3.length());

java代码结果:

33Z¯0~(%iAæªWuÏó\²£V´hK×(´
37
33Z¯0~(%iAæªWuÏó\²£V´hK×(´
37
33Z¯0~(%iAæªWuÏó\²£V´hK×(´
37

3.结论

1.非base64加密的标准数据,通过base64解码,php和java结果字符串不同

2.java获取base64解码的字节数组,长度与php解码长度一致,字节数字为正数,与php的ASCII码一致,负数的话,与php的ASCII码相差256;

3.也可以通过ISO_8859_1编码,获取到长度一致的字符串,遍历字符串每个char的int值,也是与php的ASCII码相同

4.不同的第三方jar解析base64,结果是一样的

5.长度和ASCII码都与php相同时,得到的字符串与php也不相同,暂时不知道什么原因

  • 3
    点赞
  • 3
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

mjx_2011

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值