package secret import ( "crypto/aes" "crypto/cipher" "errors" "golang.org/x/crypto/chacha20poly1305" ) type aead struct { Provider aead cipher.AEAD } // WithChaCha20Poly1305 wraps the returned value and decrypts it using ChaCha20-Poly1305 AEAD. // // The used nonce size is 12 bytes. func WithChaCha20Poly1305(p Provider, key []byte) (Provider, error) { cipher, err := chacha20poly1305.New(key) if err != nil { return nil, err } return aead{ Provider: p, aead: cipher, }, nil } // WithChaCha20Poly1305X wraps the returned value and decrypts it using ChaCha20-Poly1305 AEAD. // // The used nonce size is 24 bytes. func WithChaCha20Poly1305X(p Provider, key []byte) (Provider, error) { cipher, err := chacha20poly1305.NewX(key) if err != nil { return nil, err } return aead{ Provider: p, aead: cipher, }, nil } // WithAESGCM wraps the returned value and decrypts it using AES GCM AEAD. // // The accepted key sizes are 16 bytes for AES-128 and 32 bytes for AES-256. func WithAESGCM(p Provider, key []byte) (Provider, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(block) if err != nil { return nil, err } return aead{ Provider: p, aead: gcm, }, nil } func (p aead) GetSecret(key string) (value []byte, err error) { if value, err = p.Provider.GetSecret(key); err != nil { return } nonceSize := p.aead.NonceSize() if len(value) < nonceSize { return nil, errors.New("secret: ciphertext is too short") } nonce, ciphertext := value[:nonceSize], value[nonceSize:] return p.aead.Open(nil, nonce, ciphertext, nil) }