如果对字符串"ab"进行Base64编码,得到的结果将是:YWI=,结果中为什么会出现=呢,这就需要了解一下base64编码背后的原理。
Base64是一种便于网络传输的字节码编码方式,之所以叫Base64是由于它的编码结果是由64个可打印字符组成,这些字符在不同系统间是通用的。64个字符如下表所示:
索引
对应字符
索引
对应字符
索引
对应字符
索引
对应字符
0
A
17
R
34
i
51
z
1
B
18
S
35
j
52
0
2
C
19
T
36
k
53
1
3
D
20
U
37
l
54
2
4
E
21
V
38
m
55
3
5
F
22
W
39
n
56
4
6
G
23
X
40
o
57
5
7
H
24
Y
41
p
58
6
8
I
25
Z
42
q
59
7
9
J
26
a
43
r
60
8
10
K
27
b
44
s
61
9
11
L
28
c
45
t
62
+
12
M
29
d
46
u
63
/
13
N
30
e
47
v
14
O
31
f
48
w
15
P
32
g
49
x
16
Q
33
h
50
y
大家可以看到这里面并没 '=' 这个字符,这是因为 ’=‘ 其实是填充字符。
如果需要表示上面的64个字符,那么需要6bit,也就是2^6=64,base64的核心思想就是,将3个
字节拆分成4个6bit,然后对每个6bit的高位补2个0,构成1个字节。也即是每3个字节最终结果将变成4个字节。
如果原始字符串的字节数不是3的整数倍,那么就用0来填充,用来填充的0就被编码成了'=',这就是出现=的原因,并且只会出现在结果出,如果原始字符刚好是3字节的整数倍,那么就没有等号了。
回到开头的例子,我们看下ab是如何计算得到YWI=的。
1、ab对应的ascaii编码的二进制表示为:011000001 01100010
2、由于只有两个字节,需要填充到3个字段,也就是:011000001 01100010 00000000
3、拆分成四个6bit:011000 010110 001000 000000
4、高位补两个0,变成四字节:00011000 00010110 00001000 00000000
5、按照上表的对应关系:24-Y 22-W 8-I 填充-=, 也即是YWI=。
需要注意填充的0是要被转化成=,而不是上表中的A。
顺便附上golang示例代码:
func main() { str := "ab" // base64编码 encodedStr :=
base64.URLEncoding.EncodeToString([]byte(str)) fmt.Println(encodedStr) // YWI=
// base64解码 decodeStr, _ := base64.URLEncoding.DecodeString(encodedStr)
fmt.Println(string(decodeStr)) // ab }
如果不希望保留填充的=,可以在编码后去掉,解码前填充上,示例代码如下:
func main(){ str := "ab" // base64编码 encodedStr :=
base64.URLEncoding.EncodeToString([]byte(str)) encodedStr =
strings.TrimRight(encodedStr, "=") // 去掉填充的= fmt.Println(encodedStr) // YWI //
解码时,长度不是4的倍数,需要用=填充 i := len(encodedStr) % 4 if i != 0 { encodedStr +=
strings.Repeat("=", 4-i) } // base64解码 decodeStr, _ :=
base64.URLEncoding.DecodeString(encodedStr) fmt.Println(string(decodeStr)) //
ab }