開發者工具

Base64 是什麼?文字與 Base64 編碼/解碼教學

認識 Base64 與 Base64URL 的用途,了解如何安全地編碼與還原 UTF-8 文字。

#Base64#編碼#解碼#Base64URL

Base64 是把文字或位元資料轉為可安全放進文字欄位的編碼格式,常見於資料 URI、API 與設定值。使用Base64 Encoder可編碼 UTF-8 文字,再以Base64 Decoder還原。這篇文章說明 Base64 實際上怎麼轉換、結尾的等號從哪裡來、中文為什麼需要先轉成 UTF-8,以及什麼時候該用、什麼時候不該用。

Base64 解決什麼問題

電腦裡的資料本質上是位元組,一個位元組有 256 種可能的值,其中很多值對應不到可顯示的文字,甚至是控制字元。許多系統原本只設計來傳遞文字,例如電子郵件內文、JSON 欄位、設定檔或網址。把圖片這類二進位資料直接塞進去,內容很可能在途中被改動或截斷。

Base64 的做法是只用 64 個「到哪裡都安全」的字元來表示任意資料:

  • 大寫字母 A 到 Z(代表 0 到 25)
  • 小寫字母 a 到 z(代表 26 到 51)
  • 數字 0 到 9(代表 52 到 61)
  • + 和 /(代表 62 和 63)

另外用 = 當作補位符號。

編碼原理:3 個位元組變成 4 個字元

64 等於 2 的 6 次方,所以一個 Base64 字元可以表示 6 個位元。3 個位元組共 24 個位元,剛好可以切成 4 組 6 位元。

以 Man 為例,三個字母的位元組是 77、97、110:

M        a        n
01001101 01100001 01101110

重新每 6 位元切一組:
010011 010110 000101 101110
  19     22      5     46
  T      W       F      u

所以 Man 的 Base64 是 TWFu。

結尾的等號是怎麼來的

資料長度不是 3 的倍數時,最後一組會不滿 24 位元,不足的位元補 0,再用 = 把輸出補滿 4 個字元:

原始文字 位元組數 Base64
Man 3 TWFu
Ma 2 TWE=
M 1 TQ==

剩 2 個位元組時補一個 =,剩 1 個位元組時補兩個 =。等號只會出現在結尾,最多兩個。

實際範例

以下都是實際執行的結果:

原始文字 Base64
Hello SGVsbG8=
Hi SGk=
Hello, World! SGVsbG8sIFdvcmxkIQ==
{"id":1} eyJpZCI6MX0=
你好 5L2g5aW9
台北 101 5Y+w5YyXIDEwMQ==

「你好」只有兩個字,卻編出 8 個字元,因為每個中文字在 UTF-8 佔 3 個位元組,兩個字共 6 個位元組,剛好轉成 8 個 Base64 字元。

中文與 UTF-8

Base64 處理的是位元組,不是文字。文字要先依某種字元編碼轉成位元組,現在通用的是 UTF-8。編碼和解碼兩端必須使用相同的字元編碼,否則解出來會是亂碼。

在瀏覽器裡要特別注意:內建的 btoa 只接受每個字元都在 0 到 255 範圍內的字串,直接放中文會出錯:

btoa("Hello");   // "SGVsbG8="
btoa("你好");    // 丟出 InvalidCharacterError

正確做法是先用 TextEncoder 轉成 UTF-8 位元組:

const bytes = new TextEncoder().encode("你好");
let binary = "";
for (const b of bytes) binary += String.fromCharCode(b);
btoa(binary);    // "5L2g5aW9"

解碼時反過來,先 atob 再用 TextDecoder:

const data = Uint8Array.from(atob("5L2g5aW9"), (c) => c.charCodeAt(0));
new TextDecoder().decode(data);   // "你好"

在 Node.js 則可以直接使用 Buffer:

Buffer.from("你好").toString("base64");              // "5L2g5aW9"
Buffer.from("5L2g5aW9", "base64").toString();        // "你好"

不想寫程式時,本站的 Base64 Encoder 會以 UTF-8 處理輸入,中文可以直接貼上。

何時使用?

當系統只能接受文字、但需要傳遞特殊字元或資料時可使用 Base64。網址情境可使用 Base64URL,避免 +、/、= 等字元造成處理問題。

