對雜湊輸出進行編碼有什麼用?
在許多應用中,使用 MD5 算法產生 128 位輸出,表示為 32 位十六進制數字的序列。此輸出使用 base62 或 base64 方案進一步編碼。
我想了解進一步編碼雜湊值的需要。為什麼我們不能使用相同的雜湊值並將其儲存在我們的數據庫中?
這樣做是為了減少空間消耗嗎?
根據我的理解,MD5 雜湊輸出為 16 字節。當我們使用 base64 方案對其進行編碼並生成 8 個字元的長字元串時,它將是 8 個字節。
需要對雜湊值進行進一步編碼嗎?
**將雜湊表示為字元串,而不會過多地增加大小。**這稱為二進製到文本編碼。它通常用於加密數據(散列、密文……),因為它可以包含任意位序列(或任意字節的任意序列),並且某些數據通信、儲存或顯示裝置只能處理某些字母表中的字元。
這不應與將字元編碼為字節相混淆,因為需要散列或加密文本。我將使用RFC 1321 附錄 A.5中範例中給出的 26 個ASCII 字元消息的 MD5 散列進行解釋和範例:
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
雜湊不是32 個字元的序列
c3fcd3d76192e4007dfb496cca67e13b
。根據不同的觀點,它要麼是 16 個 8 位字節,要麼是一個 128 位序列(或位串),用0
(resp.1
) 表示位清晰 (resp. set) 是(通過 big- endian約定將字節轉換為位)¹ ):11000011111111001101001111010111011000011001001011100100000000000111110111111011010010010110110011001010011001111110000100111011
32 個字元的序列
c3fcd3d76192e4007dfb496cca67e13b
是每個小寫大端十六進制雜湊的表示。這是根據該程式碼 C 程式碼(來自 RFC)將該雜湊表示為 16個字節(或等效於 16個八位字節)獲得的:/* Prints a message digest in hexadecimal. */ static void MDPrint (digest) unsigned char digest[16]; { unsigned int i; for (i = 0; i < 16; i++) printf ("%02x", digest[i]); }
注意:在上面,
unsigned char
是一個字節,表示範圍內的整數$$ 0…255 $$對 8 位雜湊進行編碼。轉換為字元在printf
函式中,"%02x"
指定至少 2 個小寫十六進製字元。注意:每組 4 個字節是電腦字的小端表示,但這是 MD5 內部的考慮因素。
除了上述表示為 16 個字節和 32 個小寫(大端)十六進製字元之外,還有其他常見的表示,包括
C3FCD3D76192E4007DFB496CCA67E13B
: 32 個字元,大寫(大端)十六進制w/zT12GS5AB9+0lsymfhOw==
: 24 個字元,Base64 符合RFC 4648w_zT12GS5AB9-0lsymfhOw==
: 24 個字元,Base64 文件名安全字母w/zT12GS5AB9+0lsymfhOw
: 22 個字元,Base64 與填充抑制如果可以從文本(等效地,字元)編碼轉換回散列。同樣的十六進制解碼方法可以處理大寫和小寫。相同的 Base64 解碼方法可以處理常見的字母並使 pad 可選。
還有其他更不常用、有時更緊湊的二進製到文本編碼。請參閱此處了解為什麼 Base64 最受歡迎。
當我們使用 base64 方案編碼(一個 16 字節的 MD5 雜湊)並產生 8 字元長的字元串時,它將是 8 個字節。
不可以。每個 Base64 字元編碼 6 位(最後一個非填充字元可以編碼 2、4 或 6 位;最後一個填充字元(如果有)除外)。因此,根據 Base64 編碼,128 位散列至少需要 ⌈128/6⌉ = 22 個字元,如果有的話加上填充。
根據電腦語言和選項,上面的每個字元可能依次使用幾個字節。例如,C 字元串中的每個此類字元由 1 個字節表示,而在 Java 8 中則為
String
2 個字節(請參閱後續版本的註釋)。此外,每個對像都有大小成本,這可能是不可忽略的。
在 Python 字元串中,從 Python 3.3 版本左右開始,上述編碼中的每個字元預設使用 1 個字節。在以前的版本中,它使用 2 或 4,具體取決於 Python 環境;請參閱PEP 393。¹ MD5 使用 little-endian 約定將輸入字節轉換為 32 位字,然後再轉換回輸出字節,但使用 big-endian 約定在輸入位和字節之間進行轉換。因此,通過對稱性,我假設輸出字節和位之間的轉換採用大端約定。