繁體中文

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

如何使用 Base64 建立和解碼 HTTP 基本驗證標頭

· 工作原理

base64 安全

HTTP 基本驗證標頭,使用者名稱:密碼 Base64 編碼
原始 ToolAcre 向量圖

Authorization: Basic 標頭只是透過 Base64 執行的使用者名稱:密碼。這篇文章展示如何建立該值,如何從請求日誌中解碼該值,以及為什麼編碼不隱藏任何內容。

儘管憑證正確,但 401 仍然存在——一個解碼為稍微錯誤的字串的標頭值

HTTP API 傳回 401 Unauthorized 並需要 Authorization: Basic 標頭。該值是方案字Basic、一個空格和一個Base64 字串。即使可見的使用者名稱和密碼看起來正確,遺失的前綴、編碼的前綴或未被注意到的換行符號也會更改伺服器接收的內容。

解碼該字串並讀取使用者名稱:密碼(實際上是兩個之間的冒號)。位元組使用者名稱:密碼經過 UTF-8 編碼,然後進行 Base64 編碼,產生標頭值。如果憑證為 admin:s3cret,UTF-8 位元組為 0x61 0x64 0x6D 0x69 0x6E 0x3A 0x73 0x33 0x63 0x72 0x65 0x74(ASC 24164 24 64 124 124 124 124 124 242 124 字加號字母編碼YWRtaW46czNjcmV0,標頭為 Authorization: Basic YWRtaW46czNjcmV0。

來自 RFC 7617 的配方:'user:pass', UTF-8, Base64 — 確切的步驟和冒號的作用

這是 RFC 7617 中定義的完整 HTTP 基本驗證方案。它簡單、標準化,並本身不提供安全性:任何讀取標頭的人都可以立即對其進行解碼以讀取密碼。這就是為什麼 HTTPS 對於基本驗證是必要的。編碼是傳輸要求,而不是安全功能。密碼以 UTF-8 位元組傳輸,與任何其他資料相同; Base64 只是 HTTP 協定中使用的表示法。

如果需要從網路日誌中解碼 Basic 標頭,流程很簡單:剝離 Basic,Base64 解碼剩餘部分,並您有使用者名稱:密碼。冒號是使用者名稱和密碼之間的分隔符號。 RFC 7617 指定憑證為使用者 ID:密碼,第一個冒號是分隔符號。如果密碼包含冒號,則第二個冒號只是密碼中的另一個字元。冒號是結構性的,因為接收者需要一個明確的邊界。解碼後搜尋第一個冒號;它前面的所有內容都標識用戶,後面的所有內容都是密碼。因此,缺少冒號表示憑證對格式錯誤,而不是 Base64 字母問題。

工作範例:編碼 admin:s3cret 並解碼日誌中的標頭 - 兩個方向,包括尾隨換行錯誤

如果使用者名稱是 admin,密碼是 pass:word,則憑證是 admin:pass:word,編碼為 YWRtaW46cGFzczp3b3Jk。解碼時,必須只在第一個冒號上分割,給予使用者名稱 admin 和密碼 pass:word。對每個冒號進行拆分會錯誤地拆分密碼。 RFC 7617 中的字元集參數表示憑證採用 UTF-8 編碼。這表示使用者名稱或密碼中的非 ASCII 字元在 Base64 編碼之前會轉換為 UTF-8 位元組。

如果使用者名稱是咖啡廳(重音 e),則 UTF-8 位元組為 0x63 0x61 0x66 0xC3 0xA9(四個位元組用於 ASCII 字母,兩個位元組用於重音字元),並完整憑證咖啡館:密碼包含咖啡館。 Base64 輸出忠實地編碼所有位元組。解碼器必須知道將解碼後的位元組解釋為 UTF-8 文字,而不是拉丁語-1。

包含冒號、空格和非 ASCII 的密碼 — 為什麼第一個冒號會分開,以及 charset 參數的用途

一個有效的範例:從 admin:s3cret 開始。轉換為 UTF-8 位元組:a=0x61、d=0x64、m=0x6D、i=0x69、n=0x6E、:=0x3A、s=0x73、3=0x33、c=0x63、r=0x72、e=0x65、t=0x74。十進位:(97, 100, 109, 105, 110, 58, 115, 51, 99, 114, 101, 116)。 Base64 對這 12 個位元組進行編碼:分為四組,每組三個(產生四組,每組四個 Base64 字元)。

編碼值為YWRtaW46czNjcmV0。授權標頭為 Authorization: Basic YWRtaW46czNjcmV0。密碼一側可以包含另一個冒號,而無需移動第一個邊界。當雙方就文字編碼達成一致時,空格和非 ASCII 文字也會保留。 ToolAcre 可以驗證它發出的 UTF-8 位元組,但需要不同字元集的舊伺服器仍然是 Base64 轉換之外的互通性問題。

為什麼沒有 TLS 就不安全 — 解碼會向看到標頭的任何人顯示密碼

要解碼收到的標頭,請剝離 Basic、Base64 解碼 YWRtaW46czNjcmV0 以獲取字節,解釋為 UTF-8 文字以獲取 admin:s3cret,在第一個冒號上拆分以提取用戶名和密碼。一個常見的錯誤是 echo 尾隨換行符。如果執行 echo admin:s3cret | Unix shell 中的 base64,echo 預設加入換行符,因此使用換行符對 admin:s3cret 進行編碼(13 位元組而不是 12)。

Base64 輸出不同:YWRtaW46czNjcmV0Cg==(填充和額外字元)。具有此值的授權標頭將會失敗,因為密碼包含換行符號。修復方法是使用 echo -n 或透過 printf 或不附加換行符的工具進行管道傳輸。 Base64 編碼器和解碼器避免了這種情況:準確編碼您貼上的內容,沒有隱藏的換行符。 TLS 改變的是傳輸威脅,而不是憑證格式。在受保護的連接內,標頭與請求的其餘部分一起加密;一旦軟體記錄或顯示它,Base64 值就會再次向任何能夠解碼它的人公開可重複使用憑證。在每個觀察點,編輯仍然很重要。

常見錯誤 — echo 中的換行符、缺少「Basic」前綴、對值進行雙重編碼

另一個錯誤是缺少基本前綴。授權標頭值單獨使用 Base64 無效;它是方案名稱(Basic 或 Bearer 或其他),後面跟著空格,然後是憑證。某些系統無法將 YWRtaW46czNjcmV0 識別為憑證,但可以成功識別基本 YWRtaW46czNjcmV0。如果偵錯 401,請檢查伺服器是否正確解析授權標頭。

方案在 HTTP 標準中不區分大小寫,但許多實作是區分大小寫的;檢查 API 檔案。雙重編碼是另一種失敗模式。如果 Base64 編碼已經經過 Base64 編碼的字串,則輸出是不同的字串。編碼 YWRtaW46czNjcmV0 產生 WVdkbWFXNDZjek5qY3JldA== (完全不同)。某些系統可能會意外地應用編碼兩次:一次是在憑證設定期間,另一次是在構造標頭時。 shell 指令中的換行符號特別容易被忽略,因為它可以被編碼為憑證的一部分,而不是被拒絕作為 Base64 周圍的空格。產生的標頭乾淨地解碼為帶有額外位元組的密碼,產生看起來像伺服器端身份驗證失敗的 401 。

這不包括什麼 - 摘要和承載方案,以及瀏覽器憑證提示

解碼器需要單層 Base64,因此雙重編碼會導致不符。這就是為什麼以 Base64 形式(非明文)記錄憑證值可能會令人困惑:如果有人應用解碼一次,他們會看到使用者名稱和密碼;如果應用兩次,他們會看到混淆。摘要式驗證 (RFC 7616) 和承載身分驗證(針對 OAuth 令牌)使用不同的方案,每個方案都有不同的憑證格式。

Digest 要求伺服器發送隨機數,客戶端計算雜湊值,標頭包含雜湊值和用戶名,而不是密碼。 Bearer 通常是 JSON Web Token (JWT),它是 Base64url 編碼的,但不帶有使用者名稱前綴。基本驗證比兩者都簡單,但如果沒有 TLS,則完全不安全,因為憑證在標頭中是可讀的。摘要和承載使用相同的授權標頭欄位,但為其值分配完全不同的含義。瀏覽器憑證提示在 Basic 之上新增使用者介面和快取行為。本文停止建構和檢查基本憑證有效負載,而不是比較這些驗證系統。

重點:基本驗證是 Base64,而不是保護 — Base64 編碼器和解碼器如何讓您在本地檢查標頭值,而無需將憑證發送到任何地方

如果 API 支援多種驗證方案,請選擇最安全的可用方案。 Base64 編碼器和解碼器可以協助偵錯基本驗證失敗:貼上憑證字串(使用者名稱、冒號和密碼),工具立即產生 Base64 值。將結果與標頭發送進行比較,可以看到不匹配。相反,貼上網路日誌中的標頭值,去除基本前綴,解碼以查看伺服器看到的內容。

為了學習,貼上 admin:s3cret 並觀察輸出,然後修改密碼以查看 Base64 如何變化。了解標頭的建構方式可以闡明為什麼解碼需要了解 RFC 格式以及為什麼冒號是結構元素,而不是 Base64。本地檢查應使用發明的憑證,而不是從生產環境複製的即時密碼。對這對進行編碼,將輸出移回輸入面板,然後對其進行解碼。匹配的標點符號和精確的尾隨字符在標頭髮送到任何地方之前證明了表示往返。