Base64 是软件里最不起眼、也用得最广的一种编码。它诞生于只能可靠传输文本的年代,之所以活到今天,是因为它能把任意字节变成 64 种可打印的 ASCII 字符:不需要转义、不会弄坏按行处理的协议,而且只要有字节数组就能轻松还原。你最常在三个地方遇见它。第一个是 data URL,小图片被写成 data:image/png;base64 直接写进 CSS 背景或 HTML 属性里。第二个是 Basic 认证,用户名和密码被编码进 HTTP 头。第三个是 JSON Web Token,头和载荷被编码,而且用的是一套略微不同的字母表,有效期往往只有一天。这三处都要求编码分毫不差,而用错的结果往往看起来完全正常,直到别的东西崩掉为止。它跑在这个标签页里,对这个工具来说意义比一般工具更大:Base64 经常被用在那些看起来像密钥的东西上。
Base64 做什么,以及绝不做什么
算法定义在 RFC 4648 里:每次取三个字节共 24 位,拆成四个 6 位数,各自索引一个 64 字符的字母表——A 到 Z、a 到 z、0 到 9,加上加号和斜杠。输入凑不满三字节时用等号补齐。由此得到三条结论,几乎就是全部要点。第一,输出永远比输入大三分之一,所以 Base64 不是压缩,以后也不会是。第二,它完全可以逆运算,任何人都不需要密钥就能还原,所以它不是加密——锁和纸箱的区别只在于人们相信那把锁。第三,输出看起来像乱码,是因为算法刻意把三个输入字节的比特混进每一个输出字符,文件结构因此不容易被肉眼看出来。这个特性曾被用来伪装载荷,也因此催生了自动解码的扫描器。
UTF-8、填充,以及那些看起来能用的错误输出
三个具体的坑。第一个是文本:浏览器的 btoa 接受的是二进制字符串,只要看到高于 U+00FF 的字符就抛错,所以对任何中文、日文或 emoji 调用 btoa 都会直接失败;正确做法是先用 TextEncoder 把字符串编码成 UTF-8 字节,再对这些字节做 Base64。而流传很广的替代做法——先套一层 encodeURIComponent 再把百分号去掉——对 ASCII 看着没问题,对其它字符会静默损坏。第二个是解码方向:atob 返回的是二进制字符串,一个字节一个字符,直接打印中文就会看到乱码,必须再用 UTF-8 解码器把字节转回文本。第三个是填充:没有尾部等号的 Base64,有的解码器接受、有的报错,稳妥的习惯是保留填充——同时记住 URL 安全变体把加号和斜杠换成了减号和下划线,JWT 用的就是它,因为在查询串里未转义的加号会变成空格。
真正会遇见它的地方,以及代价
data URL 是最显眼的一种:可以把小图片或字体直接内联进样式表或文档,代价是多出 33% 的字节、无法单独压缩,而且浏览器和邮件客户端都对 data URL 的长度设了上限。Basic 认证是第二种:请求头里是 user:password 的 Base64,所以它只在 HTTPS 下才安全,而接受明文 HTTP 的服务器等于告诉你它并不在乎你的密码。JSON Web Token 的头和载荷用 Base64url,但第三段是二进制的签名,不是任何可读内容的编码。历史上邮件附件就是按 76 字符换行的 Base64。把二进制塞进 JSON 字段这个做法并非做不到,但更值得避开。还有一条必须说明白:永远不要把密钥的 Base64 放进 URL 查询串——URL 会被写进访问日志、代理日志、浏览器历史,以及下一个请求的 referrer 头。
常见问题
Base64 算加密吗?
不算。它是一种不带密钥的可逆编码,任何人用一秒就能还原,哪怕完全不用这个页面。需要保密就用真正的加密,需要校验完整性就用哈希。Base64 只在某种格式或协议要求它时才用。
中文、日文和 emoji 能正确编码吗?
能,因为文本会先被转换成 UTF-8 字节序列再编码,这正是所有正规实现的做法。一个常见捷径是直接用 Latin-1 编码,或者用百分号编码的取巧写法,产出的结果看起来很像样,解码后却是一堆乱码——这个工具正是为了避开这种问题而写的。
为什么解码出来的文本像乱码?
几乎都是编码不匹配。Base64 解出来是字节而不是字符,字节必须按 UTF-8 解释才是文本。如果源文件本来不是 UTF-8——Latin-1、Shift-JIS、GBK——就要用对应的编码去解,靠猜是猜不回来的。
免费吗?需要联网吗?
免费,不需要账号;页面加载完成后编解码在本地运行,网络中断也不影响。你输入的内容不会被传输:本页没有上传接口。本站有广告,广告服务商会看到页面层面的信息,比如你的 IP 地址。