概念
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模式且不需要填充等号。