secrets

package
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package secrets provides AES-256-GCM encryption with compound key derivation for tenant-isolated data encryption in multi-tenant SaaS applications.

A compound key model combines an application key and a workspace key via HKDF (RFC 5869) to derive unique encryption keys per tenant. Identical plaintext encrypted for different workspaces produces entirely different ciphertext, providing cryptographic tenant isolation.

Usage

Generate keys and encrypt data:

appKey, err := secrets.GenerateKey()
if err != nil {
	log.Fatal(err)
}
workspaceKey, err := secrets.GenerateKey()
if err != nil {
	log.Fatal(err)
}

encrypted, err := secrets.EncryptString("sensitive data", appKey, workspaceKey)
if err != nil {
	log.Fatal(err)
}

decrypted, err := secrets.DecryptString(encrypted, appKey, workspaceKey)
if err != nil {
	log.Fatal(err)
}

Binary data:

sealed, err := secrets.EncryptBytes(data, appKey, workspaceKey)
if err != nil {
	log.Fatal(err)
}

plain, err := secrets.DecryptBytes(sealed, appKey, workspaceKey)
if err != nil {
	log.Fatal(err)
}

Tenant Isolation

Different workspace keys produce different ciphertext for the same plaintext:

enc1, _ := secrets.EncryptString("hello", appKey, workspaceKey1)
enc2, _ := secrets.EncryptString("hello", appKey, workspaceKey2)
// enc1 != enc2 — different derived keys
// Decrypting enc1 with workspaceKey2 fails

Security Properties

Key requirements:

  • Both appKey and workspaceKey must be exactly 32 bytes (256 bits)
  • Generate keys using GenerateKey (crypto/rand backed)
  • Store keys securely (environment variables, key management service)

Encryption:

  • AES-256-GCM provides authenticated encryption (confidentiality + integrity)
  • Unique random nonce generated per encryption operation
  • HKDF-SHA256 derives per-tenant keys from compound key material
  • Derived key material is zeroed after use
  • Ciphertext tampering is detected during decryption

Error Handling

All errors can be checked with errors.Is:

Errors are joined so both the operation and cause can be matched:

_, err := secrets.EncryptString("data", shortKey, workspaceKey)
errors.Is(err, secrets.ErrEncryptionFailed)  // true
errors.Is(err, secrets.ErrInvalidAppKey)      // true

Index

Constants

View Source
const (
	// KeySize is the required size in bytes for both app and workspace keys (AES-256).
	KeySize = 32
)

Variables

View Source
var (
	ErrInvalidAppKey       = errors.New("secrets: invalid app key, must be 32 bytes")
	ErrInvalidWorkspaceKey = errors.New("secrets: invalid workspace key, must be 32 bytes")
	ErrEncryptionFailed    = errors.New("secrets: encryption failed")
	ErrDecryptionFailed    = errors.New("secrets: decryption failed")
	ErrInvalidCiphertext   = errors.New("secrets: invalid ciphertext")
	ErrKeyGenerationFailed = errors.New("secrets: key generation failed")
	ErrKeyDerivationFailed = errors.New("secrets: key derivation failed")
)

Functions

func DecryptBytes

func DecryptBytes(data, appKey, workspaceKey []byte) ([]byte, error)

DecryptBytes decrypts data using AES-256-GCM with a key derived from appKey and workspaceKey via HKDF. Expects the nonce prepended to the ciphertext (as produced by EncryptBytes).

func DecryptString

func DecryptString(ciphertext string, appKey, workspaceKey []byte) (string, error)

DecryptString decrypts a base64-encoded ciphertext using AES-256-GCM with a key derived from appKey and workspaceKey via HKDF.

func EncryptBytes

func EncryptBytes(data, appKey, workspaceKey []byte) ([]byte, error)

EncryptBytes encrypts data using AES-256-GCM with a key derived from appKey and workspaceKey via HKDF. Returns the nonce prepended to the ciphertext.

func EncryptString

func EncryptString(plaintext string, appKey, workspaceKey []byte) (string, error)

EncryptString encrypts plaintext using AES-256-GCM with a key derived from appKey and workspaceKey via HKDF. Returns a base64-encoded ciphertext string.

func GenerateKey

func GenerateKey() ([]byte, error)

GenerateKey generates a cryptographically secure random key suitable for use as an app key or workspace key. The returned key is exactly KeySize (32) bytes.

func ValidateKeys

func ValidateKeys(appKey, workspaceKey []byte) error

ValidateKeys checks that both appKey and workspaceKey are exactly KeySize bytes.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL