package libs
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"strings"
"errors"
)
func AesEncryptCBC(orig string, key string) string {
// 转成字节数组
origData := []byte(orig)
k := []byte(key)
// 分组秘钥
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 补全码
origData = PKCS7Padding(origData, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
// 创建数组
cryted := make([]byte, len(origData))
// 加密
blockMode.CryptBlocks(cryted, origData)
return base64.StdEncoding.EncodeToString(cryted)
}
func AesDecryptCBC(cryted string, key string) string {
// 转成字节数组
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
k := []byte(key)
// 分组秘钥
block, _ := aes.NewCipher(k)
// 获取秘钥块的长度
blockSize := block.BlockSize()
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
// 创建数组
orig := make([]byte, len(crytedByte))
// 解密
blockMode.CryptBlocks(orig, crytedByte)
// 去补全码
orig = PKCS7UnPadding(orig)
return string(orig)
}
//补码
//AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
//去码
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func AESEncryptECBStr(source string, keys string) string {
// 字符串转换成切片
src := []byte(source)
key := []byte(keys)
cipher, _ := aes.NewCipher(generateKeys(key))
length := (len(src) + aes.BlockSize) / aes.BlockSize
plain := make([]byte, length*aes.BlockSize)
copy(plain, src)
pad := byte(len(plain) - len(src))
for i := len(src); i < len(plain); i++ {
plain[i] = pad
}
encrypted := make([]byte, len(plain))
// 分组分块加密
for bs, be := 0, cipher.BlockSize(); bs <= len(src); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
}
//return encrypted
encryptstr :=strings.ToUpper(hex.EncodeToString(encrypted))
return encryptstr
}
func AESDecryptECBStr(encrypteds string, keys string) string {
// 字符串转换成切片
//encrypted := []byte(encrypteds)
encrypted, _ := hex.DecodeString(encrypteds)
key := []byte(keys)
cipher, _ := aes.NewCipher(generateKeys(key))
decrypted := make([]byte, len(encrypted))
//
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
}
trim := 0
if len(decrypted) > 0 {
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return string(decrypted[:trim])
}
func generateKeys(key []byte) (genKey []byte) {
genKey = make([]byte, 16)
copy(genKey, key)
for i := 16; i < len(key); {
for j := 0; j < 16 && i < len(key); j, i = j+1, i+1 {
genKey[j] ^= key[i]
}
}
return genKey
}
// 为了方便,声明该函数,省去错误处理
// 测试解码
//const testStr = "R2/or63oqIDnvJbnqIs="
//str :=mustDecode(base64.StdEncoding,testStr) // 打印:R2/or63oqIDnvJbnqIs=
//fmt.Println(str)
func Base64DecodeStr(enc *base64.Encoding, str string) string {
data, err := enc.DecodeString(str)
if err != nil {
panic(err)
}
return string(data)
}
// 该函数测试编解码
// enc为要测试的Encoding对象,str为要测试的字符串
//const testStr = "Go语言编程"
// 测试StdEncoding,注意打印结果里的/为URL中的特殊字符,最后有一个padding,mysql的base64加密
//testEncoding(base64.StdEncoding, testStr) // 打印:R2/or63oqIDnvJbnqIs=
测试URLEncoding,可以看到/被替换为_
//testEncoding(base64.URLEncoding, testStr) // 打印:R2_or63oqIDnvJbnqIs=
//
测试RawStdEncoding,可以看到去掉了padding
//testEncoding(base64.RawStdEncoding, testStr) // 打印:R2/or63oqIDnvJbnqIs
//
测试RawURLEncoding,可以看到/被替换Wie_,并且却掉了padding
//testEncoding(base64.RawURLEncoding, testStr) // 打印:R2_or63oqIDnvJbnqIs
func Base64EncodeStr(enc *base64.Encoding, str string) string {
// 编码
encStr := enc.EncodeToString([]byte(str))
// 解码
decStr := Base64DecodeStr(enc, encStr)
if decStr != str { // 编码后再解码应该与原始字符串相同
// 这里判断如果不同,则panic
panic(errors.New("unequal!"))
}
return encStr
}