
內容摘要
Base64 把每 3 個位元組改寫成 4 個可打印字元,讓二進位能走純文字通道。代價是體積多 33%,而且它什麼都藏不住。
Base64 到處都是——電郵附件、data URL、JSON payload、JWT 片段,以及夾帶檔案的 API 欄位——而且通常被隨手貼來貼去,沒有人問它到底做了什麼。這篇說明編碼本身:它為什麼存在、精確的數學、padding 從哪來,以及什麼情況下拉 Base64 是錯的選擇。
你可以在 UrsaKit 的 Base64 編碼/解碼工具 裡跟著操作。編碼與解碼都在瀏覽器裡執行,所以你可以一邊讀一邊貼上真實 token。
01Base64 為什麼存在
許多傳輸通道是為文字設計的,只承諾攜帶有限的可打印字元。郵件內文、HTTP 標頭、XML 文字節點與 URL 路徑,都有各自視為特殊的字元。原始 JPEG 或壓縮檔含有 0 到 255 的每一個位元組值,包括控制字元,以及文字通道會直接弄壞的位元組。
Base64 只解決一個問題:用 64 個在每個文字通道都安全的可打印字元,重新表達任意位元組。RFC 4648 定義了這套編碼,並指出第 65 個字元「等號」用來標示 padding,而不是資料。
A-Z a-z 0-9 + / (標準字母表,64 個符號)
- 與 _ 取代 + 與 / (URL-safe 字母表,RFC 4648 第 5 節)
= 補滿最後一組
這些字元會被選中,是因為它們能存活過郵件閘道、HTML 解析與複製貼上。字母表是傳輸用的外衣,不是加密,也不是 ASCII 藝術。
023 位元組轉 4 字元的規則
一個位元組有 8 位元,所以 3 個位元組有 24 位元。64 個符號每個代表 log2(64) = 6 位元,因此 4 個 6 位元符號剛好容納 24 位元。RFC 4648 第 4 節 用一句話講完同一條規則:編碼把 24 位元的輸入位元組,表示成 4 個編碼字元的輸出字串。整個設計就是這樣:輸入 3 個位元組,輸出 4 個字元。
"Man" -> 位元組 4D 61 6E -> 010011 010110 000101 101110 -> TWFu
"Ma" -> 位元組 4D 61 -> 010011 010110 0001(00) -> TWE=
"M" -> 位元組 4D -> 010011 01(0000) -> TQ==
這三個例子是在 2026-10-04 用本機 Python 3 標準函數庫的 base64 編碼器產生的。最後一組不滿 24 位元,所以缺少的位元補 0,用不到的字元則換成等號。RFC 4648 第 3.2 節 要求一般情況必須加 padding,除非引用它的規格另有規定;RFC 7515 正是 JWT 的那個例外,它去掉所有結尾的 padding 字元。
實際後果就是體積開銷。RFC 2045 第 6.8 節(定義 MIME 郵件用的 Base64)說編碼後的資料「固定比未編碼資料大約多 33%」。真實檔案的量測也吻合:
原始檔案 63,728 位元組
base64 84,972 個字元 -> 多 33.34%
這個量測對象是 UrsaKit 封面 publichttps://static.ursakit.com/media/861934dec6614009.jpg,2026-10-04 用本機 Python 編碼。所以一張 3 MB 的圖片會變成約 4 MB 的文字,而且還沒算上 JSON 的引號跳脫。如果你能控制兩端,請改用 multipart/form-data 或直接以原始位元組走 HTTP 傳送。
03Padding 與 URL-safe 字母表
標準 Base64 含有加號與斜線。在 URL 裡,加號會被解讀成空白,斜線是路徑分隔符;在檔名裡,斜線不合法。RFC 4648 第 5 節 定義了 URL 與檔名安全的字母表,把它們換成連字號與底線:
| 輸入位元組 | 標準 | URL-safe |
|---|---|---|
0xFB 0xFF | +/8= | -_8= |
0xFF 0xEF | /+8= | _-8= |
字串 Hi? | SGk/ | SGk_ |
六個值都是在 2026-10-04 用本機 Python base64.b64encode 與 base64.urlsafe_b64encode 產生的。URL-safe 模式也常省略 padding,因為 URL 片段或結構化 token 可以自己攜帶長度。JWT 使用不帶 padding 的 URL-safe 字母表,所以 header 片段看起來像 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,而且絕不會以等號結尾。
標準與 URL-safe 字母表不能互換。
用標準解碼器解 URL-safe 的
-_8=會失敗或回傳錯的位元組;用 URL-safe 解碼器解+/8=也一樣。先確認產生方用的是哪一種,再開始除錯。
04Base64 不是加密
Base64 沒有金鑰,也沒有祕密。解碼是任何人都能做的查表,所以 Base64 字串最好想成「同一批位元組的另一種字體」。
請把這些都當成明文:用 Base64「混淆」過的密碼、設定檔裡用 Base64 包起來的 API key、藏在 data URL 裡的個人紀錄。如果資料需要無法讀取,請用真正的加密——傳輸用 TLS,靜態資料用 AES-GCM 或同等機制——並記住密文在傳送時本身也會被 Base64 編碼。
完整性也是同樣的道理。Base64 除了字母表檢查之外,偵測不到任何損壞;格式本身不會告訴你傳輸途中是否有一個位元被翻轉。RFC 4648 第 12 節 還提醒了反方向:解碼器若默默忽略非字母表字元而不是拒絕它們,就開啟了一條可用來洩漏資料的隱蔽通道。請拒絕非法輸入,並用雜湊或 MAC 處理完整性。
05解碼:先位元組,再文字
解碼器回傳的是位元組,不是字串。把位元組變成可讀文字是第二個決定,也是「解碼後出現奇怪重音字元」的來源。
看得見的字元 é 會依編碼而有不同位元組:
UTF-8 "é" -> 位元組 C3 A9 -> "w6k="
ISO-8859-1 "é" -> 位元組 E9 -> "6Q=="
兩個字串都正確,只是描述了不同的位元組序列。2026-10-04 在本機用 Python 驗證。解碼時請選產生方用過的字元集。如果不知道,先試 UTF-8:它是網絡預設,而且它的非法序列規則會讓猜錯很快現形。
還有兩個解碼陷阱:
- 雙重編碼。 對已編碼字串再編碼一次,會產生合法的 Base64,解碼後還是另一個 Base64 字串。如果輸出看起來像 Base64,再解一次,別急著判定損壞。
- 空白。 多數解碼器會忽略換行與空白,而 RFC 2045 要求 MIME 編碼器每行不超過 76 個字元。嚴格到會拒絕換行的解碼器,需要先去掉換行。
06怎麼在真實世界認出 Base64
當你在讀日誌、設定檔或客服單,看到一整片像隨機字元的東西時,這種密集、沒有空白的字母表就是有用的訊號。四個檢查可以分辨真正的 Base64 與隨機 token:
- 字母表。 每個字元都是大小寫字母、數字,加上加號斜線(標準)或連字號底線(URL-safe)。含有空白、標點或非 ASCII 的字串不是 Base64。
- 長度。 有 padding 時長度是 4 的倍數;沒有 padding 時,是 4 的倍數再減 0、1 或 2。其他長度就是被截斷或複製錯了。
- Padding。 結尾有 0、1 或 2 個等號,絕不會出現在中間。
- 脈絡。 data URL 以媒體類型與
base64標記開頭,JWT 則是由點號連接的三段 base64url。MDN 把 data URL 語法寫成data:[<mediatype>][;base64],<data>。
這些檢查只能告訴你「這可能是 Base64」,無法告訴你裡面是什麼、是否有害——解碼後的內容可能是圖片、壓縮檔,或是有人為了繞過過濾器而編碼的載荷。請在你能信任的工具裡解碼,而且永遠不要把解碼結果當程式碼執行。
07讓解碼器壞掉的常見錯誤
| 症狀 | 原因 | 修正 |
|---|---|---|
| 位置 0 出現 Invalid character | 輸入以 data URL 前綴開頭,例如 data:image/png;base64, | 去掉逗號以前(含逗號)的所有內容 |
| 解碼後的圖片打不開 | 複製時掉了尾巴而截斷,或 URL-safe 字元被換成加號斜線 | 重新複製完整字串;檢查字母表 |
| 輸出是亂碼 | 解碼後的位元組用了錯的字元集 | 用 UTF-8 解,或選回原始字元集 |
| JWT 片段出現 padding 錯誤 | JWT 省略了等號 padding | 先補到 4 的倍數再解碼 |
| 體積變大且 API 拒收 | 在需要原始位元組的地方送了 Base64 | 改用 multipart 上傳 |
08什麼時候該用別的方案
| 需求 | 比 Base64 更好的選擇 |
|---|---|
| 在服務之間傳檔案 | multipart/form-data 或原始二進位 body |
| 在 JSON 裡存位元組 | Base64 是標準答案;JSON 沒有二進位字面量 |
| 讓祕密無法讀取 | AES-GCM 或其他認證加密 |
| 在 URL 路徑編碼任意位元組 | 短值用百分比編碼,不透明 blob 用 Base64url |
| 比較或索引位元組 | Hex——長度兩倍,但可讀且可排序 |
09在瀏覽器裡編碼與解碼
UrsaKit 的 Base64 工具 涵蓋整條流程,而且不用上傳任何東西:
- 選方向——Encode 或 Decode。工作區會切換成對應的輸入模式。
- 選文字或檔案——貼上文字,或拖入圖片、PDF 等檔案。檔案輸入能避開複製貼上造成的截斷。
- 需要時設定字母表選項——URL-safe 會取代加號與斜線,76 字元換行會插入 MIME 換行,即時模式會邊打邊重新編碼。
- 解碼時檢查字元集——自動偵測能認出純 Base64 字串或完整 data URL;文字看起來不對時,在 UTF-8 與單一位元組字元集之間切換。
- 複製或下載結果——解碼端可以存成檔案,這是救回編碼圖片最可靠的方法。
字串正確之後,後續管線通常是 JSON——出貨前先用 JSON 格式化與驗證工具 檢查。
10資料來源
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings(取用日期:2026-10-04)
- RFC 2045 第 6.8 節 — Base64 Content-Transfer-Encoding,體積多約 33% 且每行 76 字元(取用日期:2026-10-04)
- RFC 7515 第 2 節 — Base64url Encoding,省略結尾等號(取用日期:2026-10-04)
- MDN — Data URLs(取用日期:2026-10-04)
編碼與解碼文字或檔案,內置 URL-safe 字母表、76 字元換行與字元集選擇。
Base64 編碼/解碼工具常見問題
Base64 會讓資料變小嗎?
不會,它讓資料變大。每 3 個位元組變成 4 個字元,所以 RFC 2045 說編碼後的資料固定比原始資料大約多 33%。
Base64 是加密嗎?
不是。Base64 是可逆編碼,沒有金鑰。任何拿到字串的人都能解碼,所以絕對不能用來保護密碼、token 或個人資料。
為什麼我的 Base64 字串結尾有一或兩個等號?
等號把最後一組補滿 4 個字元。RFC 4648 要求一般情況要加 padding,因為它讓解碼器知道最後一組實際有幾個位元。長度能被 3 整除的輸入不需要 padding。
為什麼解碼後出現奇怪的字母?
那些位元組是用 UTF-8 解讀,但原本是以 ISO-8859-1 這類單一位元組編碼寫成,或反過來。請選擇與來源相符的字元集。
什麼時候該用 URL-safe Base64?
只要結果會出現在 URL、檔名、查詢字串或 JWT 裡就該用。RFC 4648 第 5 節把標準的加號與斜線換成連字號與底線;RFC 7515 還額外去掉 JWT 片段結尾的 padding。
Base64 檔案裡的換行有影響嗎?
對解碼器沒有影響,但 RFC 2045 要求 MIME base64 輸出每行不超過 76 個字元。換行是傳輸慣例,不是編碼的一部分,解碼器會忽略它。
要怎麼判斷一個字串是不是 Base64?
看字母表(大小寫字母、數字,加上加號斜線或連字號底線)、有 padding 時長度是否為 4 的倍數,以及完全沒有空白。JWT 的 header 片段通常以 eyJ 開頭,那是 JSON 物件開頭字元的 base64url。
相關文章
- 如何格式化、驗證與壓縮 JSON
大多數 Base64 字串最後都嵌在這個 payload 格式裡。
- API 該回哪個 HTTP 狀態碼?
挑對回應碼,處理以 Base64 抵達的上傳。
相關工具
- Base64 編碼/解碼工具
文字或檔案輸入、URL-safe 選項、每 76 字元換行。
- Regex 測試工具
在往下游送之前先驗證 Base64 字串。
- JSON 格式化與驗證
檢查 Base64 內容嵌在什麼 payload 裡。
- HTTP 狀態碼
每個回應碼都有白話解釋。