繁體中文

開發者工具 · Base64 編碼器和解碼器

Base64 填入解釋:= 符號的意思以及何時需要它們

· 工作原理

base64 編碼 開發人員工作流程

Base64 輸出顯示填滿區塊和等號
原始 ToolAcre 向量圖

Base64 字串末尾的 = 不是裝飾:它記錄最後一組短了多少位元組。這篇文章解釋了算術,為什麼有些字串沒有,以及為什麼解碼器不同意缺少填充。

看起來不錯的令牌中的「填充不正確」異常 - 解碼失敗及其後面的一兩個缺失字符

當 Base64 解碼器報告不正確的填充時,字串看起來完整,但帶有結構錯誤。等號不是裝飾性的:每個等號都編碼最後一組短了多少字節,使解碼器能夠準確地知道實際資料何時結束。理解這些 = 符號——以及為什麼嚴格的解碼器會拒絕沒有它們的字串——將一個神秘的錯誤轉化為可預測的算術。 JWT 區段可能有一個 =、沒有或兩個。 API 回應可能會乾淨地結束而無需填充。

這些代表有意的選擇,而不是實現變體。解碼過程不需要機械填充。填充的存在是為了使輸出明確:僅給出一個沒有有關長度的元資料的 Base64 字串,解碼器讀取填充並確切地知道資料結束的位置。 Base64 將三個位元組編碼為四個字元。三個位元組是 24 位元,完美地重新組合成四個 6 位元索引;每個選擇 64 Base64 符號之一。當輸入不是三的倍數時,編碼器面臨剩餘:一個或兩個位元組不能被三整除。

三個位元組,四個字元區塊 — 為什麼輸入長度模 3 決定是否出現零、一個或兩個 = 符號

編碼器透過將位移入第一個索引來填入這些群組,使最終值為零。為了標記這個意圖,它附加了 = 符號:零表示完整的組,一表示兩個位元組的結尾,兩個表示一位元組的結尾。演演算法是確定性的:知道輸入長度(以位元組為單位)可以讓您立即計算填充。一個位元組產生兩個 Base64 字元加上兩個 =。兩個位元組產生三個字元加上一個=。三個位元組產生四個沒有填充的位元組。

任何不是三位元組倍數的輸入都會有填;任何一個倍數都不會。這不是選擇——這是算術。沒有填充的字串必須表示三個位元組。一個等於 1 的字串必須代表 2。填充對輸入長度模三進行編碼。檢查三個輸入的變換:單一 a、對 ab、三重 abc。 ASCII a 是位元組 0x61; Base64 將其編碼為 0x61 00 00,重新分組為六位元組。

填充位包含什麼以及為什麼嚴格的解碼器會檢查它們 - 必須為零的位元以及規範編碼的含義

索引 24、4、0、0 對應到 Y、E、A、A。因為兩個組進行了填充,所以編碼器附加兩個 = 符號,產生 YQ==。對於 ab,位元組 0x61 0x62 變成 0x61 0x62 00。位元重新組合為索引 24、22、8、0,輸出 YWI=。對於 abc,位元組重新組合為索引 24、22、9、35,輸出 YWJj,無填充。填充不是任意的:它不符合位元佈局。當您解碼 Base64 字串時,解碼器會讀取每個字符,尋找其六位索引,將位元打包為位元組。

對於 YQ==,字元 Y、E、A、A 解壓縮為位元。重新組合成八位元組得到一個位元組,0x61。解碼器丟棄填充位(尾隨零)並報告一個位元組。嚴格的解碼器檢查填充位實際上為零;如果不是,則輸入不規範,這意味著有人使用不同的位元佈局進行編碼,並解碼是不明確的。完全省略填充的系統會做出有意的權衡。 JWT 段使用 Base64url 而不進行填充,依賴消費者了解預期輸出長度或推斷它。

工作範例:手動編碼 'a'、'ab' 和 'abc' — 三個輸入、三個填滿結果,逐位顯示

RFC 4648 允許填充不存在,但指示解碼器接受它(如果存在)。程式碼庫有所不同:有些會恢復丟失的填充並繼續;有些會恢復丟失的填充並繼續;其他人會失敗。當您遇到解碼失敗的標記時,附加正確數量的 = 符號通常可以修復它。必需的 = 符號始終為零、一或二,取決於字串長度模四。如果 Base64 字串長度不是四的倍數,則填充肯定會丟失或損壞。

