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,資料只在瀏覽器裡處理。