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 | ||
|  | } |