1 Base64加密与解密
1.1 标准编码与解码
package main
import (
"encoding/base64"
"fmt"
)
func main() {
var str string = "杨国强"
//标准加密
encoded := base64.StdEncoding.EncodeToString([]byte(str))
fmt.Printf("str:%v\n", encoded)
//标准解密
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
fmt.Printf("decode base 64 failed:%v\n", err)
return
}
fmt.Printf("str:%v\n", string(decoded))
}
运行结果
# go run base64.go
str:5p2o5Zu95by6
str:杨国强
1.2 URL编码和解码
URL和文件名安全方式是标准方式的变体,其输出用于URL和文件名。因为+和/字符是标准Base64字符对URL和文件名编码不安全,变体即使用-代替+,_(下划线)代替/。
func decode() {
data := "hello world12345!?$*&()'-@~"
uEnc := base64.URLEncoding.EncodeToString([]byte(data))
// Base64 Url Decoding
uDec, err := base64.URLEncoding.DecodeString(uEnc)
if err != nil {
fmt.Printf("Error decoding string: %s ", err.Error())
return
}
fmt.Println(string(uDec)) // "hello world12345!?$*&()'-@~"
}
1.3 无填充编码
标准Base64编码对输出结果使用=进行填充。一般也建议使用填充方式,但一些场景无需填充。我们可以使用Raw方式编码即没有填充。
func main() {
data := "abc!?$*&()'-@~"
// Base64 Encoding without Padding
swEnc := base64.RawStdEncoding.EncodeToString([]byte(data))
fmt.Println(swEnc) // YWJjIT8kKiYoKSctQH4
// Base64 Url Encoding without Padding
uwEnc := base64.RawURLEncoding.EncodeToString([]byte(data))
fmt.Println(uwEnc) //YWJjIT8kKiYoKSctQH4
}
2 aes256加密与解密
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"encoding/binary"
"fmt"
)
func Encrypt(data []byte, key string) (string, error) {
keyData, err := aes.NewCipher([]byte(key))
if err != nil {
return "", err
}
data, err = pad(data, aes.BlockSize)
if err != nil {
return "", err
}
iv := random(aes.BlockSize)
mode := cipher.NewCBCEncrypter(keyData, []byte(iv))
mode.CryptBlocks(data, data)
return iv + base64.StdEncoding.EncodeToString(data), nil
}
func Decrypt(encrypted string, password string) ([]byte, error) {
keyData, err := aes.NewCipher([]byte(password))
if err != nil {
return nil, err
}
if len(encrypted) <= aes.BlockSize {
return nil, fmt.Errorf("encrypted data too short")
}
iv := encrypted[:aes.BlockSize]
encryptedString := encrypted[aes.BlockSize:]
data, err := base64.StdEncoding.DecodeString(encryptedString)
if err != nil {
return nil, err
}
mode := cipher.NewCBCDecrypter(keyData, []byte(iv))
mode.CryptBlocks(data, data)
data, err = unpad(data, aes.BlockSize)
if err != nil {
return nil, err
}
return data, nil
}
// PKCS#7 padding
func pad(b []byte, blocksize int) ([]byte, error) {
if blocksize <= 0 {
return nil, fmt.Errorf("invalid blocksize %d", blocksize)
}
if len(b) == 0 {
return nil, fmt.Errorf("invalid data")
}
n := blocksize - (len(b) % blocksize)
pb := make([]byte, len(b)+n)
copy(pb, b)
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
return pb, nil
}
func unpad(b []byte, blocksize int) ([]byte, error) {
if blocksize <= 0 {
return nil, fmt.Errorf("invalid blocksize %d", blocksize)
}
if len(b) == 0 {
return nil, fmt.Errorf("invalid data")
}
if len(b)%blocksize != 0 {
return nil, fmt.Errorf("invalid data length")
}
c := b[len(b)-1]
n := int(c)
if n == 0 || n > len(b) {
return nil, fmt.Errorf("invalid padding")
}
for i := 0; i < n; i++ {
if b[len(b)-n+i] != c {
return nil, fmt.Errorf("invalid padding")
}
}
return b[:len(b)-n], nil
}
// String generates a random string using only letters provided in the letters parameter
// if user ommit letters parameters, this function will use defLetters instead
func random(n int, letters ...string) string {
defLetters := []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
var letterRunes []rune
if len(letters) == 0 {
letterRunes = defLetters
} else {
letterRunes = []rune(letters[0])
}
var bb bytes.Buffer
bb.Grow(n)
l := uint32(len(letterRunes))
// on each loop, generate one random rune and append to output
for i := 0; i < n; i++ {
bb.WriteRune(letterRunes[binary.BigEndian.Uint32(genBytes(4))%l])
}
return bb.String()
}
// Bytes generates n random bytes
func genBytes(n int) []byte {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return b
}
func main() {
//key := random(32)
key := "HXl8G2+60gnxdvi.oP5?L94*F=VrDM3_"
//key := "XPhtIGprLh8AJ01CvkFstT8Ze34TQNMi"
println("key:", key)
pwd := "test123"
encrypted, err := Encrypt([]byte(pwd), key)
if err != nil {
fmt.Printf("encrypt error: %v\n", err)
return
}
fmt.Printf("encrypt:%v\n",encrypted)
decrypted, err := Decrypt(encrypted, key)
if err != nil {
fmt.Printf("decrypt error: %v\n", err)
return
}
if string(decrypted) != pwd {
fmt.Printf("Decrypted text does not match original text")
}
fmt.Printf("decrypted:%v\n",string(decrypted))
}
运行结果:
key: HXl8G2+60gnxdvi.oP5?L94*F=VrDM3_
encrypt:tHEfGSTj2ZAgfM6hxem3wCzmUsrT+Zfq4Mk3hA==
decrypted:test123