122 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package zhicha
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"crypto/aes"
 | |
| 	"crypto/cipher"
 | |
| 	"encoding/base64"
 | |
| 	"encoding/hex"
 | |
| 	"fmt"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	KEY_SIZE = 16 // AES-128, 16 bytes
 | |
| )
 | |
| 
 | |
| // Encrypt 使用AES-128-CBC加密数据
 | |
| // 对应Python示例中的encrypt函数
 | |
| func Encrypt(data, key string) (string, error) {
 | |
| 	// 将十六进制密钥转换为字节
 | |
| 	binKey, err := hex.DecodeString(key)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("密钥格式错误: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if len(binKey) < KEY_SIZE {
 | |
| 		return "", fmt.Errorf("密钥长度不足,需要至少%d字节", KEY_SIZE)
 | |
| 	}
 | |
| 
 | |
| 	// 从密钥前16个字符生成IV
 | |
| 	iv := []byte(key[:KEY_SIZE])
 | |
| 
 | |
| 	// 创建AES加密器
 | |
| 	block, err := aes.NewCipher(binKey)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("创建AES加密器失败: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	// 对数据进行PKCS7填充
 | |
| 	paddedData := pkcs7Padding([]byte(data), aes.BlockSize)
 | |
| 
 | |
| 	// 创建CBC模式加密器
 | |
| 	mode := cipher.NewCBCEncrypter(block, iv)
 | |
| 
 | |
| 	// 加密
 | |
| 	ciphertext := make([]byte, len(paddedData))
 | |
| 	mode.CryptBlocks(ciphertext, paddedData)
 | |
| 
 | |
| 	// 返回Base64编码结果
 | |
| 	return base64.StdEncoding.EncodeToString(ciphertext), nil
 | |
| }
 | |
| 
 | |
| // Decrypt 使用AES-128-CBC解密数据
 | |
| // 对应Python示例中的decrypt函数
 | |
| func Decrypt(encryptedData, key string) (string, error) {
 | |
| 	// 将十六进制密钥转换为字节
 | |
| 	binKey, err := hex.DecodeString(key)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("密钥格式错误: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if len(binKey) < KEY_SIZE {
 | |
| 		return "", fmt.Errorf("密钥长度不足,需要至少%d字节", KEY_SIZE)
 | |
| 	}
 | |
| 
 | |
| 	// 从密钥前16个字符生成IV
 | |
| 	iv := []byte(key[:KEY_SIZE])
 | |
| 
 | |
| 	// 解码Base64数据
 | |
| 	decodedData, err := base64.StdEncoding.DecodeString(encryptedData)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("Base64解码失败: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	// 检查数据长度是否为AES块大小的倍数
 | |
| 	if len(decodedData) == 0 || len(decodedData)%aes.BlockSize != 0 {
 | |
| 		return "", fmt.Errorf("加密数据长度无效,必须是%d字节的倍数", aes.BlockSize)
 | |
| 	}
 | |
| 
 | |
| 	// 创建AES解密器
 | |
| 	block, err := aes.NewCipher(binKey)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("创建AES解密器失败: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	// 创建CBC模式解密器
 | |
| 	mode := cipher.NewCBCDecrypter(block, iv)
 | |
| 
 | |
| 	// 解密
 | |
| 	plaintext := make([]byte, len(decodedData))
 | |
| 	mode.CryptBlocks(plaintext, decodedData)
 | |
| 
 | |
| 	// 移除PKCS7填充
 | |
| 	unpadded, err := pkcs7Unpadding(plaintext)
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("移除填充失败: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return string(unpadded), nil
 | |
| }
 | |
| 
 | |
| // pkcs7Padding 使用PKCS7填充数据
 | |
| func pkcs7Padding(src []byte, blockSize int) []byte {
 | |
| 	padding := blockSize - len(src)%blockSize
 | |
| 	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
 | |
| 	return append(src, padtext...)
 | |
| }
 | |
| 
 | |
| // pkcs7Unpadding 移除PKCS7填充
 | |
| func pkcs7Unpadding(src []byte) ([]byte, error) {
 | |
| 	length := len(src)
 | |
| 	if length == 0 {
 | |
| 		return nil, fmt.Errorf("数据为空")
 | |
| 	}
 | |
| 
 | |
| 	unpadding := int(src[length-1])
 | |
| 	if unpadding > length {
 | |
| 		return nil, fmt.Errorf("填充长度无效")
 | |
| 	}
 | |
| 
 | |
| 	return src[:length-unpadding], nil
 | |
| }
 |