首頁>技術>

摘要

Base 編碼那麼多,都是用來幹什麼的?

目錄Base 編碼的歷史為什麼需要 Base58Base58 的特點小結

Base Encoding 是一組二進位制轉文字的編碼模式(Encoding Scheme),常見的有 Base64、Base58、Base32、Base16。大家不僅疑惑為什麼需要二進位制轉文字這種編碼模式呢?常見誤解之一就是既然所有的編碼最終都會變成 0 和 1,那麼分成 ASCII 和 Base64 編碼是不是就沒有必要呢?

Base 編碼的歷史

1970~1980 年代,DEC(和其他公司)生產的“微型計算機”使用的字元編碼為 ASCII。 每個位元組使用 7 位,給出 128 個可用值。 這足以滿足大寫和小寫拉丁字母,數字,標點,一些常見的數學符號,貨幣符號和控制字元的需要。此後 ASCII 變得非常流行,並在很長一段時間內占主導地位。ASCII 規定了範圍在 [0,127] 之間的字元編碼,其中 [0, 31] 以及 127 (del) 這 33 個屬於不可列印的控制字元(可以使用 man ascii 查證)。網際網路的殺手級應用——電子郵件系統當初是為了傳輸 7 位 ASCII 文字而設計的,於是在傳輸資訊時,有些郵件閘道器會把 [0,31] 這些控制字元給清除,而有些會替換 10 (newline 或 \n)和 13 (carrige 或 \r) 字元,有些更加粗暴地將二進位制的最高位清空,還有的程式在收到 [128, 255 ] 之間的國際字元會發生錯誤。

如何在不同郵件閘道器之間安全地傳輸控制字元、國際字元和二進位制檔案呢?作為 MIME(RFC 2045 和 RFC 3548)多媒體電子郵件標準的一部分的 Base64 編碼就被開發出來了。

Base64 編碼的解題思路很簡單。既然直接傳輸控制字元、國際字元和二進位制檔案容易造成原始資訊在傳遞過程中的錯誤,那麼就把原始資訊都轉成 ASCII 的可列印字元,這樣就能讓舊系統安分點,不再胡亂改變其內容。

Base64 是怎麼做的呢?它的核心演算法是將每 3 個位元組(3 * 8 = 24 位元)依次轉換成 4 個可列印字元(4 * log 64 = 24 位元)。具體操作如下:

將 3 位元組的資料,先後放入一個 24 位的緩衝區中,先來的位元組佔高位。資料不足 3 位元組的話,緩衝器中剩下的位元用 0 補足。每次取出 6 位元,按照其值選擇 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 中的字元作為編碼後的輸出,直到全部輸入資料轉換完成。若原資料長度不是 3 的倍數時且剩下 1 個輸入資料,則在編碼結果後加 2 個 =;若剩下 2 個輸入資料,則在編碼結果後加1個 =。用來代表補足的位元組數。

我們以換行字元(ASCII 碼 10)為例,原始的二進位制表示如下

10的二進位制表示是 0000 1010,放到 24 位的緩衝區補零為 00001010 00000000 00000000每次取 6 位元,則如右邊劃分所示:000010 100000 000000 000000。因為後兩部分為補零,適用於規則 3。前兩部分的十進位制依次是 2, 32,所以透過索引表選擇的值是 C, g後兩部分是補零,所以替換成=。故結果為 Cg==為什麼需要 Base58?

首先,Base58 和 Base64 一樣都是一組二進位制轉文字(binary-to-text)的編碼模式。Base58 的主要職責是將大整數表現成文字,它是由中本聰在 Bitcoin 中首先引入進來的。為什麼要這樣使用呢?有如下幾個原因:

https://en.bitcoin.it/wiki/Base58Check_encoding#Background

// Why base-58 instead of standard base-64 encoding?// - Don't want 0OIl characters that look the same in some fonts and//      could be used to create visually identical looking account numbers.// - A string with non-alphanumeric characters is not as easily accepted as an account number.// - E-mail usually won't line-break if there's no punctuation to break at.// - Doubleclicking selects the whole number as one word if it's all alphanumeric.
去掉了 Base64 中的長相相近的字元,這樣直觀上就能分辨賬戶數字,如:0(零)和O(大寫 o),I(大寫 i)和 l(小寫l),以及 + 和 / (non-alphanumeric 非字母和數字組成的),共 6 個字元。這也是 Base58 名稱的由來,因為 64 - 6 = 58非字母和數字的字元就不太容易混入賬戶地址裡在郵件裡沒有標點就不會斷行(意在排除截斷的可能性)雙擊就能全部選中所有字元和數字的串

