yolk/crypt/aes.go

107 lines
3.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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)]
}