chore: auto-commit (23 archivos)
- app.md - backend/dist/assets/index-CFDWXN9Z.js - backend/dist/index.html - backend/handlers.go - backend/main.go - backend/users.go - e2e/smoke_live.sh - frontend/src/App.tsx - frontend/src/api.ts - frontend/src/components/CardChatPanel.tsx - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
const moduleKeyEnv = "KANBAN_MODULE_KEY"
|
||||
|
||||
// moduleKey derives a 32-byte AES key from the KANBAN_MODULE_KEY env var.
|
||||
// Returns (key, true) when present; (zero, false) when missing — callers
|
||||
// must treat that as "module dispatcher disabled".
|
||||
func moduleKey() ([32]byte, bool) {
|
||||
v := os.Getenv(moduleKeyEnv)
|
||||
if v == "" {
|
||||
return [32]byte{}, false
|
||||
}
|
||||
return sha256.Sum256([]byte(v)), true
|
||||
}
|
||||
|
||||
// encryptConfig encrypts a JSON config blob with AES-GCM. Returns the
|
||||
// ciphertext and the 12-byte nonce. Caller persists both columns.
|
||||
func encryptConfig(plain []byte) (cipherOut, nonce []byte, err error) {
|
||||
key, ok := moduleKey()
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("%s not set; cannot encrypt module config", moduleKeyEnv)
|
||||
}
|
||||
block, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
nonce = make([]byte, gcm.NonceSize())
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
cipherOut = gcm.Seal(nil, nonce, plain, nil)
|
||||
return cipherOut, nonce, nil
|
||||
}
|
||||
|
||||
// decryptConfig is the inverse of encryptConfig.
|
||||
func decryptConfig(cipherIn, nonce []byte) ([]byte, error) {
|
||||
key, ok := moduleKey()
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s not set; cannot decrypt module config", moduleKeyEnv)
|
||||
}
|
||||
if len(nonce) == 0 {
|
||||
return nil, errors.New("nonce empty")
|
||||
}
|
||||
block, err := aes.NewCipher(key[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gcm.Open(nil, nonce, cipherIn, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user