107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
|
/*
|
|||
|
* @Date: 2021-03-11 17:03:16
|
|||
|
* @LastEditors: viletyy
|
|||
|
* @LastEditTime: 2021-04-26 22:43:38
|
|||
|
* @FilePath: /yolk/crypt/aes.go
|
|||
|
*/
|
|||
|
package crypt
|
|||
|
|
|||
|
import (
|
|||
|
"bytes"
|
|||
|
"crypto/aes"
|
|||
|
"crypto/cipher"
|
|||
|
"encoding/base64"
|
|||
|
"fmt"
|
|||
|
)
|
|||
|
|
|||
|
/*
|
|||
|
* AES,即高级加密标准(Advanced Encryption Standard),是一个对称分组密码算法,旨在取代DES成为广泛使用的标准.
|
|||
|
* AES中常见的有三种解决方案,分别为AES-128,AES-192和AES-256. AES加密过程涉及到4种操作:字节替代(SubBytes)
|
|||
|
* ,行移位(ShiftRows),列混淆(MixColumns)和轮密钥加(AddRoundKey).解密过程分别为对应的逆操作.由于每一步
|
|||
|
* 操作都是可逆的,按照相反的顺序进行解密即可恢复明文.加解密中每轮的密钥分别由初始密钥扩展得到.算法中16字节的明文,
|
|||
|
* 密文和轮密钥都以一个4x4的矩阵表示. AES 有五种加密模式:电码本模式(Electronic Codebook Book (ECB)),密
|
|||
|
* 码分组链接模式(Cipher Block Chaining (CBC)),计算器模式(Counter (CTR)),密码反馈模式(Cipher Feed
|
|||
|
* Back (CFB))和输出反馈模式(Output FeedBack (OFB))
|
|||
|
*/
|
|||
|
|
|||
|
var aesKey = "123456781234567812345678"
|
|||
|
|
|||
|
type AesCrypt struct {
|
|||
|
Key string
|
|||
|
}
|
|||
|
|
|||
|
func NewAesCrypt(key ...string) *AesCrypt {
|
|||
|
if len(key) > 0 {
|
|||
|
aesKey = key[0]
|
|||
|
}
|
|||
|
return &AesCrypt{
|
|||
|
Key: aesKey,
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//AES加密
|
|||
|
func (crypt *AesCrypt) Encrypt(orig string) string {
|
|||
|
// 转成字节数组
|
|||
|
origData := []byte(orig)
|
|||
|
k := []byte(crypt.Key)
|
|||
|
|
|||
|
// 分组密钥
|
|||
|
block, err := aes.NewCipher(k)
|
|||
|
if err != nil {
|
|||
|
panic(fmt.Sprintf("key 长度必须 16/24/32长度:%s", err.Error()))
|
|||
|
}
|
|||
|
// 获取密钥块的长度
|
|||
|
blockSize := block.BlockSize()
|
|||
|
// 补全码
|
|||
|
origData = PKCS7Padding(origData, blockSize)
|
|||
|
// 加密模式
|
|||
|
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
|
|||
|
// 创建数组
|
|||
|
cryted := make([]byte, len(origData))
|
|||
|
// 加密
|
|||
|
blockMode.CryptBlocks(cryted, origData)
|
|||
|
// 使用RawURLEncoding 不要使用StdEncoding
|
|||
|
// 不要使用StdEncoding 放在url参数中会导致错误
|
|||
|
return base64.RawURLEncoding.EncodeToString(cryted)
|
|||
|
}
|
|||
|
|
|||
|
//AES解密
|
|||
|
func (crypt *AesCrypt) Decrypt(cryted string) string {
|
|||
|
// 使用RawURLEncoding 不要使用StdEncoding
|
|||
|
// 不要使用StdEncoding 放在url参数中回导致错误
|
|||
|
crytedByte, _ := base64.RawURLEncoding.DecodeString(cryted)
|
|||
|
k := []byte(crypt.Key)
|
|||
|
|
|||
|
// 分组密钥
|
|||
|
block, err := aes.NewCipher(k)
|
|||
|
if err != nil {
|
|||
|
panic(fmt.Sprintf("key 长度必须 16/24/32长度:%s", err.Error()))
|
|||
|
}
|
|||
|
// 获取密钥块的长度
|
|||
|
blockSize := block.BlockSize()
|
|||
|
// 加密模式
|
|||
|
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
|
|||
|
// 创建数组
|
|||
|
orig := make([]byte, len(crytedByte))
|
|||
|
// 解密
|
|||
|
blockMode.CryptBlocks(orig, crytedByte)
|
|||
|
// 去补全码
|
|||
|
orig = PKCS7UnPadding(orig)
|
|||
|
|
|||
|
return string(orig)
|
|||
|
}
|
|||
|
|
|||
|
//补码
|
|||
|
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)]
|
|||
|
}
|