火星救援:Base64 是什么?

1. 简介

Base64,是一种二进制转可读字符的编码方式。简单来说,它提供了一种方式,将一系列二进制序列转换为 ASCII 的字符序列,以 64 进制的方式(这是它的名字的意义, 64-based,以64为基数)。

Base64 的主要用途是在无法方便地直接传递二进制形式的数据时候,可以通过转化为 ASCII 字符串来存储和传递这些数据。例如:

  • 编码图片(然后在 HTML img 标签中内联、在文本文件中保存等等)
  • 使用 SMTP 发送邮件附件
  • JWT 令牌用于身份验证
  • 等等很多很多…

2. 标准

Base 64 会将 6 个 bit 的二进制转换到 1 个 ASCII 字符。

因为是以 64 位基数,即 2⁶ 种可表示的状态,因此编码的最小单位是 6 位二进制(也就是 6 bit)。为了表示这些状态,就从 ASCII 中取出了 64 个字符用于编码。RFC 4648 中规定的编码对应表如下:

Index Binary Char Index Binary Char Index Binary Char Index Binary Char
0 000000 A 16 010000 Q 32 100000 g 48 110000 w
1 000001 B 17 010001 R 33 100001 h 49 110001 x
2 000010 C 18 010010 S 34 100010 i 50 110010 y
3 000011 D 19 010011 T 35 100011 j 51 110011 z
4 000100 E 20 010100 U 36 100100 k 52 110100 0
5 000101 F 21 010101 V 37 100101 l 53 110101 1
6 000110 G 22 010110 W 38 100110 m 54 110110 2
7 000111 H 23 010111 X 39 100111 n 55 110111 3
8 001000 I 24 011000 Y 40 101000 o 56 111000 4
9 001001 J 25 011001 Z 41 101001 p 57 111001 5
10 001010 K 26 011010 a 42 101010 q 58 111010 6
11 001011 L 27 011011 b 43 101011 r 59 111011 7
12 001100 M 28 011100 c 44 101100 s 60 111100 8
13 001101 N 29 011101 d 45 101101 t 61 111101 9
14 001110 O 30 011110 e 46 101110 u 62 111110 +
15 001111 P 31 011111 f 47 101111 v 63 111111 /
Padding =

你也看到了,上面的表中除了 64 个字符以外,还有一个叫做 Padding 的字符。和它的字面意思一样,这个字符就是用来补齐的。为什么要补齐?因为规定 Base 64 编码的字符串需要是 4 个字符的整数。

具体怎么补齐呢?我们来看几个例子。

e.g. 1: 将 ASCII 表示的字符串 “Man” 使用 base64 编码

Source Text (ASCII) M a n
Octets 77 (0x4d) 97 (0x61) 110 (0x6e)
Bits 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
Base64
encoded
Sextets 19 22 5 46
Character T W F u
Octets 84 (0x54) 87 (0x57) 70 (0x46) 117 (0x75)

一个 ASCII 字符占 1 字节 (也就是 8 位二进制),所以三个 ASCII 就是 24 位二进制,正好是整 6 bit 的。所以我们可以将它编码之后获得 “TWFu” 这个Base 64 字符串。

e.g. 2: 将 ASCII 表示的字符串 “Ma” 使用 base64 编码

Source Text (ASCII) M a
Octets 77 (0x4d) 97 (0x61)
Bits 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 0
Base64
encoded
Sextets 19 22 4 Padding
Character T W E =
Octets 84 (0x54) 87 (0x57) 69 (0x45) 61 (0x3D)

在不满 6 bit 的时候,最后的位数用 0 补齐,并且会在解码的时候被丢弃。然后加上 ‘=’ 来补齐到 4 个 ASCII 字符。

3. 使用和实现

是的,事实上在大多数时候,你并不需要手动编码和解码 Base 64 了。

有很多在线的 ASCII 转换器,比如:

Cryptii : 一个相当好用的实时 Base 64 转换器。支持文字、二进制和 Base 64 互相转换。

Base64.Guru : 提供了非常多种的文件格式对 Base 64 的编码解码支持。

以及,如果正在编程,你也可以放心。在大多数的高级程序语言中,都已经有现成的库可以帮你编码和解码 Base 64 了。比如这边是一个调用 Swift Foundation 库的的方法来编码和解码 Base 64 的例子。

import Foundation

extension String {
    func base64Encode() -> String? {
        if let data = self.data(using: .utf8) {
            return data.base64EncodedString()
        }
        return nil
    }
    func base64Decode() -> String? {
        if let data = Data(base64Encoded: self, options: .ignoreUnknownCharacters) {
            return String(data: data, encoding: .utf8)
        }
        return nil
    }
}

let base64String = "SGVsbG8sIHdvcmxkIQ=="

print("Encoded base64 string: \(base64String)")
print("Decoded from base64 string: \( base64String.base64Decode() ?? "" )")

输出如下:

Encoded base64 string: SGVsbG8sIHdvcmxkIQ==
Decoded from base64 string: Hello, world!

最后需要提醒的一点是:(重要的事情说三遍)

Base 64 不是加密算法!

Base 64 不是加密算法!

Base 64 不是加密算法!

Base 64 仅可用于编码。请勿将 Base 64 用于加密、散列用途。

发表评论

邮箱地址不会被公开。 必填项已用*标注