順帶一提,Base56 相較於 Base58,少了 1(一)和 o(小寫 o)這兩個字元,而 Base32 則只包含 A-Z 和 2-7 這 32 個字母和數字。

Base58 的特點

維基百科上說,Base58 不太適合編碼二進位制資料,而適合編碼大整數?在探討 Base58 的實現原理之前,我們先看看比較常見的幾種 Base 編碼。

Base16

有人可能會說 Base16 我沒有用過,怎麼能說常見呢?乍看這個名字還挺唬人的,但其實它就是 Hexidecimal 十六進位制編碼。對於 10101010,會被編碼成 0xAA。拆解來看,1010 是十進位制的 10,也就等於十六進位制中的 A。原因是十六進位制只能表示 0-9 以及 A-F 這16個數,16 換成二進位制的範圍就是 0000 - 1111。

Base32

那麼 Base 32 這種編碼呢?同理,它可以表達的二進位制範圍是 00000 - 11111 也即 2 的 5 次方,即 32 個數。但問題是二進位制都是 8 位起,8 是沒法整除 5 的。既然 8 除以 5 除不盡,那我們就找 8 和 5 的最小公倍數,即 40。換句話說,5 bytes = 8 chars。也就是說,我們需要將每 5 個位元組轉化成 8 個Base32 中的位元組。

由此,我們可以總結出一些規律。Base16 這種編碼方式,8 和 4 的最小公倍數是 8,所以 1 bytes = 2 chars,每次都能將一個位元組轉化成 2 個字元,都能剛好對齊。而 Base32 這種編碼方式,因為 8 和 5 的最小公倍數是 40,所以 5 bytes = 4 chars,存在對齊不了情況,那麼非 5 位元組倍數的位元組序列就需要額外補齊,同理, Base58 和 Base64 也需要如此。

Base58

繼續深入之前,我們先回憶一下中學學習的短除法求解二進位制。以 10 為例,計算如下:

圖1 短除法計算十進位制轉二進位制

短除法的實質是連除進位制,降低位權,依次得到各位上的數值。我們不妨以十進位制的 111 舉例。

圖2 短除法計算十進位制數各位上的數值

雖然上面的計算純屬畫蛇添足,不過它對於理解二進位制的短除法還是很有幫助的。我們第一次用 111/10,得到的餘數為1,便是個位上的數;再次用 11/10,得到的餘數為1,便是十位上的數;最後用 1/10 得到的餘數為 1,就是百位上的數。類比可得,上例中計算 10 這個數字的二進位制時,第一次用 10/2,得到的餘數 0 便是最低位上的數,得到的商為 5,則是 10 這個數的二進位制 1010 的高三位(101),依次類推即可得到不同數位上的二進位制數了。所以這樣就不難理解短除法有效性的來源。

我們再來看看 Base58 這種編碼方式,它有 58 個字元,所以可以表示的二進位制範圍是 000000 - 111001。因此,Base58 編碼演算法需要除法運算實現,如果被編碼的資料較長,則要用特殊的類來處理大數,在 Bitcoin 使用了 OpenSSL 中的 BIGNUM。

虛擬碼 - Base58 利用短除法編碼的過程
code_string = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";x = convert_bytes_to_big_integer(hash_result);output_string = "";while(x > 0){    (x, remainder) = divide(x, 58);    output_string.append(code_string[remainder]);}repeat(number_of_leading_zero_bytes_in_hash){    output_string.append(code_string[0]);}output_string.reverse();
小結

Base64 用於編碼郵件內容、網頁圖片,意在減少傳輸過程中可能出現的錯誤;Base58 是比特幣地址使用的編碼方法,旨在提高地址的辨識度;Base32 用在一些對大小寫不敏感的檔案系統中。每種 Base-x 的編碼都有適合它們的應用場景。自然,為應對需要我們也可以發明自己的 Base 編碼。

15
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Oracle 資料庫設定密碼永不過期