AI Gateway Go 0.10.0 源码快照 + 旗舰版需求规划报告
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package cryptox
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var ErrKeyUnavailable = errors.New("encryption key unavailable")
|
||||
|
||||
type AESGCM struct {
|
||||
aead cipher.AEAD
|
||||
version int
|
||||
purpose string
|
||||
}
|
||||
|
||||
func NewAESGCM(encodedKey string, version int, purpose string) (*AESGCM, error) {
|
||||
if encodedKey == "" {
|
||||
return nil, nil
|
||||
}
|
||||
key, err := base64.StdEncoding.DecodeString(encodedKey)
|
||||
if err != nil {
|
||||
key, err = base64.RawStdEncoding.DecodeString(encodedKey)
|
||||
}
|
||||
if err != nil || len(key) != 32 {
|
||||
return nil, errors.New("encryption key must be base64-encoded 32 bytes")
|
||||
}
|
||||
if version < 1 || purpose == "" {
|
||||
return nil, errors.New("encryption version and purpose are required")
|
||||
}
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
aead, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &AESGCM{aead: aead, version: version, purpose: purpose}, nil
|
||||
}
|
||||
|
||||
func (c *AESGCM) Encrypt(plaintext []byte) ([]byte, int, error) {
|
||||
if c == nil {
|
||||
return nil, 0, ErrKeyUnavailable
|
||||
}
|
||||
nonce := make([]byte, c.aead.NonceSize())
|
||||
if _, err := rand.Read(nonce); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
ciphertext := c.aead.Seal(nil, nonce, plaintext, c.additionalData())
|
||||
return append(nonce, ciphertext...), c.version, nil
|
||||
}
|
||||
|
||||
func (c *AESGCM) Decrypt(encrypted []byte, version int) ([]byte, error) {
|
||||
if c == nil {
|
||||
return nil, ErrKeyUnavailable
|
||||
}
|
||||
if version != c.version {
|
||||
return nil, fmt.Errorf("encryption key version %d is not loaded", version)
|
||||
}
|
||||
nonceSize := c.aead.NonceSize()
|
||||
if len(encrypted) <= nonceSize {
|
||||
return nil, errors.New("encrypted value is truncated")
|
||||
}
|
||||
plaintext, err := c.aead.Open(nil, encrypted[:nonceSize], encrypted[nonceSize:], c.additionalData())
|
||||
if err != nil {
|
||||
return nil, errors.New("encrypted value authentication failed")
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
func (c *AESGCM) additionalData() []byte {
|
||||
return []byte(fmt.Sprintf("ai-gateway/%s/v%d", c.purpose, c.version))
|
||||
}
|
||||
Reference in New Issue
Block a user