Utilo

Base64解釋了:它是如何工作的,何時使用它,何時不使用

一個清晰的解釋Base64編碼:演算法,填充,URL安全Base64,資料URL,大小上述,Unicode陷和安全誤解。

· 6 分鐘閱讀

Base64在電子郵件附件,JSON Web Token,資料 URL,Kubernetes 機密,HTTP 基本身份驗證以及無數需要透過文字通道移動二進位制資料的API中出現。簡單一點,但卻經常被濫用,。本文將逐步解釋演算法,常見的變體以及Base64是正確的工具時的實用指導。

這個問題Base64解決了

許多系統的設計目的是傳輸文字,而不是任意位元組。電子郵件 (SMTP) 歷史上只支援7位ASCII。JSON字串不能包含原始二進位制。URL和HTTP頭有限制的字符集。如果將影象的原始位元組放入其中,

Base64 將任意位元組對映到 64 個安全可列印字元上:A–Z,a–z,0–9,+ 和/。任何能夠傳輸純文字的系統都能傳輸完整的資料。

如何編碼工作

Base64處理輸入的組為 3 個位元組 (24 位),輸出 4 個 6 位的字元。因為2^6=64,每個6位值都會從字母表中選擇一個字元。

舉個例子,Man:

  1. 亞斯基位元組:M = 77,a = 97,n = 110。
  2. 在二進位制:01001101 01100001 01101110。
  3. 分為四個6位組:010011 010110 000101 101110。
  4. 作為一個數字:19,22,5,46。
  5. 檢視字母表:T,W,F,u。

所以Man變成了TWFu。解碼會扭轉這個過程。

填充用 =

當輸入長度不是3的倍數時,最後一個組是不完整的。基64填充它:

  • 一個剩餘位元組產生2個字元加上==。
  • 剩下的2個位元組產生3個字元加上=。

Ma編碼為 TWE= 和 M 到 TQ==。填充使得輸出長度是四倍的,。其他,尤其是URL安全的實現,會省略它,因為長度已經暗示了缺少多少位元組。

大小開支

每3位元組就變成4個字元,因此Base64輸出大約比輸入大33%,加上填充和有時行斷 (MIME電子郵件將行包裹在76個字元)。一個1MB的影象大約是1.37MB的文字。這種費用在JSON或HTML中嵌入大型檔案時很重要。

網址安全Base64

標準字母包括+和/,在URL中具有特殊含義,以及用於查詢字串的=。Base64URL在RFC 4648中定義,用-取代+和_取代/,通常會丟棄填充。許多API令牌和Web推送鍵使用這種變體,請參閱[JWT如何工作] (/blog/how-jwt-works)。

標準解碼器在-和_上失敗,反之亦然,這是"無效字元"錯誤的常見來源。一個寬容的 [Base64解碼器] ((/工具/base64) 接受兩個字母,並自動恢復缺失的填充。

文字,位元組和Unicode

基64編碼位元組,而不是字元。要編碼文字,首先必須將其轉換為位元組,。這就是瀏覽器會讓人陷入困境的地方:JavaScript的內建btoa()只接受拉丁-1範圍的字元,所以btoa("héllo")是偶然執行的,而btoa("你好")則會出現錯誤。

在現代JavaScript中正確的方法:

const bytes = new TextEncoder().encode("你好 👋");
const b64 = btoa(String.fromCharCode(...bytes));
const back = new TextDecoder().decode(Uint8Array.from(atob(b64), c => c.charCodeAt(0)));

其他語言明確表示:Python的 base64.b64encode 需要位元組,所以你寫 base64.b64encode("你好".encode("utf-8"))。

資料URL

資料URL直接嵌入HTML或CSS檔案:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="">

這樣可以儲存HTTP請求,在HTTP/1.1時代是非常有價值的。如今,在HTTP/2多重複用時,平衡通常偏好單獨的檔案:

  • 資料URL不能獨立快取;它們在包含它們的每一個頁面或樣式表時都會重新下載。
  • 它們充滿了HTML和CSS,
  • 雖然gzip可以恢復部分。

使用資料URL用於微小的資產小圖示12 KB以下,佔位符影象或單個檔案HTML出口。對於任何更大的檔案,服務一個正常的檔案,而不是[壓縮它] (/blog/compress-image-to-100kb)。

Base64不是加密

這就是最重要的一點。基64沒有金鑰。任何人都可以立即解碼,。然而,通常發現:

  • 在前端程式碼中隱藏在Base64中的API鍵。
  • 密碼儲存在資料庫或配置檔案中。
  • 庫伯尼特斯的秘密被認為是受保護的,

Kubernetes 在 Base64 中編碼秘密值,以便二進位制資料適應 YAML;保護來自訪問控制和靜止加密,必須單獨配置。如果資料需要保密,請使用AES-GCM這樣的真實演算法加密,如果需要驗證密碼,請使用密碼雜湊函式而不是Base64而不是像MD5這樣的簡單雜湊 (為什麼不)。

常見的用例做得很好

  • HTTP基本身份驗證 傳送 Authorization: Basic base64(user:password)。編碼只能避免特殊字元的問題;憑證僅由HTTPS保護。
  • 電子郵件附件使用MIME Base64,每76個字元都會有行斷。
  • 將二進位制資料嵌入JSON中,例如一個小的簽名影象或密碼金鑰,是合法的使用。對於大型檔案,單獨上傳並透過URL引用它們。
  • 僅儲存文字配置中的二進位制資料,例如環境變數中的TLS證書。

解碼錯誤的故障排除

  • **不有效的字元:**您可能使用標準解碼器解碼Base64URL,或者字串包含空白或行斷。
  • 不正確的填充: 加入=直到長度是四的倍數。
  • **解碼後出現錯誤的文字:**原件是從不同的字符集編碼的,或者資料是二進位制而不是文字。
  • **輸出看起來像Base64:**資料被編碼兩次;再一次解碼。

相關編碼

  • Base32使用32個字元 (AZ和27),不敏感大寫,用於身份驗證應用程式的TOTP秘密。總費用是60%。
  • 十六進位制 (Base16) 每位元組使用兩個字元 100% 總額但易於閱讀,並且用於雜湊。
  • Base58刪除類似字元,用於比特幣地址。
  • 百分比編碼只逃離URL中的不安全字元。

總結

Base64將位元組轉換為64個字元的文字字母,一次3個位元組,成本約為33%的額外大小。使用它透過文字道傳輸二進位制資料;在URL和令牌中使用URL安全變體;始終首先將文字轉換為UTF-8位元組。永遠不要使用它來保護秘密,這是一個加密,不是鎖。

本頁內容由英文自動翻譯而來,如發現錯誤,歡迎告訴我們。

相關指南