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也不相同,暫時不知道什么原因