看到 Python 代码里:
b64 = base64.b64encode(data.encode("utf-8")).decode("ascii")
return b64.translate(TRANS)
这里的 .translate() 不是 Base64 库的方法——是 Python 字符串内置的 str.translate()。整个逻辑其实两步:
b64encode把数据编成标准 Base64 字符串translate(TRANS)按映射表把字符逐个替换
常见用途:URL-Safe Base64、简单混淆、自定义字母表。
str.translate 是什么
str.translate(table) 按照 table 里的映射一次性替换多个字符——比一堆 .replace() 快得多:
TRANS = str.maketrans({"a": "x", "b": "y"})
"abc".translate(TRANS) # "xyc"
maketrans 三种参数形式:
# 字典:字符 → 字符
str.maketrans({"a": "x", "b": "y"})
# 两个字符串:一一对应
str.maketrans("abc", "xyz") # a→x, b→y, c→z
# 三个参数:第三个是"要删除的字符"
str.maketrans("", "", "aeiou") # 删除所有元音
"hello world".translate(...) # "hll wrld"
底层是 dict[int, int|None],translate 每个字符按 code point 查表。
URL-Safe Base64(最常见用途)
标准 Base64 用了 + 和 /,在 URL 里出现要 percent-encode(%2B %2F)。URL-safe 变体换掉这两个字符:
TRANS = str.maketrans({"+": "-", "/": "_"})
b64 = base64.b64encode(data).decode("ascii")
url_safe = b64.translate(TRANS)
其实 Python 标准库直接提供了:
base64.urlsafe_b64encode(data).decode("ascii")
自己写 translate 版本效果一样,一般是兼容其它平台的历史代码。
反向:URL-Safe → 标准
TRANS_BACK = str.maketrans({"-": "+", "_": "/"})
standard_b64 = url_safe.translate(TRANS_BACK)
# 补 padding(长度必须是 4 的倍数)
padded = standard_b64 + "=" * (-len(standard_b64) % 4)
data = base64.b64decode(padded)
URL-safe Base64 通常省掉了 = padding——解码时得手动补。
完全自定义字母表
某些爬虫 / 反调试代码会用非标准字母表做混淆:
CUSTOM_ALPHABET = "NOPQRSTUVWXYZABCDEFGHIJKLM" + \
"nopqrstuvwxyzabcdefghijklm" + \
"0123456789-_"
STANDARD_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + \
"abcdefghijklmnopqrstuvwxyz" + \
"0123456789+/"
TRANS = str.maketrans(STANDARD_ALPHABET, CUSTOM_ALPHABET)
编码时把标准 Base64 输出通过 TRANS 转成”看起来不一样但结构相同”的字符串。解码时反向映射再走标准 b64decode。
这是很低强度的混淆——攻击者拿到映射表就完全还原了。但作为”不让日志里的密码一眼可读”够用。
性能对比
translate 一次映射多个字符,比 .replace() 快很多:
import timeit
s = "a" * 10000
t1 = timeit.timeit(
"s.replace('a', 'x').replace('b', 'y')",
globals={"s": s},
number=10000,
)
TRANS = str.maketrans({"a": "x", "b": "y"})
t2 = timeit.timeit(
"s.translate(TRANS)",
globals={"s": s, "TRANS": TRANS},
number=10000,
)
print(t1 / t2) # translate 一般快 3-5 倍
尤其映射表大的时候差距明显。
常见坑
1. maketrans 键值长度必须一样(字符串形式)
str.maketrans("abc", "xy") # 报错:长度不匹配
str.maketrans("abc", "xyz") # OK
字典形式没这个限制。
2. translate 对 bytes 用 bytes 表
b"abc".translate(bytes.maketrans(b"a", b"x"))
字符串和字节的 translate 不通用。
3. 删除字符时用 None
TRANS = {ord("a"): None}
"abc".translate(TRANS) # "bc"
或者用 str.maketrans("", "", "a") 生成的表。
一句话总结
看到 str.translate(TRANS) + Base64 的组合,大概率是做 URL-safe Base64 或简单字母表混淆。Python 标准库直接有 urlsafe_b64encode,自己用 translate 主要是历史代码。真正的性能优势在于批量替换比多次 replace 快得多。
