解读Base64编码中为什么会有等号(=)问题
Base64编码中为什么会有等号(=)
如果对字符串"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
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341