轉載自:
http://liuzhigong.blog.163.com/blog/static/178272375201121281922865/
網絡傳輸——Base64詳解
自從引用以來,Base64編碼的標準極普及爲的迅速。不過,把文件作爲附件通過網際郵件擴充協議(MIME)傳送時,Base64是標準的編碼標準。然而,幾乎所有的電子郵件客戶端都是用MIME發送文件(以附件形式)的,這就意味着大多數的電子郵件客戶端使用Base64對文件編碼後通過網絡傳輸。格式如下:
Content-Transfer-Encoding:base64( Gb2312)
這種傳輸格式又被稱爲U-t-U(Unix to Unix)傳輸協議,能兼容大多數的硬件設備並基於其上進行無損字節傳輸。但是缺點在於是,使用此種格式會使文件的大小增加百分之四十左右。
除了作爲MIME的默認編碼標準,base64編碼也廣泛用於其他領域。一個常見的例子是用於網絡服務器完成基於HTTP的基本認證。當服務器想限制訪問某些文件時,通過使用基於HTTP的基本認證系統,便可以對這些文件進行密碼保護。而基本認證使用Base64編碼標準對用戶名和密碼進行編碼。這樣,黑客們使用TCP通過端口連接ESMTP服務器時,手動輸入量就會大大增加。
儘管Base64編碼受到廣泛的支持和應用,但卻是當今最弱的編碼標準之一,通過以下步驟就可以輕易地進行逆向工程。不僅僅是算法上的容易逆向,因爲在網絡上Base64用純文本形式發送密碼,使得Base64加密文本很容易受到sniffer程序的嗅探。
編碼程序如下:
1、 將要加密的文本的每個字符轉換成標準的ASCII十進制碼。
2、 通過任何一種方式(手算、機器算、對照表格)將這部分十進制編碼轉換成二進制(文章最後附有轉換表)編碼。每個十進制碼都對應器等價的八位二進制數值。
3、 將這部分二進制數連結到一起,產生一串二進制數。
4、 將這一大片的二進制字符串分割成每6個字符爲一部分的小塊。
5、 通過任何一種方式(手算、機器算、對照表格)將這部分6字符的小塊分別轉換成相應的等價十進制數。
6、 通過Base64錶轉換成Base64編碼。
Base64編碼轉換表如下:
十進制 |
編碼 |
十進制 |
編碼 |
十進制 |
編碼 |
十進制 |
編碼 |
||
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 |
/ |
||
例如:mne,通過ASCII字符錶轉化爲是進制值爲:m、109,n,110,e、101.合起來就是:109110101.轉化爲二進制就是:0110 1101 0110 1110 0110 0101。將它們分成六個字爲一段:011011 010110 111001 100101。而他們對應的十進制字符分別是:27 22 57 37。Base64等價值就是:27、b,22、w,57、5,37、1,也就是說mne的Base64編碼是bw51。
需要注意的是:如果被加密的字符串每3個一組,還剩1或2個字符,使用特殊字符“=”補齊Base64成爲4個字。
知道了加密方式,要逆向就很簡單了。將對應的Base64值轉換爲十進制,再通過計算轉換成二進制編碼。將這一串碼分爲8位1組,得到十進制碼,最後再等價到相應的ASCII編碼即可。
附1:ASCII編碼表(部分)
二進制 |
十進制 |
十六進制 |
縮寫/字符 |
解釋 |
0000 0000 |
0 |
00 |
NUL (null) |
空字符 |
0000 0001 |
1 |
01 |
SOH (start of handing) |
標題開始 |
0000 0010 |
2 |
02 |
STX (start of text) |
正文開始 |
0000 0011 |
3 |
03 |
ETX (end of text) |
正文結束 |
0000 0100 |
4 |
04 |
EOT (end of transmission) |
傳輸結束 |
0000 0101 |
5 |
05 |
ENQ (enquiry) |
請求 |
0000 0110 |
6 |
06 |
ACK (acknowledge) |
收到通知 |
0000 0111 |
7 |
07 |
BEL (bell) |
響鈴 |
0000 1000 |
8 |
08 |
BS (backspace) |
退格 |
0000 1001 |
9 |
09 |
HT (horizontal tab) |
水平製表符 |
0000 1010 |
10 |
0A |
LF (NL line feed, new line) |
換行鍵 |
0000 1011 |
11 |
0B |
VT (vertical tab) |
垂直製表符 |
0000 1100 |
12 |
0C |
FF (NP form feed, new page) |
換頁鍵 |
0000 1101 |
13 |
0D |
CR (carriage return) |
回車鍵 |
0000 1110 |
14 |
0E |
SO (shift out) |
不用切換 |
0000 1111 |
15 |
0F |
SI (shift in) |
啓用切換 |
0001 0000 |
16 |
10 |
DLE (data link escape) |
數據鏈路轉義 |
0001 0001 |
17 |
11 |
DC1 (device control 1) |
設備控制1 |
0001 0010 |
18 |
12 |
DC2 (device control 2) |
設備控制2 |
0001 0011 |
19 |
13 |
DC3 (device control 3) |
設備控制3 |
0001 0100 |
20 |
14 |
DC4 (device control 4) |
設備控制4 |
0001 0101 |
21 |
15 |
NAK (negative acknowledge) |
拒絕接收 |
0001 0110 |
22 |
16 |
SYN (synchronous idle) |
同步空閒 |
0001 0111 |
23 |
17 |
ETB (end of trans. block) |
傳輸塊結束 |
0001 1000 |
24 |
18 |
CAN (cancel) |
取消 |
0001 1001 |
25 |
19 |
EM (end of medium) |
介質中斷 |
0001 1010 |
26 |
1A |
SUB (substitute) |
替補 |
0001 1011 |
27 |
1B |
ESC (escape) |
溢出 |
0001 1100 |
28 |
1C |
FS (file separator) |
文件分割符 |
0001 1101 |
29 |
1D |
GS (group separator) |
分組符 |
0001 1110 |
30 |
1E |
RS (record separator) |
記錄分離符 |
0001 1111 |
31 |
1F |
US (unit separator) |
單元分隔符 |
附2:下列Perl腳本將會自動幫你做解密:
Use MIME::Base64;
Print decode_base64(“Insert Text here”);
附3:使用Java腳本實現解密(代碼):
<script type="text/javascript">
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
function base64Encode(str) {
var out, i, len;
var c1, c2, c3;
len = str.length;
i = 0;
out = "";
while(i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if(i == len)
{
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += base64EncodeChars.charAt(c1 >> 2);
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
out += base64EncodeChars.charAt(c3 & 0x3F);
}
return out;
}
function base64Decode(str) {
var c1, c2, c3, c4;
var i, len, out;
len = str.length;
i = 0;
out = "";
while(i < len) {
/* c1 */
do {
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c1 == -1);
if(c1 == -1)
break;
/* c2 */
do {
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
} while(i < len && c2 == -1);
if(c2 == -1)
break;
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
/* c3 */
do {
c3 = str.charCodeAt(i++) & 0xff;
if(c3 == 61)
return out;
c3 = base64DecodeChars[c3];
} while(i < len && c3 == -1);
if(c3 == -1)
break;
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
/* c4 */
do {
c4 = str.charCodeAt(i++) & 0xff;
if(c4 == 61)
return out;
c4 = base64DecodeChars[c4];
} while(i < len && c4 == -1);
if(c4 == -1)
break;
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
}
return out;
}
alert("原文:"+sTemp+"\n加密:"+base64Encode(sTemp)+"\n解密:"+base64Decode(base64Encode(sTemp)));
alert("原文:"+sTemp+"\n加密:"+base64Encode(sTemp)+"\n解密:"+base64Decode(base64Encode(sTemp)));
</script>