Base58 解碼是將 58 個符號的比特幣風格字串轉回其原始位元組序列的可逆過程,作法是將每個字元對應到其數值索引,將結果視為一個 base-58 整數,然後把該整數改寫成 base 256。58 個字元來自一個刻意省略了四個符號的固定字母表,這四個符號是正常數字系統會包含的,這就是為什麼「比特幣地址」絕不會包含數字 0、大寫字母 O、大寫字母 I,或小寫字母 l。這些字元在字型和螢幕之間複製時,都太容易被誤認為其他東西,將它們移除後,編碼後的字串在手抄時才會清楚可讀。解碼是一種確定性的轉換:貼上有效的字串,每次都會得到相同的位元組序列,不涉及任何校驗和、金鑰或秘密。輸出純粹是二進位重建,這也是為什麼工具會先把結果顯示為小寫十六進位位元組,只有當位元組恰好形成有效文字時,才將 UTF-8 文字檢視作為便利選項提供。

比特幣 Base58 字母表及其刻意排除的字元
Base58 編碼與解碼所使用的比特幣字母表是一個由 58 個字元組成的單一字串:123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz。索引從 0 開始,因此數字 1 是字元 0、數字 2 是字元 1,依此類推到索引 8 的 9,接著是從索引 9 的 A 開始到 Z 的大寫字母(中間有跳號),再來是小寫字母。四個符號是刻意省略的:
| 被排除的字元 | 被移除的原因 | 容易混淆的對象 |
|---|---|---|
| 0(數字零) | 在許多等寬字型中看起來像大寫字母 O | O |
| O(大寫 O) | 看起來像數字 0 | 0 |
| I(大寫 I) | 看起來像數字 1 和小寫 l | 1、l |
| l(小寫 L) | 看起來像數字 1 和大寫 I | 1、I |
由於字母表是固定的且區分大小寫,一個有效的 Base58 字串只會出現 58 種可能的符號,不會有其他字元。空白、標點符號、四個被排除的字母,以及任何非 ASCII 字元,都會被嚴格的解碼器拒絕,而不會被靜默猜測、刪除或取代。這種嚴格性正是讓編碼能在終端機、聊天視窗和紙本列印之間安全複製的原因:任何不在字母表中的字元都會被視為錯誤,而不是線索。如需完整的字母表與其規則及前導零慣例的簡明參考,Base58 解碼速查表將相同內容彙整成一個可列印的表格。
解碼器如何還原原始位元組
在底層,解碼是編碼器進位轉換步驟的反向操作。解碼器從左到右逐一掃描輸入字串,在字母表中查找每個字元的數值索引,並使用 base-58 算術累加一個總和:total = total × 58 + index。整個字串處理完後,該總和就是原本編碼的整數。接著解碼器透過重複除法將該整數轉回 base 256,產生結果中非零的尾部位元組。
光這樣還不夠,因為整數算術沒有前導零的概念。為了還原前導零位元組,解碼器會計算 Base58 字串中前導 1 字元的數量。每個前導 1 對應到來源中的一個前導 0x00 位元組,因為編碼器會為輸入中第一個非零位元組之前出現的每個 0x00 位元組輸出一個 1。解碼器會在 base-256 轉換所產生的內容前面,加上該數量的零位元組,原始的位元組序列便會被精確地重建回來。
大整數部分與前導零之間的這種區隔,是大多數簡陋實作最容易出錯的地方,這也是為什麼一個嚴謹的解碼器會用固定的測試樣本來驗證其輸出,而不是依賴來回轉換的自洽性。Bitcoin Core 專案發布了一組官方的 base58_encode_decode 測試向量,涵蓋簡單的 ASCII、較長的片語、任意二進位內容,以及前導零的情境,這些測試向量會把字母表順序、數值轉換和前導零行為都鎖定下來。
如何逐步解碼 Base58 字串
Base58 編碼 / 解碼頁面會在瀏覽器本地執行完整轉換,並在可用時同時顯示十六進位位元組和 UTF-8 預覽。若要解碼現有的值:
- 將工具切換到 Base58 轉位元組與文字模式。
- 將原始的比特幣字母表字串完全照收到的樣子貼到輸入框中,保留大小寫,並省略所有空格、換行或周圍的標點符號。
- 執行解碼器。頁面會以小寫十六進位回傳還原的位元組,並在這些位元組構成有效的 UTF-8 時,一併顯示 UTF-8 文字詮釋。
- 請先閱讀十六進位,因為它是無損的表示方式。將它與您預期的格式比對,無論是地址承載資料、金鑰主體、雜湊摘要,或其他應用程式專屬的物件。
- 如果缺少文字詮釋,請將其視為該位元組序列並非文字。請勿把替代字元再貼回編碼器,因為這樣做會隱藏原本承載資料中刻意包含的位元組。
- 為了進行健全性檢查,請透過工具的編碼端將還原的十六進位重新編碼,並確認產生的 Base58 字串與您原本的輸入逐字元相符。
前導零、十六進位輸出,以及文字檢視消失的時機
成功解碼後,畫面上一定會出現兩個輸出:小寫十六進位位元組序列,以及在特定條件下才會出現的 UTF-8 文字檢視。十六進位檢視才是真相,因為 Base58 基本上是一種二進位編碼。文字檢視只有在那些位元組恰好代表可列印字元時,才作為便利選項存在。
當解碼出的位元組序列不是有效的 UTF-8 時,頁面會保留精確的十六進位輸出,但會顯示文字詮釋無法取得。這段訊息的意思就如同字面所述:結果中有位元組無法構成完整的 UTF-8 編碼單位,且工具不會靜默插入替代字元。在無效位元組的位置插入 U+FFFD 會讓結果看起來像是成功的來回轉換,卻同時悄悄改變了底層資料,這與除錯型解碼器的用途恰恰相反。
前導零的處理會直接反映在十六進位輸出中。如果原始字串以一個或多個 1 字元開頭,請預期十六進位的前端會有相同數量的 00 位元組。這點對版本化承載資料和比特幣風格識別碼等格式至關重要,因為這些格式的第一個位元組是版本標籤,若弄錯,即使其餘解碼看似合理,也會讓整個物件失效。
原始 Base58 與 Base58Check
有兩種共用相同字母表的相關編碼,其差異很容易被忽略。原始 Base58 就是前面描述的字母表轉換。Base58Check 是一層外殼,會在前面加上一個版本位元組,並在後面附加四個位元組的雙重 SHA-256 校驗和,再將整個合併後的承載資料進行 Base58 編碼。成功的原始 Base58 解碼只能證明位元組可以被還原;它無法證明版本位元組屬於允許的值,也無法驗證校驗和。
| 屬性 | 原始 Base58 | Base58Check |
|---|---|---|
| 字母表 | 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz | 相同的字母表 |
| 版本位元組 | 無,視為一般承載資料 | 一個位於前端、用來識別物件類型的位元組 |
| 校驗和 | 無 | 結尾處四個位元組的雙重 SHA-256 校驗和 |
| 乾淨解碼能證明什麼 | 僅能證明位元組可透過字母表往返轉換 | 單獨無法證明任何事;校驗和必須另外驗證 |
| 典型呼叫者 | 內部編碼、除錯、人工資料檢視 | 比特幣地址、WIF 金鑰、BIP-32 延伸金鑰 |
對於比特幣地址、WIF 私鑰和 BIP-32 延伸金鑰,請使用懂得版本位元組並能驗證校驗和的格式感知錢包或經審核的函式庫,例如獨立的Bitcoin libbase58 專案以取得參考行為。原始解碼器是用來檢視位元組本身的正確工具;它無法取代通訊協定層級的驗證。
為什麼 Base58 解碼有時會失敗
少數幾種模式就佔了大多數的解碼失敗原因,能辨識它們可以省下不少時間:
- 有被排除的字元混進字串中。輸入中的 0、O、I 或 l 幾乎一定是抄錄錯誤,因為這些字元都不存在於比特幣字母表。請從可信的來源重新複製該值。
- 為了可讀性而加入的空白或標點符號。引號、換行、群組之間的空格,以及結尾的逗號,在解碼前都必須先移除。
- 編碼類型錯誤。標示為 Base58 的值實際上可能是 Base58Check,它帶有一個原始解碼會忽略的四位元組校驗和。如果解碼後的位元組看起來像合理的承載資料,後面又接著四個看似隨機的位元組,那多出來的位元組很可能就是校驗和。
- 大小寫假設錯誤。字母表區分大小寫,因此 abc 和 ABC 解碼出來的數字完全不同。絕對不要在解碼前先正規化大小寫。
- 輸入超過瀏覽器的工作上限。解碼的運算量隨輸入長度呈二次方成長,工具會將解碼承載資料上限設為 4,096 位元組,以免在極端輸入下讓頁面卡住。對於更長的承載資料,請改用像 Base64 這類串流格式。
如果某個字串無法解碼,第一件事就是檢查字母表:不在 58 個符號集合內的字元(包括那四個被排除的字元)是最常見的原因。接著,請確認該值是否預期採用 Base58Check 處理方式,因為即使原始解碼成功,應用程式層級的物件仍可能無效。
如需更深入的探討,請參閱凱薩密碼解碼速查表:快速解碼位移。