package agentapi import ( "crypto/rand" "encoding/base64" "sync/atomic" "time" "github.com/rs/zerolog/log" "github.com/yusing/godoxy/agent/pkg/agent" ) type PEMPairResponse struct { Cert string `json:"cert" format:"base64"` Key string `json:"key" format:"base64"` } // @name PEMPairResponse var encryptionKey atomic.Value const rotateKeyInterval = 15 * time.Minute func init() { if err := rotateKey(); err != nil { log.Panic().Err(err).Msg("failed to generate encryption key") } go func() { for range time.Tick(rotateKeyInterval) { if err := rotateKey(); err != nil { log.Error().Err(err).Msg("failed to rotate encryption key") } } }() } func getEncryptionKey() []byte { return encryptionKey.Load().([]byte) } func rotateKey() error { // generate a random 32 bytes key key := make([]byte, 32) if _, err := rand.Read(key); err != nil { return err } encryptionKey.Store(key) return nil } func toPEMPairResponse(encPEMPair agent.PEMPair) PEMPairResponse { return PEMPairResponse{ Cert: base64.StdEncoding.EncodeToString(encPEMPair.Cert), Key: base64.StdEncoding.EncodeToString(encPEMPair.Key), } } func fromEncryptedPEMPairResponse(pemPair PEMPairResponse) (agent.PEMPair, error) { encCert, err := base64.StdEncoding.DecodeString(pemPair.Cert) if err != nil { return agent.PEMPair{}, err } encKey, err := base64.StdEncoding.DecodeString(pemPair.Key) if err != nil { return agent.PEMPair{}, err } pair := agent.PEMPair{Cert: encCert, Key: encKey} return pair.Decrypt(getEncryptionKey()) }