UrsaKit 封面,說明 Base64 編碼如何把位元組轉成可打印字元

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:

  1. 字母表。 每個字元都是大小寫字母、數字,加上加號斜線(標準)或連字號底線(URL-safe)。含有空白、標點或非 ASCII 的字串不是 Base64。
  2. 長度。 有 padding 時長度是 4 的倍數;沒有 padding 時,是 4 的倍數再減 0、1 或 2。其他長度就是被截斷或複製錯了。
  3. Padding。 結尾有 0、1 或 2 個等號,絕不會出現在中間。
  4. 脈絡。 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 工具 涵蓋整條流程,而且不用上傳任何東西:

  1. 選方向——Encode 或 Decode。工作區會切換成對應的輸入模式。
  2. 選文字或檔案——貼上文字,或拖入圖片、PDF 等檔案。檔案輸入能避開複製貼上造成的截斷。
  3. 需要時設定字母表選項——URL-safe 會取代加號與斜線,76 字元換行會插入 MIME 換行,即時模式會邊打邊重新編碼。
  4. 解碼時檢查字元集——自動偵測能認出純 Base64 字串或完整 data URL;文字看起來不對時,在 UTF-8 與單一位元組字元集之間切換。
  5. 複製或下載結果——解碼端可以存成檔案,這是救回編碼圖片最可靠的方法。

字串正確之後,後續管線通常是 JSON——出貨前先用 JSON 格式化與驗證工具 檢查。

10資料來源

常見問題

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。

返回文章列表

相關文章

相關工具