18-base64-encoding

18. 计算机编码规则之:Base64编码

简介

我们知道计算机中的文件可以分为两种,一种是人肉眼可读的文本类文件,一种是肉眼不可读的二进制文件。一般来说二进制文件如果用文本编辑器打开的话会显示乱码,并且二进制文件和文本文件的存储和传输方式是不一样的,那么有没有什么办法将二进制文件转换成为文本文件进行传输或者存储呢?答案是肯定的。

这种编码方式就是我们今天要讲到的Base64编码。

Base64和它的编码原理

Base64是一种将二进制编码格式转换为text编码的一种形式。我们知道二进制编码是0和1的形式,它的单位通常是一个字节,也就是8bits,每个bit表示的是0或者1。

而文本编码的格式有很多种,最早也就是最简单的编码格式就是ASCII编码,ASCII编码的全称是American Standard Code for Information Interchange,也就是美国信息交换标准代码,它主要表示的是常用的一些西欧字符。

ASCII的编码范围是0x00-0x7F,用十进制来表示就是0-127,总共128个字符,刚好是7bits表示的范围。

ASCII编码中包含了33个控制字符和95个可打印的字符,如下所示:

ASCII码含义ASCII码含义

16进制

10进制

2进制

16进制

10进制

2进制

0x00

0

0

NUL 空

0x40

64

1000000

@

0x01

1

1

SOH 标题开始

0x41

65

1000001

A

0x02

2

10

STX 正文开始

0x42

66

1000010

B

0x03

3

11

ETX 正文结束

0x43

67

1000011

C

0x04

4

100

EOT 传输结束

0x44

68

1000100

D

0x05

5

101

ENQ 询问字符

0x45

69

1000101

E

0x06

6

110

ACK 承认

0x46

70

1000110

F

0x07

7

111

BEL 报警

0x47

71

1000111

G

0x08

8

1000

BS 退一格

0x48

72

1001000

H

0x09

9

1001

HT 横向制表

0x49

73

1001001

I

0x0A

10

1010

LF 换行

0x4A

74

1001010

J

0x0B

11

1011

VT 垂直制表

0x4B

75

1001011

K

0x0C

12

1100

FF 走纸控制

0x4C

76

1001100

L

0x0D

13

1101

CR 回车

0x4D

77

1001101

M

0x0E

14

1110

SO 移位输出

0x4E

78

1001110

N

0x0F

15

1111

SI 移位输入

0x4F

79

1001111

O

0x10

16

10000

DLE 数据链路转义

0x50

80

1010000

P

0x11

17

10001

DC1 设备控制1

0x51

81

1010001

Q

0x12

18

10010

DC2 设备控制2

0x52

82

1010010

R

0x13

19

10011

DC3 设备控制3

0x53

83

1010011

S

0x14

20

10100

DC4 设备控制4

0x54

84

1010100

T

0x15

21

10101

NAK 否定

0x55

85

1010101

U

0x16

22

10110

SYN 空转同步

0x56

86

1010110

V

0x17

23

10111

ETB 信息组传送结束

0x57

87

1010111

W

0x18

24

11000

CAN 作废

0x58

88

1011000

X

0x19

25

11001

EM 纸尽

0x59

89

1011001

Y

0x1A

26

11010

SUB 换置

0x5A

90

1011010

Z

0x1B

27

11011

ESC 换码

0x5B

91

1011011

[

0x1C

28

11100

FS 文字分隔符

0x5C

92

1011100

\

0x1D

29

11101

GS 组分隔符

0x5D

93

1011101

]

0x1E

30

11110

RS 记录分隔符

0x5E

94

1011110

^

0x1F

31

11111

US 单元分隔符

0x5F

95

1011111

_

0x20

32

100000

(space)

0x60

96

1100000

