| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- package utils
- import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/rand"
- "encoding/base64"
- "errors"
- "fmt"
- "io"
- "os"
- )
- // 获取加密密钥(优先从环境变量读取,否则使用默认值)
- // 重要说明:
- // 1. 这个密钥是固定的,用于加密/解密所有 API Key
- // 2. API Key 的长度可以不同,但都用同一个加密密钥加密
- // 3. 如果改变这个密钥,之前加密的 API Key 将无法解密
- // 4. 生产环境必须从环境变量 ENCRYPTION_KEY 读取
- // AES-256 需要 32 字节的密钥
- func getEncryptionKey() []byte {
- key := os.Getenv("ENCRYPTION_KEY")
- if key != "" && len(key) == 32 {
- return []byte(key)
- }
- // 默认密钥(仅用于开发环境,生产环境必须设置 ENCRYPTION_KEY)
- return []byte("abcdefghijklmnopqrstuvwxyz123456") // 32 bytes for AES-256
- }
- // EncryptAPIKey 加密 API Key
- // 参数:
- // - plaintext: 用户输入的 API Key(长度可变,不同服务商不同)
- //
- // 返回:
- // - 加密后的字符串(base64 编码)
- //
- // 说明:
- // - 无论 API Key 多长,都用同一个固定的 encryptionKey 加密
- // - 加密密钥(encryptionKey)是固定的,不会因为 API Key 长度变化而改变
- func EncryptAPIKey(plaintext string) (string, error) {
- // 验证输入
- if plaintext == "" {
- return "", errors.New("API Key 不能为空")
- }
- // 获取加密密钥(优先从环境变量读取)
- key := getEncryptionKey()
- if len(key) != 32 {
- return "", errors.New("加密密钥长度必须为 32 字节")
- }
- // 创建 AES cipher
- block, err := aes.NewCipher(key)
- if err != nil {
- return "", fmt.Errorf("创建加密器失败: %v", err)
- }
- // 创建 GCM(Galois/Counter Mode)
- gcm, err := cipher.NewGCM(block)
- if err != nil {
- return "", fmt.Errorf("创建 GCM 失败: %v", err)
- }
- // 生成随机 nonce
- nonce := make([]byte, gcm.NonceSize())
- if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
- return "", fmt.Errorf("生成随机数失败: %v", err)
- }
- // 加密数据
- ciphertext := gcm.Seal(nonce, nonce, []byte(plaintext), nil)
- // 返回 base64 编码的密文
- return base64.StdEncoding.EncodeToString(ciphertext), nil
- }
- // DecryptAPIKey 解密 API Key
- func DecryptAPIKey(ciphertext string) (string, error) {
- // 获取加密密钥(优先从环境变量读取)
- key := getEncryptionKey()
- if len(key) != 32 {
- return "", errors.New("加密密钥长度必须为 32 字节")
- }
- // 解码 base64
- data, err := base64.StdEncoding.DecodeString(ciphertext)
- if err != nil {
- return "", err
- }
- // 创建 AES cipher
- block, err := aes.NewCipher(key)
- if err != nil {
- return "", err
- }
- // 创建 GCM
- gcm, err := cipher.NewGCM(block)
- if err != nil {
- return "", err
- }
- // 检查数据长度
- if len(data) < gcm.NonceSize() {
- return "", errors.New("ciphertext too short")
- }
- // 提取 nonce 和密文
- nonce, ciphertextBytes := data[:gcm.NonceSize()], data[gcm.NonceSize():]
- // 解密数据
- plaintext, err := gcm.Open(nil, nonce, ciphertextBytes, nil)
- if err != nil {
- return "", err
- }
- return string(plaintext), nil
- }
|