Documentation
¶
Overview ¶
Package crypto provides envelope encryption (AES-256-GCM, per-record DEK) for sensitive data such as secret headers and webhook secrets.
The Key Encryption Key (KEK) is loaded from the SPARROW_ENCRYPTION_KEY environment variable (64 hex chars = 32 bytes). This is required -- the server will not start without it.
Envelope Encryption ¶
Each Encrypt call generates a random 256-bit Data Encryption Key (DEK), encrypts the plaintext with the DEK, then wraps (encrypts) the DEK with the KEK. This enables efficient key rotation: re-wrap every DEK with the new KEK without touching the (potentially large) data.
Backward Compatibility ¶
Decrypt auto-detects envelope-encrypted data (version prefix 0x01). If the prefix is absent, it falls back to legacy direct AES-256-GCM decryption so that data encrypted before the envelope migration is still readable.
When no encryption key is configured, any attempt to encrypt or decrypt returns ErrNoEncryptionKey.
Index ¶
- Variables
- func GenerateKey() (string, []byte, error)
- func IsEnvelopeEncrypted(ciphertext []byte) bool
- func ParseKey(raw string) ([]byte, error)
- type Service
- func (s *Service) Decrypt(ciphertext []byte) ([]byte, error)
- func (s *Service) DecryptJSON(ciphertext []byte, v any) error
- func (s *Service) DecryptString(ciphertext []byte) (string, error)
- func (s *Service) Enabled() bool
- func (s *Service) Encrypt(plaintext []byte) ([]byte, error)
- func (s *Service) EncryptJSON(v any) ([]byte, error)
- func (s *Service) EncryptString(plaintext string) ([]byte, error)
- func (s *Service) EnvelopeDecrypt(ciphertext []byte) ([]byte, error)
- func (s *Service) EnvelopeEncrypt(plaintext []byte) ([]byte, error)
Constants ¶
This section is empty.
Variables ¶
var ErrNoEncryptionKey = errors.New("crypto: encryption key not configured (set SPARROW_ENCRYPTION_KEY)")
ErrNoEncryptionKey is returned when encryption/decryption is attempted without a configured encryption key.
Functions ¶
func GenerateKey ¶ added in v0.5.0
GenerateKey generates a cryptographically random 32-byte key and returns it as a 64-character hex string suitable for SPARROW_ENCRYPTION_KEY. This is primarily used in tests; production deployments should generate keys externally via: openssl rand -hex 32
func IsEnvelopeEncrypted ¶ added in v0.5.0
IsEnvelopeEncrypted reports whether ciphertext appears to be envelope-encrypted. It checks the version byte and structural validity without attempting decryption.
Types ¶
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides encrypt/decrypt operations using envelope encryption (per-record DEK wrapped with a KEK). A nil *Service or one created without a key is valid — calls return ErrNoEncryptionKey.
func NewService ¶
NewService creates a new crypto service from a 32-byte AES-256 key (the KEK). Pass nil to create a no-op service that returns ErrNoEncryptionKey on use.
func (*Service) Decrypt ¶
Decrypt decrypts ciphertext, auto-detecting the format:
- Envelope format (version 0x01 prefix): uses envelope decryption
- Legacy format (no prefix): falls back to direct AES-256-GCM
This ensures backward compatibility during migration from direct to envelope encryption.
func (*Service) DecryptJSON ¶
DecryptJSON decrypts ciphertext (auto-detecting format) and unmarshals into v.
func (*Service) DecryptString ¶ added in v0.5.0
DecryptString decrypts ciphertext back to a plaintext string. Returns "" if the input is nil/empty.
func (*Service) Encrypt ¶
Encrypt encrypts plaintext using envelope encryption (per-record DEK). New data is always written in envelope format.
func (*Service) EncryptJSON ¶
EncryptJSON marshals v to JSON, then encrypts using envelope encryption.
func (*Service) EncryptString ¶ added in v0.5.0
EncryptString encrypts a plaintext string and returns the ciphertext bytes. Returns nil if the input is empty.
func (*Service) EnvelopeDecrypt ¶ added in v0.5.0
EnvelopeDecrypt decrypts data produced by EnvelopeEncrypt. It unwraps the DEK using the KEK, then decrypts the data with the DEK.
func (*Service) EnvelopeEncrypt ¶ added in v0.5.0
EnvelopeEncrypt encrypts plaintext using envelope encryption:
- Generates a random 256-bit DEK (Data Encryption Key)
- Encrypts the plaintext with the DEK using AES-256-GCM
- Encrypts (wraps) the DEK with the KEK (Key Encryption Key, held by Service)
Wire format:
[0x01] [edek_len:2 LE] [encrypted_dek:edek_len] [data_nonce:12] [data_ciphertext+tag]