什麼是Base64
Base64是網路上最常見的用於傳輸8Bit位元組程式碼的編碼方式之一,Base64並不是安全領域的加密演算法,其實Base64只能算是一個編碼演算法,對資料內容進行編碼來適合傳輸。標準Base64編碼解碼無需額外資訊即完全可逆,即使你自己自定義字符集設計一種類Base64的編碼方式用於資料加密,在多數場景下也較容易破解。Base64編碼本質上是一種將二進位制資料轉成文字資料的方案。對於非二進位制資料,是先將其轉換成二進位制形式,然後每連續6位元(2的6次方=64)計算其十進位制值,根據該值在A--Z,a--z,0--9,+,/
這64個字元中找到對應的字元,最終得到一個文字字串。
Base64 編碼要求把 3 個 8 位位元組(3x8=24)轉化為 4 個 6 位的位元組(4x6=24),之後在 6 位的前面補兩個 0 ,形成 8 位一個位元組的形式。 如果剩下的字元不足 3 個位元組,則用 0 填充,輸出字元使用 ‘=’,因此編碼後輸出的文字末尾可能會出現 1 或 2 個 ‘=’。
java實現
public abstract class Base64 {
private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.toCharArray();
public static String encode(byte[] data) {
int start = 0;
int len = data.length;
StringBuilder buf = new StringBuilder(data.length * 3 / 2);
int end = len - 3;
int i = start;
int n = 0;
while (i <= end) {
int d = ((((int) data[i]) & 0x0ff) << 16)
| ((((int) data[i + 1]) & 0x0ff) << 8)
| (((int) data[i + 2]) & 0x0ff);
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append(legalChars[(d >> 6) & 63]);
buf.append(legalChars[d & 63]);
i += 3;
if (n++ >= 14) {
n = 0;
buf.append(" ");
}
}
if (i == start + len - 2) {
int d = ((((int) data[i]) & 0x0ff) << 16)
| ((((int) data[i + 1]) & 255) << 8);
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append(legalChars[(d >> 6) & 63]);
buf.append("=");
} else if (i == start + len - 1) {
int d = (((int) data[i]) & 0x0ff) << 16;
buf.append(legalChars[(d >> 18) & 63]);
buf.append(legalChars[(d >> 12) & 63]);
buf.append("==");
}
return buf.toString();
}
}
複製程式碼
自定義 Base64 編碼表及破解
標準的base64編碼表是A--Z,a--z,0--9,+,/
,但是我們完全可以替換這64個字元或者打亂順序,這樣只有我們知道編碼表才能解碼。通過拼接0~63的6位2進位制字串,然後分割轉換成長度為48的byte陣列,便可以得到編碼表。詳細步驟如下:
- 計算出0-63這64個數字的6位2進位制數,轉換成字串拼接成一個完整的字串,長度就是64x6
- 將字串每8個(1byte就是8位)一組,分割成48份,48x8
- 通過
Integer.parseInt(binaryString, 2)
解析成數字,再強轉成byte - 對這個長度為48的byte陣列進行編碼
- 編碼的結果就是編碼表了
public class test {
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 64; i++) {
stringBuilder.append(binary2decimal(i, 6));
}
byte[] byteDecode = new byte[48];
System.out.println(stringBuilder.toString());
for (int i = 0; i < 48; i++) {
String binaryString = stringBuilder.substring(i * 8, (i + 1) * 8);
byteDecode[i] = (byte) Integer.parseInt(binaryString, 2);
}
System.out.println(Base64.encode(byteDecode));
}
//十進位制轉換為指定位數的二進位制
private static String binary2decimal(int decNum, int digit) {
StringBuilder binStr = new StringBuilder();
for (int i = digit - 1; i >= 0; i--) {
binStr.append((decNum >> i) & 1);
}
return binStr.toString();
}
}
複製程式碼
列印如下:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567 89+/
複製程式碼