base64 编码原理和实现方法
base64 编码是使用 64 个可打印 ASCII 字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成 ASCII 字符串,另有 “=” 符号用作后缀用途。
base64 是网络上最常见的用于传输 8Bit 字节码的编码方式之一,base64 就是一种基于 64 个可打印字符来表示二进制数据的方法。
base64 编码是从二进制到字符的过程,可用于在 HTTP 环境下传递较长的标识信息。采用 base64 编码具有不可读性,需要解码后才能阅读。
数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 | |||
---|---|---|---|---|---|---|---|---|---|---|
0 | A | 16 | Q | 32 | g | 48 | w | |||
1 | B | 17 | R | 33 | h | 49 | x | |||
2 | C | 18 | S | 34 | i | 50 | y | |||
3 | D | 19 | T | 35 | j | 51 | z | |||
4 | E | 20 | U | 36 | k | 52 | 0 | |||
5 | F | 21 | V | 37 | l | 53 | 1 | |||
6 | G | 22 | W | 38 | m | 54 | 2 | |||
7 | H | 23 | X | 39 | n | 55 | 3 | |||
8 | I | 24 | Y | 40 | o | 56 | 4 | |||
9 | J | 25 | Z | 41 | p | 57 | 5 | |||
10 | K | 26 | a | 42 | q | 58 | 6 | |||
11 | L | 27 | b | 43 | r | 59 | 7 | |||
12 | M | 28 | c | 44 | s | 60 | 8 | |||
13 | N | 29 | d | 45 | t | 61 | 9 | |||
14 | O | 30 | e | 46 | u | 62 | + | |||
15 | P | 31 | f | 47 | v | 63 | / |
base64 将输入字符串按字节切分,取得每个字节对应的二进制值(若不足 8 比特则高位补 0),然后将这些二进制数值串联起来,再按照 6 比特一组进行切分,最后一组若不足 6 比特则末尾补 0。将每组二进制值转换成十进制,然后在上述表格中找到对应的符号并串联起来就是 base64 编码结果。
由于二进制数据是按照 8 比特一组进行传输,因此 base64 按照 6 比特一组切分的二进制数据必须是 24 比特的倍数(6和8的最小公倍数)。24 比特就是 3 个字节,若原字节序列数据长度不是 3 的倍数时且剩下 1 个输入数据,则在编码结果后加 2 个=;若剩下 2 个输入数据,则在编码结果后加 1 个=。
完整的 base64 定义可见 RFC1421 和 RFC2045。因为 base64 算法是将 3 个字节原数据编码为 4 个字节新数据,所以 base64 编码后的数据比原始数据略长,为原来的 4/3。在电子邮件中,根据 RFC822 规定,每 76 个字符,还需要加上一个回车换行。可以估算编码后数据长度大约为原长的 135.1%。
base64 可用于任意数据的底层二进制数据编码,以应用于只能传输ASCII字符的场合。不过最常用于文本数据的处理传输,例如在 MIME 格式的电子邮件中,base64 可以用来编码邮件内容,方便在不同语言计算机间传输而不乱码,注意是传输而不是显示,例如在西欧地区计算机上使用 utf-8 编码即可正常显示中文(安装有对应字库),但是它未必能正常传输中文,这时转换为 base64 便无此顾虑。
base64 编码若无特别说明,通常约定非 ASCII 字符按照 UTF-8 字符集进行编码处理。
golang 中 base64 的编码和解码可以用内置库 encoding/base64。
base64 编码示例:
package main import ( "encoding/base64" "fmt" "log" ) func main() { input := []byte("hello world") fmt.Println("原始内容:" + string(input)) // 演示base64编码 encodeString := base64.StdEncoding.EncodeToString(input) fmt.Println("编码:" + encodeString) // 对上面的编码结果进行base64解码 decodeBytes, err := base64.StdEncoding.DecodeString(encodeString) if err != nil { log.Fatalln(err) } fmt.Println("解码:" + string(decodeBytes)) // 如果要用在url中,需要使用 URLEncoding uEnc := base64.URLEncoding.EncodeToString([]byte(input)) fmt.Println("url编码:" + uEnc) uDec, err := base64.URLEncoding.DecodeString(uEnc) if err != nil { log.Fatalln(err) } fmt.Println("url解码:" + string(uDec)) }
运行结果如下:
原始内容:hello world 编码:aGVsbG8gd29ybGQ= 解码:hello world url编码:aGVsbG8gd29ybGQ= url解码:hello world
下一章:SHA-256 算法介绍
Hash(哈希或散列)算法是非常基础和重要的计算机算法,它能将任意长度的二进制明文映射为较短的固定长度的二进制Hash值,并且不同的明文很难映射为相同的Hash值。SHA-256 是一种 Hash 算法,在比特币源 ...