Base64 编码解码工具
快速进行 Base64 编码和解码,支持 UTF-8 文本转换
选择转换方式
什么是 Base64?
Base64 是一种用 64 个可打印字符表示二进制数据的方法。这 64 个字符包括大小写字母 A-Z、数字 0-9,以及 + 和 / 两个符号。因为只使用可打印字符,Base64 编码后的数据可以安全地在邮件、网页、JSON 等只支持文本的场景中传输。编码后的数据会比原始数据大约增加 33%。Base64 最早出现在 1987 年的 PEM 协议中,用于在邮件中安全传输二进制数据。现在它已成为互联网标准之一,被广泛应用于各种场景,从电子邮件附件到 JWT 令牌,从图片内嵌到数据传输。几乎所有编程语言都内置了 Base64 编解码功能。
使用方法
使用步骤
- 将文本粘贴到左侧输入框
- 选择「编码」或「解码」操作
- 结果自动显示在右侧
- 点击「复制」按钮保存结果
常见误区
- Base64 是编码而非加密;任何拥有文本的人都可以解码,请勿用于保护机密。
- 解码失败时,请检查是否缺少填充、误带换行符、URL-safe Base64 字符或多余引号。
使用场景
技术原理
Base64 是 RFC 4648(S. Josefsson,2006 年 10 月)中定义的几种二进制到文本编码之一,同属该规范的还有 Base16(十六进制)和 Base32。"Base64" 这个名称和字母表最初在 PEM(Privacy-Enhanced Mail,RFC 989,1987 年)中定义,PEM 将二进制的 S/MIME 和 X.509 材料包装在可打印的 ASCII 信封中,以便在 7 位安全传输环境中使用。同一字母表后来成为 MIME(RFC 2045)、JWT 签名(RFC 7519)、HTML data: URI(RFC 2397)、SSH 公钥块(RFC 2553 §6.6)和 Git LFS 指针文件(将 SHA-256 哈希存储为 Base64)的事实标准。Git 自身的包文件并非 Base64 —— 它们使用 delta 编码加 zlib 压缩,Git 对象 ID 是 40 字符的十六进制 SHA-1 字符串,而非 Base64。代价是:每 3 个输入字节变为 4 个输出字符,因此编码输出恰好是原始大小的 4/3(33.3% 的膨胀)。一个 10MB 的二进制文件编码后约为 13.3MB。 编码机制:将输入分成 3 字节(24 位)的组;每组被拆分为四个 6 位值;每个 6 位值从 64 字符字母表中选取一个字符。标准字母表为 A-Z(索引 0-25)、a-z(26-51)、0-9(52-61)、"+"(62)、"/"(63),"=" 作为填充字符。RFC 4648 的经典示例:"Man"(0x4d 0x61 0x6e)打包为 24 位值 0x4d616e;拆分为 6 位块得到 0x0d 0x16 0x0e 0x0a,映射为 "TWFu"。当输入长度不是 3 的倍数时,末尾的组在右侧补零:剩余 1 字节 → 2 个有效的 6 位块 + "=="(2 个填充字符);剩余 2 字节 → 3 个有效块 + "="(1 个填充)。填充字符不携带信息,但它们使编码长度成为输入长度的确定性函数,并让解码器能拒绝截断的输入。 在浏览器中,Base64 有两个著名的陷阱。首先,`btoa` 和 `atob`(DOMString 版本)操作的是 Latin-1 代码单元而非字节 —— 传入包含 U+00E9(é)或 U+4E2D(中)的字符串会抛出 InvalidCharacterError。本页面通过在调用 btoa 之前使用 `TextEncoder().encode(str)`(始终为 UTF-8)进行转换,在 atob 之后使用 `TextDecoder().decode(bytes)` 解码来解决这个问题。UTF-8 多字节字符会膨胀:"你" 占 3 字节(0xe4 0xbd 0xa0)→ 4 个 Base64 字符("你好" 占 8 个 Base64 字符)。其次,Base64URL(RFC 4648 §5)将 "+" 和 "/" 替换为 "-" 和 "_",并去掉填充,因为 "+" 和 "/" 在 URL 中有特殊含义,而 "=" 会终止查询字符串。JWT(RFC 7519)和 JWS(RFC 7515)要求使用 Base64URL 正是出于这个原因。 Base64 是编码而非加密 —— 编码后的形式没有任何保密性,字母表如此之短以至于任何观察者都能轻松读取。将 Base64 误认为安全机制是一种常见的 CVE 模式:CVE-2004-2761 记录了 X.509 MD5 选择前缀碰撞,使攻击者能伪造具有碰撞 MD5 签名的证书;CVE-2005-4900 等则涉及旧的做法,即认证层将 `$1$` md5crypt 密码哈希重新编码或重新哈希,混淆了 Base64 解码后的字节与新凭证。反复出现的模式相同:系统将编码当作添加了一层实际不存在的保密性,最终导致可被利用的漏洞。对于真正的机密信息,应使用 AES-GCM(RFC 5288)或 ChaCha20-Poly1305(RFC 8439)。对于压缩后再 Base64 编码(`gzip -b64` 的做法),注意编码后的大小约为 gzip 压缩后的 1.37 倍,且压缩流中的任何字节变化都会导致解码失败 —— 因此 Base64 是一个糟糕的完整性保护层;在编码前对字节计算 HMAC-SHA256 才是正确做法。
- RFC 4648(2006 年 10 月)定义了 Base64、Base32 和 Base16,使用标准字母表(A-Z、a-z、0-9、+、/)和 "=" 作为填充字符。MIME 变体(RFC 2045)每 76 个字符插入换行以便传输;URL 安全变体(Base64URL,RFC 4648 §5)将 + 和 / 替换为 - 和 _,并去掉填充 —— 被 JWT(RFC 7519)、JWS(RFC 7515)和 JWK(RFC 7517)使用。
- 编码机制:3 个输入字节(24 位)→ 4 个输出字符(每个 6 位)。膨胀率为 33.3% —— 每 1MB 二进制输入变为 1.33MB Base64。对于 ASCII 文本,当输入包含 "=" 或其他被周围协议转义的字符时,比率可能更差。
- 填充规则:输入长度 mod 3 = 0 → 无填充;mod 3 = 1 → "=="(2 个填充字符,编码 1 字节);mod 3 = 2 → "="(1 个填充字符,编码 2 字节)。"=" 不携带信息;它只是让解码器知道丢弃了多少字节。
- UTF-8 + btoa 的陷阱:`btoa('é')` 会抛出 InvalidCharacterError,因为 btoa 将输入视为 Latin-1 代码单元。本页面通过在 btoa 之前用 TextEncoder(UTF-8)编码、在 atob 之后用 TextDecoder 解码来解决。如果没有这一步,U+0000..U+00FF 之外的任何字符都会变成 "0 字节被编码" 而不是报错。
- Base64URL 是 JWT、JWS 和 JWK(RFC 7519/7515/7517)的必选方案。它使用 "-" 和 "_" 代替 "+" 和 "/"(URL 特殊字符),并去掉 "=" 填充(会终止查询字符串)。将 JWT 头段传给 Base64 解码器而非 Base64URL 解码器会返回乱码;本页面不会自动检测 —— 请为载荷选择正确的变体。
- 性能:在现代笔记本的 V8 中,编码速度约为 400-700 MB/s(通过查表和位移的紧密循环实现)。解码速度类似。对于大文件(10MB 以上),瓶颈在于内存分配而非计算 —— 输出缓冲区大 33%,且 TextEncoder/TextDecoder 会创建副本。
- Base64 是编码而非加密 —— 任何人都能读取编码后的字符串。CVE-2004-2761(X.509 证书签名的 MD5 选择前缀碰撞)和许多 MISC-CTF 题解都利用这种误解作为第一步。对于机密信息,使用 AES-GCM(RFC 5288)或 ChaCha20-Poly1305(RFC 8439)。对于 data: URI,注意编码后的大小:一张 10MB 的图片会变成 13.3MB 的 URL,超出大多数浏览器的 URL 长度限制和大多数邮件的大小限制。
- 迁移说明:Base16(十六进制)在底层协议和哈希输出中更受青睐,因为每个字节恰好映射为 2 个字符,长度可预测(无需填充计算)。Base32 更适合人工抄录(没有易混淆字符)。Base64 是文本协议中二进制传输的通用默认方案,但在 HTTP/2 和 WebTransport 等帧允许原始字节传输的场景中正逐步被取代。
示例
编码 ASCII 文本
输入: Hello
输出: SGVsbG8= (5 字节 -> 8 个字符,1 个填充)
输入: Hello, World!
输出: SGVsbG8sIFdvcmxkIQ== (13 字节 -> 18 个字符,1 个填充)
输入: Man
输出: TWFu (3 字节 -> 4 个字符,无需填充)
'Man' 是 RFC 4648 里的经典示例: 字节 0x4D 0x61 0x6E 拼成 24 位的 0x4D616E,
再切成 6 位的 0x0D 0x16 0x0E 0x0A,按标准字母表映射成 T W F u。编码 UTF-8 文本(中文)
输入: 你好 (UTF-8 共 6 字节)
输出: 5L2g5aW9 (8 个字符)
输入: 你好世界 (4 个汉字,UTF-8 共 12 字节)
输出: 5L2g5aW95LiW55WM (16 个字符)
每个常用汉字在 UTF-8 下占 3 个字节(如 E4 BD A0),Base64
输出会再放大约 4/3 — 编码后的字符数大约是原汉字数的 2.67 倍。
页面会先用 TextEncoder().encode(str) 把文本转成字节数组,
以避开 btoa 在非 ASCII 输入下抛出的 'InvalidCharacterError'。解码并往返 JWT 片段
编码: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
解码: {"alg":"HS256","typ":"JWT"}
往返过程:
encode('{"alg":"HS256","typ":"JWT"}') -> eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
decode('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9') -> {"alg":"HS256","typ":"JWT"}
JWT 用的是 Base64URL,所以页面要同时识别 '-' / '_' 和标准的
'+' / '/'。如果直接把 JWT 头丢给严格的 Base64 解码器只会得到
乱码 — 用什么变体得看负载本身。Base64 与 Base64URL 的区别
输入: Hello><h2>
标准: SGVsbG8+PGgyPg== (使用 + / 和 = 填充;可安全放入 JSON / 邮件)
URL 安全版: SGVsbG8-PGIyPg (使用 - 和 _,无填充;可安全放入 URL 路径或查询)
差异:
'+' (62) -> '-' /' (63) -> '_'
URL 安全版完全去掉 '=' 填充
JWT、JWS、JWK 以及任何会出现在 URL 查询串里的 token 都该用
Base64URL,因为 '+' / '/' 在 URL 中有特殊含义,'=' 又会终止查询。常见问题
Base64 是加密吗?
不是。Base64 是一种编码而不是加密。它只是把任意字节转换成 64 个可打印 ASCII 字符(A-Z、a-z、0-9、+、/),方便在那些会破坏二进制数据的系统里传输。任何拿到编码字符串的人都能瞬间还原,根本没有秘密可言。
为什么编码结果末尾会有一个或两个 = 号?
Base64 每 3 个输入字节产出 4 个输出字符。当输入长度不是 3 的倍数时,编码器会用 = 补齐,让输出长度仍是 4 的倍数。剩 1 个字节 → 2 个 =;剩 2 个字节 → 1 个 =;正好对齐 → 没有 =。也有实现会省略 = 填充,这虽然合法,但兼容性不一定好。
URL 安全的 Base64 是什么?
标准 Base64 包含 / 和 +,它们在 URL 和文件名中有特殊含义。URL 安全 Base64(RFC 4648 §5)把它们替换成 _ 和 -,并经常省略 = 填充。它用于 JWT 令牌、URL 参数和文件名;其他场景仍用标准 Base64 即可。
为什么 Base64 字符串比原始数据大约长 33%?
每 6 位输入会被编码成一个 8 位输出字符,所以编码长度 = ceil(input_length / 3) × 4,大约是输入的 4/3,即 33% 的额外开销。这就是用可打印 ASCII 表示任意字节所付出的代价。
可以粘贴哪些格式的输入?
编码时可粘贴纯文本(按 UTF-8 编码处理),或上传文件。解码时粘贴 Base64 字符串即可,含不含空白都没关系,解码器会自动去掉换行。如果解码失败,请检查是否混入了多余字符,或缺少 = 填充。
Base64 能携带二进制文件内容吗?
可以,这正是它的主要用途——HTML/CSS 内嵌图片(data: URL)、邮件附件(MIME)、HTTP 头中的凭据(Basic Auth)都靠 Base64 把二进制内容塞进纯文本通道。注意编码后的体积会比原文件大约多 33%。
可以用 Base64 隐藏敏感数据吗?
千万不要。Base64 无需密钥即可还原——把它当作"混淆"是常见错误,现实中已多次因此泄露密码和令牌。敏感数据请使用真正的加密或专门的密钥管理服务。