常見的實際用途:

  • 資料 URI:把小圖示直接寫進 HTML 或 CSS,格式像 data:text/plain;base64,SGVsbG8=。圖片可以用圖片 Base64 轉換器轉換。
  • API 傳遞檔案內容:JSON 不能直接放二進位資料,所以常把檔案內容轉成 Base64 字串放進欄位。
  • HTTP 基本驗證:帳號與密碼以 帳號:密碼 的形式做 Base64 後放進標頭,例如 user:pass 會變成 dXNlcjpwYXNz。這只是格式要求,並沒有保護效果,所以必須搭配 HTTPS。
  • 電子郵件附件:郵件以文字傳輸,附件會先轉成 Base64。
  • JWT:Token 的三個部分都是 Base64URL 編碼,可以用JWT Decoder查看內容。

Base64URL 與標準 Base64 的差別

標準 Base64 用到的 +、/、= 在網址裡都有特殊意義:+ 可能被解讀成空格,/ 是路徑分隔符號,= 用來分隔參數名稱與值。Base64URL 因此做了三個調整:

  • + 換成 -
  • / 換成 _
  • 結尾的 = 通常省略

同樣的內容,兩種格式的結果對照:

原始文字 標準 Base64 Base64URL
台北 101 5Y+w5YyXIDEwMQ== 5Y-w5YyXIDEwMQ
<<???>> PDw/Pz8+Pg== PDw_Pz8-Pg

兩種格式不能混用。把 Base64URL 的字串交給只認標準格式的解碼器,遇到 - 或 _ 就會失敗。本站的工具可以在「Base64 格式」選擇「標準 Base64」或「Base64URL」,並提供移除結尾 = 的選項。如果要把標準 Base64 放進網址參數,另一個做法是再做一次 URL 編碼,可以參考URL 編碼是什麼。

注意事項

Base64 通常會讓資料變大,也不能取代加密。Token、密碼與個資不應只做 Base64 後就公開傳送。

資料會變大約三分之一

每 3 個位元組變成 4 個字元,所以輸出大約是原本的 4/3 倍。一個 3 MB 的檔案,編碼後大約是 4 MB。把大圖片轉成 Base64 內嵌在網頁裡,會讓 HTML 或 CSS 變得很大,通常只適合很小的圖示。

Base64 不是加密

Base64 沒有金鑰,任何人都能立刻還原。看到一串像 dXNlcjpwYXNz 的字串,貼進解碼工具就會得到 user:pass。需要保密的資料應該使用真正的加密方式,並透過 HTTPS 傳輸。同樣的道理,不要把含有真實密碼或金鑰的 Base64 字串貼到公開的地方求助。

常見錯誤與排除

  • 解碼出來是亂碼:通常是字元編碼不一致,原始資料不是 UTF-8;或者原始資料根本不是文字,而是圖片或壓縮檔。
  • 出現無效字元的錯誤:檢查字串裡是不是混入了 -、_(代表是 Base64URL),或是複製時帶進了空格與換行。Base64 Decoder 提供「忽略空格與換行」的選項可以處理後者。
  • 長度不正確:標準 Base64 的長度一定是 4 的倍數。複製時漏掉結尾的 = 或少了幾個字元,就會出現這個問題。
  • 把 Base64 當成壓縮:Base64 只會讓資料變大,不會變小。

小結

  • Base64 用 64 個安全字元表示任意位元組,每 3 個位元組變成 4 個字元。
  • 結尾的 = 是補位,最多兩個。
  • 中文要先轉成 UTF-8 位元組再編碼。
  • 用在網址時改用 Base64URL。
  • Base64 可以輕易還原,不能用來保護資料。

想快速驗證一段字串時,把內容貼進Base64 Encoder或Base64 Decoder,資料只在瀏覽器裡處理。

常見問題

Base64 是加密嗎?

不是。Base64 是可逆的編碼方式,不應用來保護密碼或機密資料。

Base64 結尾的 = 是什麼意思?

那是補位符號。Base64 每 3 個位元組轉成 4 個字元,資料長度不是 3 的倍數時,用 = 把最後一組補滿 4 個字元。少 1 個位元組補一個 =,少 2 個補兩個。

Base64 編碼後資料會變大多少?

每 3 個位元組變成 4 個字元,所以大約增加三分之一。例如 3 MB 的檔案編碼後大約是 4 MB。

喜歡這篇文章嗎?

你的支持能幫助 Alan 工具箱持續維護,並新增更多免費工具與教學內容。

支持 Alan 工具箱 ↗