`

0x21

33

100001

0x61

97

1100001

a

0x22

34

100010

0x62

98

1100010

b

0x23

35

100011

#

0x63

99

1100011

c

0x24

36

100100

$

0x64

100

1100100

d

0x25

37

100101

%

0x65

101

1100101

e

0x26

38

100110

&

0x66

102

1100110

f

0x27

39

100111

'

0x67

103

1100111

g

0x28

40

101000

(

0x68

104

1101000

h

0x29

41

101001

)

0x69

105

1101001

i

0x2A

42

101010

*

0x6A

106

1101010

j

0x2B

43

101011

+

0x6B

107

1101011

k

0x2C

44

101100

,

0x6C

108

1101100

l

0x2D

45

101101

-

0x6D

109

1101101

m

0x2E

46

101110

.

0x6E

110

1101110

n

0x2F

47

101111

/

0x6F

111

1101111

o

0x30

48

110000

0

0x70

112

1110000

p

0x31

49

110001

1

0x71

113

1110001

q

0x32

50

110010

2

0x72

114

1110010

r

0x33

51

110011

3

0x73

115

1110011

s

0x34

52

110100

4

0x74

116

1110100

t

0x35

53

110101

5

0x75

117

1110101

u

36

54

110110

6

0x76

118

1110110

v

0x37

55

110111

7

0x77

119

1110111

w

0x38

56

111000

8

0x78

120

1111000

x

0x39

57

111001

9

0x79

121

1111001

y

0x3A

58

111010

:

0x7A

122

1111010

z

0x3B

59

111011

;

0x7B

123

1111011

{

0x3C

60

111100

<

0x7C

124

1111100

|

0x3D

61

111101

=

0x7D

125

1111101

}

0x3E

62

111110

>

0x7E

126

1111110

~

0x3F

63

111111

?

0x7F

127

1111111

DEL 删除

Base64就是从ASCII编码中挑选出64个字符和二进制一个字节8bits进行映射,这也就是Base64中64的含义。为什么要选择ASCII编码呢?这是因为ASCII编码是最早出现的编码形式,几乎所有的计算机应用都对其完全支持,不会出现数据传输过程中的内容转换,非常的安全。

当然Base64编码也有多种编码形式,比如在MIME中,Base64选择的是A-Z, a-z, 和 0-9 总共62个字符,再加上其他自选的两个字符组成了64个编码字符。

64个字符用二进制表示是6bits,而常用的二进制使用一个字节来表示,也就是8bits,那么问题来了,怎么将8bits的二进制用6bits的Base64字符来表示呢?

很简单,我们只需要将3个8bits连接起来,变成24bits,这样就可以用4个Base64来表示了。

为什么必须对二进制进行转换呢?这是因为互联网中的某些传输协议只支持某些特定的字符集,如果是其他的字符集是不支持的。比如说常用的发送电子邮件的附件。因为SMTP协议最开始设计的时候是支持7 位 ASCII 字符,所以如果要传输文件的话,我们需要对文件进行编码之后再进行传输。

另外Base64的一种用法就是在HTML中将图片嵌入到网页中,从而实现图片的展示。

虽然Base64很好用,但是因为其只能使用6bits的字符映射集,所以会造成数据映射的损失,从而导致二进制文件编码过后文件体积变大的缺点。

Base64的变体

Base64简单点说就是bit到bit之间的映射,那么肯定不止一种映射方式,我们来看下Base64编码方式的各种变体,通常来说前62位基本上是一样的,不同之处在后面两个字符,以及用于填充的字符(这在某些协议中可能是强制性的,或者在其他协议中可能被删除)。

下表是常见的Base64编码的变体:

编码名称编码字符编码字符编码字符

第62位

第63位

补全符

RFC 1421: Base64 for Privacy-Enhanced Mail (deprecated)

+

/

= mandatory

RFC 2045: Base64 transfer encoding for MIME

+

/

= mandatory

RFC 2152: Base64 for UTF-7

+

/

No

RFC 3501: Base64 encoding for IMAP mailbox names

+

,

No

RFC 4648: base64 (standard)

+

/

= optional

RFC 4648: base64url (URL- and filename-safe standard)

-

_

= optional

RFC 4880: Radix-64 for OpenPGP

+

/

= mandatory

Base64的编码细节

上一节我们讲到了Base64编码的基本原则和一些常见的变体,那么到底是如何进行映射的呢?

本节我们会以Base64的标准形式RFC 4648为例来进行详细的讲解。

RFC 4648选择+和/这两个字符作为编码中的第62位和63位,并且选择=作为补全字符。

首先来观察一下RFC 4648的映射表:

索引

二进制

字符

索引

二进制

Char

索引

二进制

Char

索引

二进制

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

/

补全符

=

我们来以单词man为例,来观察一下Base64的编码流程。

man这个单词在ASCII中分别用77, 97和110表示,转换成为二进制就是01001101, 01100001 和 01101110。

将上面的三个二进制合并在一起就成了:010011010110000101101110, 总共24-bit,从上面的表中选择出对应的字符,所以我们可以得到man经过base64编码之后得到:TWFu。

上面的例子中,man刚好是3个字符,也就是24个bits,可以用base64完整的表示。如果我们只有ma这两个字符,应该怎么进行编码呢?

和上面一样,ma的二进制分别是01001101, 01100001,合并起来就是0100110101100001。

但是上面的bits只有16位,因为一个base64是6bits,所以可以用3个base64来表示,因为原始的bits少了两位,所以用0来补全:

0100110101100001+00 = 010011010110000100。

010011010110000100转换成为base64就是TWE,因为base64编码需要4个字符,所以最后的字符用=来补全,也就是说me经过base64之后变成TWE=。

总结

以上就是Base64的基本含义和转换规则,其实协议很简单,将要转换的数据变成二进制,然后对照转换表格进行转换和补全即可。

最后更新于