戴兜

戴兜

Coding the world.
github
bilibili
twitter

base64數據隱寫實現原理分析

在開始這篇文章前,先讓我們來看一組 base64 編碼的字串

ZG==
YY==
aW==
ZF==
cm==
aM==
b2==
dc==
c2==
Zf==

解碼後的內容是 daidrhouse,似乎沒有什麼問題。但是仔細看,第一行和第 4 行解碼後的結果都是 d,但內容竟然不太一樣?

按照正常的 base64 編碼,daidrhouse 應該得到下面的結果。

ZA==
YQ==
aQ==
ZA==
cg==
aA==
bw==
dQ==
cw==
ZQ==

顯然,與前者相比,每串 base64 的第二個字元都被改變了,但解碼後的內容依然不變,這得從 base64 編碼的原理說起。

什麼是 base64

顧名思義,base64 編碼就是用 64 個 ascii 字元作為基礎來編碼二進位內容的一種編碼方式。相信各位一定在網頁中看到過 base64 編碼的內嵌圖片,甚至 QQ 音樂傳輸歌詞文件時,也採用了 base64 編碼。將二進位編碼為 ascii 字元,使資料在某些場景下更便於閱讀、便於傳輸。當然,將所有二進位「濃縮」到區區 64 個字元來表示,一定會在體積上作出妥協。字元在編碼完成後,會增大 1/3 倍,至於原因,下面會講到。

索引表

base64 有一張標準編碼表,為 64 個 ascii 字元排序並賦予索引。

索引 字符 索引 字符 索引 字符 索引 字符
0 A 16 Q 32 g 48 w
1 B 17 R 33 h 49 x
2 C 18 S 34 i 50 y
3 D 19 T 35 j 51 z
4 E 20 U 36 k 52 0
5 F 21 V 37 l 53 1
6 G 22 W 38 m 54 2
7 H 23 X 39 n 55 3
8 I 24 Y 40 o 56 4
9 J 25 Z 41 p 57 5
10 K 26 a 42 q 58 6
11 L 27 b 43 r 59 7
12 M 28 c 44 s 60 8
13 N 29 d 45 t 61 9
14 O 30 e 46 u 62 +
15 P 31 f 47 v 63 /

有時為了防止混淆(比如連結),會使用 . _ 來代替索引表中的 + /

編碼方式

base64 將 3 個位元組(24 位)作為一組進行處理。不足 3 位元組時填充 0,並在結尾使用 = 來標識填充的位元組數。並將每 6 位元作為 1 小組,將 24 位元編碼成 4 組 6 位元二進位。此時,這 6 位元二進位一共有 26=642^6=6426=64 種情況,正好能夠用 64 個字元來表示。(這也解釋了為什麼編碼完成後體積會增大 1/3)

舉些例子

隱寫的原理

base64 在解碼的時候,會按照字串末尾的 = 數量來刪除相應位元組數。或許你已經發現了,當一組字元的數量為 1 位元組或 2 位元組的時候,會有 4 位或 2 位二進位在解碼時被忽略,及下圖的紅色標識。

紅色標識的這些二進位,能夠被編碼,但解碼時卻會被忽略。修改這些位置的內容,不會影響到原始資料。

解決問題

現在,可以來嘗試解決文章開頭的問題了。那組 base64 編碼的字串,隱藏了什麼?

將所有紅色標識的二進位位拼接起來,可以得到最後的結果 hello

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。