繁體中文

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

Base64 與 base64url:為什麼標準解碼器拒絕 - 和 _

· 工作原理

base64 編碼 開發人員工作流程

Base64 字母與 base64url 替換
原始 ToolAcre 向量圖

base64url 將 + 和 / 交換為 - 和 _,因此輸出可以在 URL 和檔案名稱中傳輸而無需轉義。這篇文章解釋了這兩個字母、如何在它們之間進行轉換以及為什麼通常也會刪除填充。

解碼除您的程式碼之外的所有位置的令牌 - 由單一 - 或 _ 引起的無效字元錯誤

JWT 段無法在標準 Base64 解碼器中解碼,並出現無效字元錯誤命名破折號。但從視覺上看,沒有出現破折號。再看看——確實如此。 base64url 版本使用 - 其中標準 Base64 使用 +,而 _ 使用 /. 許多解碼器僅接受一種字母表,並為 URL 安全編碼的令牌將被期望 RFC 4648 標準 Base64 的代碼拒絕。

這兩個字母是等效的;它們之間的轉換是機械的字元替換。出現問題的原因是 + 和 / 在 URL 中具有意義。加號表示 application/x-www-form-urlencoded 表單資料中的空格。正斜線是 URL 中的路徑分隔符號。如果您將 Base64 直接嵌入到 URL 查詢參數中而不進行百分比編碼 + 和 /, 解碼器可能會誤解它們。

為什麼 + 和 / 是 URL 和檔案名稱中的問題 — / 在路徑中的保留含義以及 + 在表單資料中作為空格的保留含義

+ 在到達解碼器之前可以被讀取為空格。 / 可能會在錯誤的位置分割參數值。 RFC 4648 部分 5 定義了 base64url 字母以消除歧義:使用 - 代替 +,使用 _ 代替 /,,因此 URL 和檔案名稱中的輸出是安全的。除了兩個字元之外,這兩個字母是相同的。

標準 Base64 在位置 62 和 63 使用字元:A–Z (0–25)、a–z (26–51)、0–9 (52–61)、+ (62)、/ (63)。 base64url 使用 A–Z (0–25)、a–z (26–51)、0–9 (52–61)、- (62)、_ (63)。其他一切——位元重組、填充規則、將位元映射到索引——都是相同的。標準 Base64 的索引字串將產生 Base64url 的索引字串;只有位置 62 和 63 處的字元會有所不同。

RFC 4648 部分 5 中的 base64url 字母 — 兩個替換字元以及為什麼沒有其他變化

如果輸入不包含索引 62 或 63 (標準中沒有 + 或 /,base64url 中沒有 - 或 _),則兩個字母會產生相同的輸出。將標準 Base64 轉換為 base64url 是簡單的查找和替換:將 + 替換為 - 並將 / 替換為 _。解碼標準 Base64 中的 base64url 字串需要反向:交換 - 為 + 和 _ 為 /.

轉換是對稱的並始終有效。如果您遇到令牌解碼失敗並出現無效字元錯誤命名 - 或 _,請檢查解碼器是否接受 base64url。如果不是,則應用字元替換,如果輸入格式正確,則解碼應該成功。考慮 JWT 標頭 {"alg":"HS256","typ":"JWT"} 編碼為 base64url。標準 UTF-8 位元組經過位元重組:三個位元組變成四個索引,在 base64url 字母中尋找。 ToolAcre 將填充公開為編碼器選擇,而不是將其綁定到字母表切換。這種分離是有用的證據:URL 安全輸出可以被填充或不填充,而解碼器在呼叫瀏覽器原語之前規範化任一形式。字母和填充是相關的約定,而不是一個開關。

按照慣例,base64url 中的填充是可選的 — 為什麼 JWT 省略 = 以及解碼器如何從長度恢復它

當索引為62時,輸出字元為-;當 63 時,輸出為 _。標準字母表中的相同位元組將在索引 62 處產生 +,並在索引 63 處產生 /。將 base64url 結果轉換為標準是逐字操作:掃描 - 並替換為 +,掃描 _ 並替換為 /,,然後照常解碼。

