Base64的使用

Golang内置支持Base64编码解码,Go的encoding/base64包遵照RFC 4648规范实现了base64编码解码功能,包括标准方式以及URL/文件名称安全方式编码。

标准方式编码解码

RFC 4648规范约定标准Base64对任何二进制数据使用US-ASCII字符子集进行编码,字符包括:A-Z, a-z, 0-9, +, and /

1
2
3
4
5
6
7
8
9
10
func main() {
data := "我爱Go语言"
// base64编码,通常说的base64 0-9a-zA-Z+_ 64
// 5oiR54ixR2/or63oqIA= 标准编码带/
fmt.Println(base64.StdEncoding.EncodeToString([]byte(data)))

// 解码 内容:我爱Go语言
txt,err := base64.StdEncoding.DecodeString("5oiR54ixR2/or63oqIA=")
fmt.Println(string(txt),err)
}

URL和文件名安全编码解码

URL和文件名安全方式是标准方式的变体,其输出用于URL和文件名。因为+/字符是标准Base64字符对URL和文件名编码不安全,变体即使用-代替+_(下划线)代替/

1
2
3
4
5
6
7
8
9
10
func main() {
data := "我爱Go语言"
// 将+替换成- 将/替换成_
// 编码
fmt.Println(base64.URLEncoding.EncodeToString([]byte(data))) // 5oiR54ixR2_or63oqIA=

// 解码
txt, err := base64.URLEncoding.DecodeString("5oiR54ixR2_or63oqIA=")
fmt.Println(string(txt), err) // 我爱Go语言
}

无填充编码

标准Base64编码对输出结果使用=进行填充。一般也建议使用填充方式,但一些场景无需填充。我们可以使用Raw方式编码即没有填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
data := "我爱Go语言"
// 标准编码
fmt.Println(base64.RawStdEncoding.EncodeToString([]byte(data))) // 5oiR54ixR2/or63oqIA
// url编码
fmt.Println(base64.RawURLEncoding.EncodeToString([]byte(data))) // 5oiR54ixR2_or63oqIA

// 标准解码
txt, err := base64.RawStdEncoding.DecodeString("5oiR54ixR2/or63oqIA")
fmt.Println(string(txt), err) // 我爱Go语言
// url解码
txt1, err := base64.RawStdEncoding.DecodeString("5oiR54ixR2_or63oqIA")
fmt.Println(string(txt1), err) // 我爱Go语言
}

hex和md5编码

hex编码

1
2
3
4
5
6
7
8
9
10
11
12
13
func main() {
data := []byte("我爱Go语言")

// 通过Pritf打印十六进制
fmt.Printf("%x\n",data) // e68891e788b1476fe8afade8a880

// hex编码字节切片,注意数据类型是字节切片
fmt.Println(hex.EncodeToString(data)) // e68891e788b1476fe8afade8a880

// hex解码
txt,_ := hex.DecodeString("e68891e788b1476fe8afade8a880")
fmt.Println(string(txt))
}

md5的hash计算

计算字符串的md5 hash

1
2
3
4
5
6
7
8
9
10
func main() {
// hash算法 => 前面 (不可逆)
// MD5, SHA1, SHA256, SHA512
// %x 表示按照16进制来表示,如果需要大写的字符,使用 %X
// "我爱go语言:代表要加密的字符串

fmt.Printf("%x\n",md5.Sum([]byte("我爱go语言"))) // e9bf125aad0d21a1c9b77dbf2c78325d
re := md5.Sum([]byte("我爱go语言"))
fmt.Printf("%X\n",re) // E9BF125AAD0D21A1C9B77DBF2C78325D
}

分批次写入字符串一起计算md5

分别写入我爱go语言一起计算md5值

1
2
3
4
5
6
func main() {
hasher := md5.New()
hasher.Write([]byte("我爱"))
hasher.Write([]byte("go语言"))
fmt.Println(hex.EncodeToString(hasher.Sum(nil))) //e9bf125aad0d21a1c9b77dbf2c78325d
}

计算md5值加盐

1
2
3
4
5
6
7
8
9
10
func main() {
// 取当前时间戳生产盐
salt := time.Now().Unix()
m5 := md5.New()
m5.Write([]byte("我爱go语言"))
m5.Write([]byte(string(salt)))
st := m5.Sum(nil)

fmt.Println(hex.EncodeToString(st)) // ad53884b4151b876aaeaef476d6c8f14
}

计算文件md5小工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func main() {
var name string
flag.StringVar(&name,"p","","path")
flag.Parse()

if name == ""{
return
}

f,err := os.Open(name)
defer f.Close()
if err != nil{
fmt.Println("文件打开失败",err)
return
}

hasher := md5.New()
ctx := make([]byte,1024)
for {
n,err := f.Read(ctx)
if err == io.EOF {
break
}
hasher.Write(ctx[:n])
}
fmt.Printf("%x",hasher.Sum(nil))
}

运行示例

1
2
3
4
5
6
7
// 小工具计算结果
$ go run fileio.go -p fileio.go
12af4076365a97ae5123f02e6133e3f5

// mac自带工具计算结果
$ md5 fileio.go
MD5 (fileio.go) = 12af4076365a97ae5123f02e6133e3f5