長度 5 不能是有效的 Base64:每個完整字元編碼六位,因此四個字元編碼 24 位(三個位元組),五個字元編碼 30 位,它不是八的倍數,不能成為位元組。解碼器必須拒絕此操作或添加填充。如果長度為 2 模 4,則加入兩個 =。若 3 對 4 取模,則加一 =。如果 0 對 4 取模,則不加入任何內容。長度為 3 的字串缺少它需要的 = ;加一,解碼前生效。

為什麼有些系統完全刪除填充 — JWT 段和省略 = 的 URL 安全標記以及如何從長度恢復它

如果填滿留在原處,連接兩個填滿的 Base64 字串會損壞。連接的兩個單獨的編碼直接產生雜散填充字符,從而破壞解碼字母表。這就是為什麼某些系統在連接之前去除填充的原因:由三個點連接的 Base64url 段組成的令牌在段內沒有填充,從而使連接變得簡單。如果從各個部分建立 Base64 值,請在任何操作之前驗證每個部分是否已填充並一致地剝離或添加填充。

Base64 編碼器和解碼器應用 RFC 4648,預設需要填入。當您輸入文字並要求 Base64 輸出時,工具會產生填充結果:規格形式。如果您看到沒有填充的 Base64 並想要對其進行解碼,請檢查您的解碼器是否接受缺少填充。該工具接受填充和未填充的輸入,並正確恢復原始位元組。為了進行調試,對長度模四進行計數會告訴您填充是否被剝離,並公式會告訴您應該存在什麼填充。

常見錯誤:修剪 = 就好像它是空格一樣,或連接兩個填滿的字串 - 每個字串如何破壞解碼

Base32 和 Base16(十六進位)在 RFC 4648 部分 6 和 7 中定義了不同的填滿規則。 Base32 使用 =,但最終群組可以是 2、4、5、7 或 8 字符,取決於輸入長度五。十六進制不需要填充;它總是將一個位元組映射到兩個字符,沒有餘數。 MIME Base64 換行涉及填入:76 列換行的字串在最後幾行仍然有填入。

了解 Base64 的填充就是了解位元佈局和輸入長度模三;一旦你看到算術,填充就成為一個直接的結果,而不是一個需要記住的規則。填充是可匯出的,而不是神奇的。

這不包括什麼 - base32 和 base16 填入規則,以及 MIME 行長度約定

給定任意長度的 Base64 字串,您可以將字元數除以四、取餘數並附加對應數量的 = 符號來恢復規範的填充形式。這就是為什麼缺少 = 是可以修復的,也是為什麼嚴格的解碼器可以寬容的原因:填充攜帶訊息(您的輸入屬於三種情況的哪個分支),但該資訊可以僅根據長度來計算。

Base64 編碼器和解碼器立即顯示填滿輸出,以便您可以將解碼後的位元組與原始文字進行比較並驗證往返是否有效。 Base64 和相關編碼擴展了將位元重新分組為不同字元寬度的原理。 RFC 4648 指定了這三者,理解其中之一會讓其他概念在概念上變得簡單。關鍵的見解是編碼是純粹的位元操作:選擇字母大小,相應地對位元進行分組,在表中尋找每個組。

重點:填充是可推導的,因此缺少的 = 是可以修復的 — Base64 編碼器和解碼器如何向您顯示您編碼的任何文字的填充規範形式

解碼相反:查找每個字符,提取位,重新組合它們,寫入字節。這種確定性的雙向映射就是 Base64 在所有平台和語言上可靠運作的原因。編碼和解碼中的錯誤通常歸因於對填充或字母差異的誤解。如果解碼因填滿錯誤而失敗,請檢查解碼器是否需要規範的 Base64(嚴格填充)或接受變體。如果因字元錯誤而失敗,請檢查輸入是否為 base64url 以及解碼器是否需要標準 Base64。

Base64 編碼器和解碼器接受字母並一致地驗證填充,因此可以立即驗證任何手動計算的範例。透過解碼回來測試編碼是在錯誤導致生產問題之前發現錯誤的最可靠方法。