You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

117 lines
3.2 KiB

package security
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"reflect"
)
// 参考:https://www.yisu.com/zixun/696240.html
func TestAes() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recover...", r.(error).Error(), reflect.TypeOf(r))
}
}()
// aesKeyStr := GetAesKey256()
aesKeyStr := "YYNLVy4qZ+WwkyG7r4kUhMfZu6g9e+" // 0uiba5DAgINl8=
fmt.Println(aesKeyStr)
key, _ := base64.StdEncoding.DecodeString(aesKeyStr)
fmt.Println(key)
text := []byte("you are my sunshine!")
encrypt, _ := EncryptAesCBC(text, key)
fmt.Println(encrypt)
fmt.Println(base64.URLEncoding.EncodeToString(text))
result, _ := DecryptAesCBC(encrypt, key)
fmt.Println(string(result))
}
func GetAesKey256() string {
key := getAesKey(256)
return base64.StdEncoding.EncodeToString(key)
}
func getAesKey(keySize int) []byte {
var key = make([]byte, keySize/8)
_, err := rand.Read(key)
if err != nil {
panic(err)
}
return key
}
// EncryptAesCBC
// src -> 要加密的原文
// key -> 秘钥, 和加密秘钥相同, 大小为: 8byte
func EncryptAesCBC(src, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 对最后一个明文分组进行数据填充
src = pkcs5Padding(src, blockSize)
// 3.创建一个密码分组为链接模式的,底层使用 DES 加密的 BlockMode 接口
// 参数 iv 的长度,必须等于 b 的块尺寸
iv := make([]byte, blockSize, blockSize)
copy(iv, key)
blackMode := cipher.NewCBCEncrypter(block, iv)
// 5.加密连续的数据块
dst := make([]byte, len(src))
blackMode.CryptBlocks(dst, src)
return dst, nil
}
// DecryptAesCBC
// src -> 要解密的密文
// key -> 秘钥, 和加密秘钥相同, 大小为: 8byte
func DecryptAesCBC(src, key []byte) ([]byte, error) {
// 1. 创建并返回一个使用DES算法的cipher.Block接口
block, err := aes.NewCipher(key)
// 2. 判断是否创建成功
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
// 3. 创建一个密码分组为链接模式的, 底层使用DES解密的BlockMode接口
iv := make([]byte, blockSize, blockSize)
copy(iv, key)
blockMode := cipher.NewCBCDecrypter(block, iv)
// 4. 解密数据
dst := src
blockMode.CryptBlocks(src, dst)
// 5. 去掉最后一组填充的数据
dst = pkcs5UnPadding(dst)
// 6. 返回结果
return dst, nil
}
// PKCS5Padding 使用pks5的方式填充
func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
// 1. 计算最后一个分组缺多少个字节
padding := blockSize - (len(ciphertext) % blockSize)
// 2. 创建一个大小为padding的切片, 每个字节的值为padding
padText := bytes.Repeat([]byte{byte(padding)}, padding)
// 3. 将padText添加到原始数据的后边, 将最后一个分组缺少的字节数补齐
newText := append(ciphertext, padText...)
return newText
}
// PKCS5UnPadding 删除pks5填充的尾部数据
func pkcs5UnPadding(origData []byte) []byte {
// 1. 计算数据的总长度
length := len(origData)
// 2. 根据填充的字节值得到填充的次数
number := int(origData[length-1])
// 3. 将尾部填充的number个字节去掉
return origData[:(length - number)]
}