您恢復的位元組是相同的,因為索引是相同的;只是符號不同。按照慣例,base64url 中的填充是可選的,即使標準允許這樣做。 JWT 的結構為三個由點連接的 base64url 段;如果需要,每個段都會使用填充,但許多實作會忽略它並依賴消費應用程式知道預期位元組長度的事實。

工作範例:將 JWT 標頭段轉換為標準 Base64 — 取代字元、新增填色、解碼為 JSON

解碼器可以透過將字串長度除以四、計算餘數、附加 0、1 或 2 等號來恢復遺失的填充。如果字串長度不是四的倍數,則明顯缺少填充。如果長度是四的倍數,則字串要么被填充,然後刪除填充,要么輸入已經是四個位元組的倍數(在最終區塊中以三個位元組結束,不需要填充)。

連接 base64url 區段需要注意填充。如果三個段落都以 = 結尾,則連接直接產生類似 AAAA=BBBB=CCCC= 的字串,其中中間的填充現在是雜散字符,而不是終止標記。這就是 JWT 在每個段落中省略填充的原因:三段結構是顯式的,因此解碼在每個部分上獨立進行,並連接字串中間的填充是不必要的,並會破壞解析。

常見錯誤 - 在一個字串中混合字母,或使用百分比編碼標準 Base64 而不是使用 base64url

如果建立多段有效負載,請在開始時決定填充約定:要么包含在每個段中並從不直接連接,要么省略並僅在解碼時從長度恢復。 RFC 4648 標準是這兩個字母的權威。 4 節指定標準 Base64; 5 部分指定 base64url。每個合格的解碼器都應該清楚地說明它接受哪個字母表。

接受 base64url 但不接受標準 Base64(反之亦然)的程式碼僅實現子集。 base64url 字母表的存在是為了與 URL 和檔案名稱約束相容;它不是改進或替代,只是特定環境的變體。當您編寫 API 或令牌格式時,請選擇一種字母表並記錄哪一種。一個常見的錯誤是使用百分比編碼標準 Base64 而不是使用 base64url。該實現還解釋了文章邊界。它在解碼之前標準化連字符和下劃線,但它不驗證令牌簽名或解釋宣告。將 JWT 段轉換為位元組可以顯示 JSON;它無法確定是誰發布了 JSON 或是否有人更改了它。

這不包括什麼 - 驗證 JWT 簽章、base32 和其他 RFC 4648 編碼

%2B 是 + 的百分號代碼; %2F 是 /. 的百分比代碼 百分比編碼將 TWFu 轉換為 TWFu 不變(無特殊字元),但 TE9S+g== 轉換為 TE9S%2Bg%3D%3D(字元太多,無法處理)。正確的解決方案是使用 base64url,它已經產生 URL 安全的輸出。百分比編碼 Base64 是多餘且浪費的。以正確的字母表作為上下文。 Base64 編碼器和解碼器會自動接受這兩種字母。

如果貼上包含 - 的字串,它會將其視為 base64url;如果貼上包含 + 的字串,則將其視為標準 Base64。工具也接受 URL 並將其視為 URL 安全輸入。因此,實際檢查有兩個獨立的結果:位元組往返,以及所選表示適合其通道。透過第一個表示轉變是可逆的。透過第二個表示標點符號和填充不會被承載它的 URL、檔案名稱、cookie 或協定重寫。

重點:兩個字母表,一個佈局 — Base64 編碼器和解碼器如何處理瀏覽器中的標準字母表,以及其工具頁面在何處說明它接受的內容

解碼 JWT 段或 URL 安全令牌時,無需轉換即可直接貼上,工具從上下文中識別字母。調試失敗的解碼變得簡單:貼上令牌,查看工具是否接受它,如果不接受,則手動交換字元並重試。

替換本身是一行程式碼,但失敗的解碼也可能來自不可能的長度、錯誤的填滿、損壞或非 Base64 輸入。該工具會自動標準化兩個字母表,因此接受僅確認可以恢復位元組。解碼後的 JWT 有效負載仍然是未簽署的宣告,直到單獨的驗證者檢查其簽名和預期演演算法為止。