開發者工具 · Base64 編碼器和解碼器
Base64 簡史:從 uuencode 和 PEM 到今天的字母表
· 背景
base64 編碼
Base64 的字母是 1980 年代運輸問題的化石記錄。這篇文章遵循從 uuencode 透過隱私增強郵件到 MIME 和 RFC 4648 的沿襲,並解釋了每個設計選擇。
為什麼字母不只是按某種明顯順序排列的 0–63 — 這個問題可以追溯到四十年前
Base64 並未完全形成標準。字母(A-Z、a-z、0-9、+、/) 是數十年編碼實驗的化石記錄,每個實驗都試圖解決相同的問題:如何將二進位資料表示為 1970 年代和 1980 年代電子郵件、USENET 和 Unix 工具中倖存的1993 中的 1421),1996 中的 MIME (RFC 2045),最後是 2006 中的 RFC 4648,合併了所有變體。
了解這段歷史可以解釋為什麼某些字元出現在字母表中以及為什麼 RFC 為實現者留下了某些選擇。 uuencode 是 Unix-to-Unix 編碼的縮寫,是第一個解決 Unix 上 7 位元傳輸問題的工具。它在 1980 中創建,將每個 3 位元組(24 位元)編碼為 64 字元字母中的 4 字元。 uuencode 字母是 ASCII 32(空格)到 ASCII 95(底線和其他標點符號),之所以選擇這些字元是因為這些字元可以在任何終端上列印。該儲存庫展示了目前實施的字母表,但它不包含有關誰選擇該順序或每個角色為何獲勝的檔案證據。因此,標題被縮小:可以準確地檢查當前的佈局,而動機和日期需要此處未包含的主要歷史文獻。
為什麼字母表看起來很歷史——這個儲存庫沒有記錄的邊界
然而,空格作為編碼字元是有問題的:文字編輯器和郵件系統會修剪尾隨空格,從而損壞輸出。字母表並不理想,但對於 Unix 到 Unix 檔案傳輸來說它已經足夠好了。隱私增強郵件(RFC 1421、1992)是標準化加密電子郵件的早期嘗試。它包含自己的 Base64 編碼(RFC 1341,用於 MIME,RFC 1421 早於規範,但在採用方面滯後)。
RFC 1421 Base64 使用字母 A-Z、a-z、0-9、+、/(現代 Base64 字母),並在 64 字元處換行。這個字母表避免了空格和其他有問題的字元;每個字元都可以明確列印,並不會與控制代碼或國家字元集變體混淆。 64 字元行長度與 20 世紀 80 年代紙質終端的寬度相匹配,是可讀性的實際折衷方案。 Uuencode 屬於周圍的歷史,但該工具既不讀取也不寫入其字母表。將其視為可互換的 Base64 將是一個格式錯誤。這裡有用的比較僅限於用可列印字元表示位元組的共同問題。
早期編碼作為上下文,而不是實現證據
RFC 1421 沒有被加密電子郵件廣泛採用,但其 Base64 字母表保留了下來。 MIME(多用途互聯網郵件擴充、RFC 2045、1996)採用了 RFC 1421 Base64 字母表,但將換行從 64 更改為 76 字元。原因不是技術性的,而是歷史性的:PEM(隱私增強郵件)區塊是 64 字符,MIME 選擇了稍微不同的限制,以避免在自動解析中與 PEM 混淆。
MIME Base64 成為電子郵件附件的標準,並是當今使用最廣泛的 Base64 變體。 RFC 2045 也定義了其他內容傳輸編碼值(7 位元、8 位元、可引用列印),為郵件系統提供基於內容類型的選項。字母選擇避免了 ASCII 和 EBCDIC(IBM 大型機字元編碼)之間不同的字元。字元 A-Z、a-z、0-9、+ 和 / 在兩種編碼中相同。 PEM 樣式的塊是可識別的,因為標籤圍繞著包裹的編碼材料。 ToolAcre 可以在刪除這些標籤後處理擷取的 Base64 正文。它無法確定哪個檔案規範首先使用給定的約定,並本文並不假裝原始碼樹回答了該問題。
PEM 式裝甲作為現代可觀察格式,無需宣告起源故事
開括號和閉括號等字元在 ASCII 和 EBCDIC 之間有所不同,因此被排除在外。這在 20 世紀 80 年代和 90 年代初非常重要,當時大型主機到 Unix 的資料傳輸很常見。字母表還避免了反斜線、單引號和雙引號,這些在 C 字串和 shell 語法中具有特殊含義。 Base64 字串可以嵌入到 C 程式或 shell 腳本中,而無需轉義幾乎每個字元。
RFC 3548 (2006) 合併 Base64、base32 和 base16 編碼。它指出,MIME、PEM 和其他應用程式都使用類似的概念,但具有不同的填充規則和字母。 RFC 4648(2006,與 RFC 3548 一起發布)是當前標準,它定義了五個編碼系列,每個系列都有測試向量。 RFC 也記錄了歷史:哪些檔案定義了哪些編碼、版本之間發生了什麼變化以及做出選擇的原因。編碼器的 76 字元換行選項和解碼器的空白刪除可讓 MIME 形狀的樣本測試。這些實施事實並不能證明郵件標準的完整歷史。它們展示了讀者可以直接在面板和測試中重現的現代相容性行為。
MIME 樣式包裝作為編碼器選項,無需重建標準歷史記錄
大多數開發人員在 RFC 4648 中只遇到 base64 和 base64url;為需要實作舊變體的人記錄了歷史記錄。 Base64url(RFC 4648 部分 5)將加號替換為破折號,將斜杠替換為下劃線,以避免 URL 保留字元。包含 + 和 / 的 Base64 字串必須在 URL 中進行百分比編碼(%2B 和 %2F); base64url 避免了這種情況。
JWT (JSON Web Token) 使用不含填充的 base64url。某些應用程式使用帶有填充的 base64url。 RFC 定義了這兩種變體;這取決於應用程式的選擇。這種差異就是為什麼 JWT 解碼器和電子郵件 Base64 解碼器可能會為相同的輸入字串產生不同的輸出(一個期望是 base64url,另一個期望是 base64)。字母表、填充規則和換行都是從真實系統的實際約束中產生的。可移植性最好被視為對傳輸字母表的限制,而不是每個符號的經過驗證的傳記。在常見文字系統中,字母和數字在視覺上保持熟悉,而最終標點符號在 URL 安全模式中有所不同。在沒有主要證據的情況下,省略了確切的歷史選擇理由。
可移植性作為設計約束,而不是單一角色選擇的驗證說明
選擇 64 字元集是為了跨編碼的可表示性;字母由 RFC 1341 和 1421 以及 MIME 固定;填充規則來自 3 位元組對齊;換行來自電子郵件傳輸限制。忽略此歷史的實現可能會發明新的編碼或忘記邊緣情況。 RFC 4648 測試向量(foobar 產生 Zm9vYmFy)是驗證實作是否符合標準的方法。
現代替代品如 base85(在某些情況下使用)存在,但由於歷史勢頭且足夠好,base64 仍然占主導地位。 Base64 不是最緊湊的編碼(base85 和 base91 更密集),但它簡單、通用且經過驗證。可以肯定地說的是目前的這對字母:標準結尾為加號和斜線; URL 安全替代連字符和底線。填充和包裹是單獨的選項。測試涵蓋模式和缺失填充,為當前行為提供可重複的證據,而不是推斷的時間順序。
儲存庫證明了目前標準和 URL 安全字母表的內容
33 百分比大小開銷對於大多數用途來說是可以接受的。字母表在各個實現中都是穩定的。 RFC 非常清楚,偏差通常是故意的(例如填充省略或空白處理),而不是偶然的誤解。
了解 Base64 歷史可以解釋為什麼它看起來是這樣的。加號和斜線字元是經過深思熟慮的選擇,以避免不同字元編碼中的歧義。填充規則來自 3 位元組分組。 Base85 和 Ascii85 使用不同的群組大小和字母表,並不在實現範圍內。提及他們並不會使本頁面成為他們的轉換器。比較它們的密度或歷史記錄需要超出為此模組審核的 Base64 檔案之外的來源和測試向量。
重點:每個字元的選擇都是有原因的 — Base64 編碼器和解碼器如何實現由此產生的標準字母表
換行來自電子郵件。每個決定都是為了解決真實系統的實際問題。如今,Base64 主要用於歷史記錄無關緊要的上下文(JWT、API、資料 URI),但字母和填充規則是透過 RFC 4648 從 MIME 和 PEM 繼承的。
讀取一次 RFC 並在 Base64 編碼器和解碼器工具中編碼測試字串,將目前標準與其歷史根源連結起來。只要輸入達到索引 62 或 63,產生的標準字母就可見。使用產生這些位置的範例,切換 URL 安全模式,並僅比較已變更的標點符號。該實驗展示了當今的格式,而不依賴關於其發明的未經證實的故事。