package crypto import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" ) // Cipher 用主密钥派生的 AES-256-GCM 做敏感字段加解密。 type Cipher struct { aead cipher.AEAD } // NewCipher 以 SHA-256 从主密钥字符串派生 32 字节密钥, // 允许 DATA_KEY 是任意长度的强随机字符串。 func NewCipher(masterKey string) (*Cipher, error) { if masterKey == "" { return nil, fmt.Errorf("new cipher: empty master key") } sum := sha256.Sum256([]byte(masterKey)) block, err := aes.NewCipher(sum[:]) if err != nil { return nil, fmt.Errorf("new cipher: %w", err) } aead, err := cipher.NewGCM(block) if err != nil { return nil, fmt.Errorf("new cipher: %w", err) } return &Cipher{aead: aead}, nil } // EncryptString 加密明文,返回 base64(nonce | ciphertext)。 func (c *Cipher) EncryptString(plaintext string) (string, error) { nonce := make([]byte, c.aead.NonceSize()) if _, err := rand.Read(nonce); err != nil { return "", fmt.Errorf("encrypt: %w", err) } out := c.aead.Seal(nonce, nonce, []byte(plaintext), nil) return base64.StdEncoding.EncodeToString(out), nil } // DecryptString 解密 EncryptString 的输出。 func (c *Cipher) DecryptString(encoded string) (string, error) { raw, err := base64.StdEncoding.DecodeString(encoded) if err != nil { return "", fmt.Errorf("decrypt: %w", err) } ns := c.aead.NonceSize() if len(raw) < ns { return "", fmt.Errorf("decrypt: ciphertext too short") } plain, err := c.aead.Open(nil, raw[:ns], raw[ns:], nil) if err != nil { return "", fmt.Errorf("decrypt: %w", err) } return string(plain), nil }