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 }