yolk/crypt/aes.go

107 lines
3.1 KiB
Go
Raw Permalink Normal View History

2021-04-26 23:54:51 +08:00
/*
* @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)]
}