diff options
| author | Chia <Chia@93.nz> | 2026-08-04 19:58:52 +1200 |
|---|---|---|
| committer | Chia <Chia@93.nz> | 2026-08-04 20:43:23 +1200 |
| commit | 5b651488b081b65fda8a323f228e139adb79a35d (patch) | |
| tree | 08baf40efb8fe103b32721cd991ff712323e3173 /internal/security/credentials.go | |
Build AI gateway control plane and admin UI
Diffstat (limited to '')
| -rw-r--r-- | internal/security/credentials.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/security/credentials.go b/internal/security/credentials.go new file mode 100644 index 0000000..b55fb6b --- /dev/null +++ b/internal/security/credentials.go @@ -0,0 +1,57 @@ +package security + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "errors" + "fmt" + "io" +) + +type CredentialCipher struct { + aead cipher.AEAD +} + +func NewCredentialCipher(encodedKey string) (*CredentialCipher, error) { + key, err := base64.StdEncoding.DecodeString(encodedKey) + if err != nil { + return nil, fmt.Errorf("decode credential key: %w", err) + } + if len(key) != 32 { + return nil, errors.New("credential key must be a base64-encoded 32-byte key") + } + block, err := aes.NewCipher(key) + if err != nil { + return nil, fmt.Errorf("create credential cipher: %w", err) + } + aead, err := cipher.NewGCM(block) + if err != nil { + return nil, fmt.Errorf("create credential AEAD: %w", err) + } + return &CredentialCipher{aead: aead}, nil +} + +func (c *CredentialCipher) Encrypt(plaintext string) ([]byte, error) { + if plaintext == "" { + return nil, errors.New("credential cannot be empty") + } + nonce := make([]byte, c.aead.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { + return nil, fmt.Errorf("generate credential nonce: %w", err) + } + return c.aead.Seal(nonce, nonce, []byte(plaintext), nil), nil +} + +func (c *CredentialCipher) Decrypt(ciphertext []byte) (string, error) { + if len(ciphertext) < c.aead.NonceSize() { + return "", errors.New("credential ciphertext is truncated") + } + nonce := ciphertext[:c.aead.NonceSize()] + plaintext, err := c.aead.Open(nil, nonce, ciphertext[c.aead.NonceSize():], nil) + if err != nil { + return "", errors.New("decrypt credential: authentication failed") + } + return string(plaintext), nil +} |
