add utils to pkg
CI / changes (push) Successful in 1s
CI / docker-bff (push) Successful in 1s
CI / docker-product (push) Failing after 1s

This commit is contained in:
2026-08-07 09:55:22 +08:00
parent 95d4c7bdc2
commit 10424d23d8
21 changed files with 410 additions and 1081 deletions
+303
View File
@@ -0,0 +1,303 @@
package utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/binary"
"fmt"
)
type Crypto struct {
}
// DecryptKey 解密处理函数
func (c Crypto) DecryptKey(data, iv, key string) (string, Error) {
info, err := c.aesCBCDecryptKey(data, iv, key)
if err != nil {
return "", err
}
return info, nil
}
func (c Crypto) aesCBCDecryptKey(data, iv, key string) (string, Error) {
cipherByte, err := base64.StdEncoding.DecodeString(data)
if err != nil {
Logger.Error(err)
return "", ErrorEncryptBase64Error
}
k := []byte(key)
// 分组密钥
block, err := aes.NewCipher(k)
if err != nil {
Logger.Error(err)
return "", ErrorEncryptBase64Error
}
if len(iv) < 16 {
return "", ErrorEncryptBase64Error
}
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, []byte(iv))
// 创建数组
origData := make([]byte, len(cipherByte))
// 解密
blockMode.CryptBlocks(origData, cipherByte)
// 去补码
origData = c.pKCS7UnPadding(origData)
return string(origData), nil
}
// Decrypt 解密处理函数
func (c Crypto) Decrypt(data, iv string) (string, Error) {
info, err := c.aesCBCDecrypt(data, iv)
if err != nil {
return "", err
}
return info, nil
}
func (c Crypto) aesCBCDecrypt(data, iv string) (string, Error) {
key := c.GetKey()
cipherByte, err := base64.StdEncoding.DecodeString(data)
if err != nil {
Logger.Error(err)
return "", ErrorEncryptBase64Error
}
k := []byte(key)
// 分组密钥
block, err := aes.NewCipher(k)
if err != nil {
Logger.Error(err)
return "", ErrorEncryptBase64Error
}
if len(iv) < 16 {
return "", ErrorEncryptBase64Error
}
// 加密模式
blockMode := cipher.NewCBCDecrypter(block, []byte(iv))
// 创建数组
origData := make([]byte, len(cipherByte))
// 解密
blockMode.CryptBlocks(origData, cipherByte)
// 去补码
origData = c.pKCS7UnPadding(origData)
return string(origData), nil
}
func (c Crypto) GetKey() string {
return GetConfigString("encrypt.encrypt_key")
}
// PKCS7UnPadding 去码
func (c Crypto) pKCS7UnPadding(origData []byte) []byte {
length := len(origData)
if length == 0 {
return nil
}
unPadding := int(origData[length-1])
if length < unPadding {
return nil
}
return origData[:(length - unPadding)]
}
func (c Crypto) pKCS7Padding(ciphertext []byte, blockSize int) []byte {
// 判断缺少几位长度,最少为 1,最多为 blockSize
padding := blockSize - len(ciphertext)%blockSize
// 补足位数,把切片 []byte{byte(padding)} 复制 padding 个
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// Encrypt 加密
func (c Crypto) Encrypt(data []byte) (map[string]string, Error) {
info, err := c.aesCBCEncrypt(data)
if err != nil {
return nil, err
}
return info, nil
}
func (c Crypto) aesCBCEncrypt(data []byte) (map[string]string, Error) {
key := c.GetKey()
k := []byte(key)
iv := GetRandString(NumberSixteen)
// 分组密钥
block, err := aes.NewCipher(k)
if err != nil {
return nil, ErrorEncryptAesKeyError
}
// 获取密钥块的长度
blockSize := block.BlockSize()
// 补充码
data = c.pKCS7Padding(data, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, []byte(iv))
// 创建数组
crypted := make([]byte, len(data))
// 加密
blockMode.CryptBlocks(crypted, data)
return map[string]string{
"data": base64.StdEncoding.EncodeToString(crypted),
"iv": iv,
}, nil
}
// Encrypt 加密
func (c Crypto) EncryptKey(data []byte, key string) (map[string]string, Error) {
info, err := c.aesCBCEncryptKey(data, key)
if err != nil {
return nil, err
}
return info, nil
}
func (c Crypto) aesCBCEncryptKey(data []byte, key string) (map[string]string, Error) {
k := []byte(key)
iv := GetRandString(NumberSixteen)
// 分组密钥
block, err := aes.NewCipher(k)
if err != nil {
return nil, ErrorEncryptAesKeyError
}
// 获取密钥块的长度
blockSize := block.BlockSize()
// 补充码
data = c.pKCS7Padding(data, blockSize)
// 加密模式
blockMode := cipher.NewCBCEncrypter(block, []byte(iv))
// 创建数组
crypted := make([]byte, len(data))
// 加密
blockMode.CryptBlocks(crypted, data)
return map[string]string{
"data": base64.StdEncoding.EncodeToString(crypted),
"iv": iv,
}, nil
}
// AESEncryptECB 不使用IV的AES-ECB加密
// key长度必须为16、24或32字节,对应AES-128、AES-192、AES-256
func (c Crypto) AESEncryptECB(data string) (string, Error) {
key := GetConfigString("encrypt.data_key")
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", ErrorEncryptMissingKey
}
// 检查密钥长度
keyLen := len(key)
if keyLen != 16 && keyLen != 24 && keyLen != 32 {
return "", ErrorEncryptMissingKey
}
dataByte := []byte(data)
// 填充数据以适应块大小
dataByte = c.pKCS7Padding(dataByte, block.BlockSize())
// ECB模式加密
crypted := make([]byte, len(dataByte))
bs := block.BlockSize()
for i := 0; i < len(dataByte); i += bs {
block.Encrypt(crypted[i:i+bs], dataByte[i:i+bs])
}
return base64.StdEncoding.EncodeToString(crypted), nil
}
// AESDecryptECB 不使用IV的AES-ECB解密
// key长度必须为16、24或32字节,对应AES-128、AES-192、AES-256
func (c Crypto) AESDecryptECB(data string) (string, Error) {
if len([]byte(data)) < 16 {
return "", ErrorEncryptMissingKey
}
key := GetConfigString("encrypt.data_key")
block, err := aes.NewCipher([]byte(key))
if err != nil {
return "", ErrorEncryptMissingKey
}
// 检查密钥长度
keyLen := len(key)
if keyLen != 16 && keyLen != 24 && keyLen != 32 {
return "", ErrorEncryptMissingKey
}
dataByte, err := base64.StdEncoding.DecodeString(data)
if err != nil {
Logger.Error(err)
return "", ErrorEncryptBase64Error
}
// ECB模式解密
decrypted := make([]byte, len(dataByte))
bs := block.BlockSize()
// 修复:正确 ECB 循环
for i := 0; i < len(dataByte); i += bs {
block.Decrypt(decrypted[i:i+bs], dataByte[i:i+bs])
}
// 移除填充
return string(c.pKCS7UnPadding(decrypted)), nil
}
func (c Crypto) DecryptWechatMsg(msgEncrypt string, encodingAESKey string) (msg []byte, receiveId string, err error) {
aesKey, err := base64.StdEncoding.DecodeString(encodingAESKey + "=")
if err != nil {
return nil, "", fmt.Errorf("AESKey解码失败: %v", err)
}
// 1. Base64 解码密文
aesMsg, err := base64.StdEncoding.DecodeString(msgEncrypt)
if err != nil {
return nil, "", fmt.Errorf("base64解码失败: %v", err)
}
// 2. AES 解密(ECB + PKCS7
randMsg, err := c.aesDecrypt(aesMsg, aesKey)
if err != nil {
return nil, "", fmt.Errorf("aes解密失败: %v", err)
}
// 3. 去掉前16随机字节
content := randMsg[16:]
if len(content) < 4 {
return nil, "", fmt.Errorf("数据格式非法")
}
// 4. 读取4字节消息长度
msgLen := binary.BigEndian.Uint32(content[:4])
end := 4 + msgLen
if uint32(len(content)) < end {
return nil, "", fmt.Errorf("消息长度非法")
}
// 5. 截取消息体
msg = content[4:end]
// 6. 剩余为 receiveid
receiveId = string(content[end:])
return msg, receiveId, nil
}
// aesDecrypt AES-ECB-PKCS7 解密(微信加密标准)
func (c Crypto) aesDecrypt(cipherText, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
// ECB 模式
mode := cipher.NewCBCDecrypter(block, make([]byte, aes.BlockSize))
plainText := make([]byte, len(cipherText))
mode.CryptBlocks(plainText, cipherText)
// PKCS7 去填充
return c.pKCS7UnPadding(plainText), nil
}