base64 编码原理和实现方法

base64 编码是使用 64 个可打印 ASCII 字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成 ASCII 字符串,另有 “=” 符号用作后缀用途。

base64 是网络上最常见的用于传输 8Bit 字节码的编码方式之一,base64 就是一种基于 64 个可打印字符来表示二进制数据的方法。

base64 编码是从二进制到字符的过程,可用于在 HTTP 环境下传递较长的标识信息。采用 base64 编码具有不可读性,需要解码后才能阅读。

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

Hash(哈希或散列)算法是非常基础和重要的计算机算法,它能将任意长度的二进制明文映射为较短的固定长度的二进制Hash值,并且不同的明文很难映射为相同的Hash值。SHA-256 是一种 Hash 算法,在比特币源 ...