科技 · 實用指南
Python的Base64嚴格解碼仍接受不同寫法?查核填充位與執行版本
嚴格解碼與只有一種規範寫法是兩項檢查。17項本機對照區分填充位、版本參數、大小限制和解碼位元組的含義。

在本刊的CPython3.12.14環境中,base64.b64decode(value,validate=True)把Zg==和Zh==都解碼為位元組f,也把Zm8=和Zm9=都解碼為fo。嚴格解碼成功,不能證明編碼文字採用了規範寫法。
先釐清真正需要的協定。本篇只測試一種窄範圍策略:非空bytes輸入、標準Base64字母表、具備必要填充、長度有界,而且重新編碼必須與原文完全一致。它不驗證JWT、簽章或MIME訊息。
1. 區分填充字元與未使用的填充位元
實測的Zg==和Zh==有相同數量的等號,差別在最後一個字母表字元的未使用位元。嚴格解碼都接受,但把回傳位元組重新編碼只得到Zg==,所以第二種寫法未通過相等檢查。Zm8=和Zm9=也出現相同對照結果。
RFC4648要求合規編碼器把未使用的填充位元設為零;解碼器可以拒絕非零填充位元,引用此標準的具體協定也可規定更嚴格要求。因此,僅憑解碼器接受,不能判定輸入符合應用程式的單一寫法規則。
2. 使用新參數前先查核執行版本
Python3.15文件新增canonical=True,用來拒絕非零填充位元。字母表驗證仍應明確設定validate=True,並保留協定要求的填充與大小規則。本刊讀了該文件,但沒有執行Python3.15。
在實際CPython3.12.14直譯器中傳入canonical=True,會因未知關鍵字觸發TypeError。在此環境中,本篇的標準填充策略採用validate=True解碼,再要求base64.b64encode(decoded)==encoded。此比較檢查表示形式,不驗證MAC或簽章。
3. 執行完整的有界策略
本刊輔助函式先要求輸入型別恰為bytes,並拒絕超過4096位元組的編碼輸入;嚴格解碼後拒絕超過3072位元組的輸出,套用非空規則,再比較標準重新編碼與原輸入。全部通過才回傳位元組。
17項對照包括f、fo、foo的有效編碼,兩種填充位元變體,冗餘或過量填充、換行、缺少必要填充、URL安全字元、填充後的額外資料與空值。其他對照驗證解碼前長度上限、輸出上限、未知關鍵字及獨立的UTF-8失敗。
4. 格式通過與載荷含義仍須分開
完整三個位元組foo的規範編碼是Zm9v,沒有等號。要求必要填充,不代表每個輸入都要附加=;實測嚴格解碼器拒絕Zm9v=。空Base64能成功解碼,但本應用程式主動拒絕空載荷,這是不同的事實與策略。
規範輸入/w==解碼為位元組0xff,並通過表示形式檢查;將該位元組按UTF-8解碼則失敗。因此,格式有效不證明文字、檔案有效或來源真實。應保留失敗原輸入供診斷;協定要求精確形式時,不要悄悄刪除字元或附加填充。
