Golang库包-Base64编解码

2,447 阅读4分钟

概念

Base64是一种表示二进制的方法,有64个可打印字符,取值为A-Za-z0-9+/。

因为2^6=64,所以需要6位二进制数才能表示64个字符。

对于数据来说是以字节为单位的,1字节=8比特。

1字节与1Base64字符不能直接做整值换算,取最小公倍数为24。

最终3字节=4位Base64字符=4个Base64单元。

Base64索引表

编码过程

如果要编码的字节数不能被3整除,最后会多出1个或2个字节,那么可以使用下面的方法进行处理:

先使用0字节值在末尾补足,使其能够被3整除,然后再进行Base64的编码。

在编码后的Base64文本后加上一个或两个=号,代表补足的字节数。

也就是说,

当最后剩余两个八位(待补足)字节(2个byte)时,最后一个6位的Base64字节块有四位是0值,最后附加上两个等号;

如果最后剩余一个八位(待补足)字节(1个byte)时,最后一个6位的base字节块有两位是0值,最后附加一个等号。

用途

用来处理文本数据,比如传输、存储、表示等。

URLSafe模式

采用Base64编码好处:简短、不可读性,即所编码的数据不会被人用肉眼所直接看到。

然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的/和+字符变为形如%XX的形式,而这些%号在存入数据库时还需要再进行转换,因为ANSI SQL中已将%号用作通配符。

为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充=号,并将标准Base64中的+和/分别改成了-和_,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。

如概念中所述的就是Base64标准模式,+/在HTTP传输过程中,可能被偷偷拦截、过滤或是空格代替,导致数据错误。

Golang中base64包

const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
模式 区别 备注
StdEncoding 字符串由A-Za-z0-9+/组成,字节长度不能被3整除,用=补足
RawStdEncoding 字符串由A-Za-z0-9+/组成,字节长度不能被3整除,不用=补足
URLEncoding 字符串由A-Za-z0-9-_组成,字节长度不能被3整除,用=补足
RawURLEncoding 字符串由A-Za-z0-9-_组成,字节长度不能被3整除,不用=补足

代码

// Base64StdEncode 将字节数组编码成字符串
func Base64StdEncode(data []byte) string {
	return base64.StdEncoding.EncodeToString(data)
}

// Base64StdDecode 将base64Std编码后的字符串解码成字节数组
func Base64StdDecode(data string) ([]byte, error) {
	return base64.StdEncoding.DecodeString(data)
}

// Base64RawStdEncode 将字节数组编码成字符串
func Base64RawStdEncode(data []byte) string {
	return base64.RawStdEncoding.EncodeToString(data)
}

// Base64RawStdDecode 将base64Std编码后的字符串解码成字节数组
func Base64RawStdDecode(data string) ([]byte, error) {
	return base64.RawStdEncoding.DecodeString(data)
}

// Base64URLEncode 将字节数组编码成字符串
func Base64URLEncode(data []byte) string {
	return base64.URLEncoding.EncodeToString(data)
}

// Base64URLDecode 将base64Std编码后的字符串解码成字节数组
func Base64URLDecode(data string) ([]byte, error) {
	return base64.URLEncoding.DecodeString(data)
}

// Base64RawURLEncode 将字节数组编码成字符串
func Base64RawURLEncode(data []byte) string {
	return base64.RawURLEncoding.EncodeToString(data)
}

// Base64RawURLDecode 将base64Std编码后的字符串解码成字节数组
func Base64RawURLDecode(data string) ([]byte, error) {
	return base64.RawURLEncoding.DecodeString(data)
}

测试

func main() {
	originData := "Golang欢迎你的加入!"
	base64StdEncodeVal := Base64StdEncode([]byte(originData))
	base64StdDecodeVal, err := Base64StdDecode(base64StdEncodeVal)
	if err != nil {
		fmt.Println("Base64StdDecode failed, error: ", err)
	}

	base64RawStdEncodeVal := Base64RawStdEncode([]byte(originData))
	base64RawStdDecodeVal, err := Base64RawStdDecode(base64RawStdEncodeVal)
	if err != nil {
		fmt.Println("Base64RawStdDecode failed, error: ", err)
	}

	base64URLEncodeVal := Base64URLEncode([]byte(originData))
	base64URLDecodeVal, err := Base64URLDecode(base64URLEncodeVal)
	if err != nil {
		fmt.Println("Base64StdDecode failed, error: ", err)
	}

	base64RawURLEncodeVal := Base64RawURLEncode([]byte(originData))
	base64RawURLDecodeVal, err := Base64RawURLDecode(base64RawStdEncodeVal)
	if err != nil {
		fmt.Println("Base64RawURLDecode failed, error: ", err)
	}

	fmt.Println("base64StdEncodeVal: ", base64StdEncodeVal)
	fmt.Println("base64RawStdEncodeVal: ", base64RawStdEncodeVal)
	fmt.Println("base64URLEncodeVal: ", base64URLEncodeVal)
	fmt.Println("base64RawURLEncodeVal: ", base64RawURLEncodeVal)

	fmt.Println("base64StdDecodeVal: ", base64StdDecodeVal)
	fmt.Println("base64RawStdDecodeVal: ", base64RawStdDecodeVal)
	fmt.Println("base64URLDecodeVal: ", base64URLDecodeVal)
	fmt.Println("base64RawURLDecodeVal: ", base64RawURLDecodeVal)
}

结果如下:

项目使用经验

一般使用Base64URLSafe模式且不需要填充等号。