keys_manager

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Dec 6, 2025 License: MIT Imports: 19 Imported by: 0

README ΒΆ

πŸ” Key Manager Library

A lightweight, extensible, production-ready key management subsystem designed for applications that require:

  • secure storage of private keys
  • automated and manual key rotation
  • in-memory caching of active keys
  • cryptographic signing and verification
  • publishing public keys in JWK/JWKS format
  • pluggable encryption and storage backends

The library focuses on security, simplicity, and clean separation of concerns.


✨ Features

πŸ”Έ Secure storage of private keys

All private keys are stored only in encrypted form using a pluggable Encryptor interface. A built-in AES-256-GCM encryptor is included out of the box.

πŸ”Έ Automated and manual key rotation

The KeyManager supports two rotation workflows:

  • Manual rotation per algorithm (Rotate(alg))
  • Automatic rotation for expired keys during cache reload (ReloadCache())

Rotation policies (TTL, metadata, future constraints) are provided via a user-defined RotationPolicy function.

πŸ”Έ In-memory key cache

To avoid unnecessary decryption and database access, the manager maintains two caches:

  • cache[kid] β€” all known keys
  • active[alg] β€” currently active signing key per algorithm

Caches are fully rebuilt during ReloadCache().

πŸ”Έ Signing and verification

The manager supports signing and verification using:

  • RSA (RS256)
  • ECDSA P-256 (ES256)
  • Ed25519 (EdDSA)

The design keeps signing and verification algorithm-agnostic, relying on Go’s crypto.Signer interfaces.

πŸ”Έ Public key export (JWKS)

The manager can produce a JWKS document containing all public keys stored in the system.

πŸ”Έ Pluggable backends

The following interfaces allow full customization:

Interface Purpose
Store Storage of encrypted private keys, metadata, key state
Encryptor Encryption/decryption of private keys at rest
RotationPolicy Defines TTL and rotation behavior

You can implement backends using files, SQL, Redis, Vault, KMS, HSM, or any other mechanism.

πŸ”Έ Included AES-256-GCM encryptor

The package ships with a secure AES-GCM based encryptor:

  • takes a 32-byte master key
  • encrypts/decrypts PKCS8 private keys
  • uses random nonces
  • authenticated encryption (AEAD)

This enables safe use in Kubernetes by storing the master key as a base64-encoded secret.


πŸ“¦ Installation

go get github.com/keylet-auth/keys-manager

πŸš€ Quick Start

1. Create an Encryptor (AES-GCM)
masterKey := mustLoad32ByteKeyFromEnv()
encryptor, err := NewAESGCMEncryptor(masterKey)
2. Provide a Store implementation

Example: a simple in-memory or database-backed store implementing:

type Store interface {
    Save(key *Key) error
    List() ([]*Key, error)
    GetByKID(kid string) (*Key, error)
    Rotate(newKey *Key, oldKey *Key) error
}
3. Create a KeyManager
km, err := NewKeyManager(store, encryptor, func() (RotationConfig, error) {
    return RotationConfig{TTL: time.Hour * 24}, nil
})
4. Rotate keys
if err := km.Rotate(AlgRS256); err != nil {
    log.Fatal(err)
}
5. Sign or verify data
sig, err := km.Sign(AlgRS256, data)
err = km.Verify(kid, AlgRS256, data, sig)
6. Export public keys (JWKS)
jwksJSON, _ := km.JWKS()

πŸ”§ Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          KeyManager          β”‚
β”‚------------------------------β”‚
β”‚ - caches active keys         β”‚
β”‚ - loads from Store           β”‚
β”‚ - decrypts via Encryptor     β”‚
β”‚ - rotates keys automatically β”‚
β”‚ - exposes sign/verify        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β–Ό                     β–Ό
Encryptor            Store
AES-GCM (built-in)   DB / Redis / Vault / KMS / FS / custom

The KeyManager itself does not store any unencrypted private keys on disk, and does not control where or how keys are persisted β€” this is delegated to the Store.

πŸ”’ Included AES-GCM Encryptor

The library contains a production-grade implementation:

  • AES-256-GCM
  • random per-encryption nonce
  • authenticated encryption
  • works with raw PKCS8 private key bytes
  • deterministic decryption
  • safe failure modes

Master key storage example for Kubernetes:

kubectl create secret generic key-manager-secret \
  --from-literal=MASTER_KEY=$(openssl rand -base64 32)

and then mount via env or file.


πŸ§ͺ Testing

The library includes a rich test suite covering:

  • signing & verification
  • rotation logic
  • cache rebuilding
  • AES-GCM encryption/decryption
  • corrupted data handling
  • time-based expiration checks

πŸ›  Extending the Library

You can:

  • add new algorithms
  • integrate external KMS/HSM
  • implement multi-region Stores
  • version encryption keys
  • implement master-key rotation
  • publish JWKS for distributed systems The architecture is intentionally modular and easy to extend.

πŸ“„ License

MIT License.


πŸ€– Note

This README was assisted/generated by AI

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func DERToRawECDSA ΒΆ added in v0.0.6

func DERToRawECDSA(alg Alg, der []byte) ([]byte, error)

Types ΒΆ

type AESGCMEncryptor ΒΆ

type AESGCMEncryptor struct {
	// contains filtered or unexported fields
}

func NewAESGCMEncryptor ΒΆ

func NewAESGCMEncryptor(masterKey []byte) (*AESGCMEncryptor, error)

func (*AESGCMEncryptor) Decrypt ΒΆ

func (e *AESGCMEncryptor) Decrypt(enc *EncryptedKey) ([]byte, error)

func (*AESGCMEncryptor) Encrypt ΒΆ

func (e *AESGCMEncryptor) Encrypt(privateKey []byte) (*EncryptedKey, error)

type Alg ΒΆ

type Alg string
const (
	AlgRS256 Alg = "RS256"
	AlgES256 Alg = "ES256"
	AlgEdDSA Alg = "EdDSA"
)

type CachedKey ΒΆ

type CachedKey struct {
	// contains filtered or unexported fields
}

type EncryptedKey ΒΆ

type EncryptedKey struct {
	Nonce      []byte
	Ciphertext []byte
}

type Encryptor ΒΆ

type Encryptor interface {
	Encrypt(privateKey []byte) (*EncryptedKey, error)
	Decrypt(encrypted *EncryptedKey) ([]byte, error)
}

type JWK ΒΆ

type JWK struct {
	Kty string `json:"kty"`
	Kid string `json:"kid"`
	Alg string `json:"alg"`
	Use string `json:"use,omitempty"`

	N string `json:"n,omitempty"`
	E string `json:"e,omitempty"`

	Crv string `json:"crv,omitempty"`
	X   string `json:"x,omitempty"`
	Y   string `json:"y,omitempty"`
}

type JWKS ΒΆ

type JWKS struct {
	Keys []JWK `json:"keys"`
}

type Key ΒΆ

type Key struct {
	KID          string
	Alg          Alg
	IsActive     bool
	CreatedAt    time.Time
	ExpiresAt    *time.Time
	EncryptedKey *EncryptedKey
}

type KeyManager ΒΆ

type KeyManager struct {
	// contains filtered or unexported fields
}

func NewKeyManager ΒΆ

func NewKeyManager(
	store Store,
	enc Encryptor,
	policy RotationPolicy,
) (*KeyManager, error)

func (*KeyManager) InitKeys ΒΆ added in v0.0.3

func (km *KeyManager) InitKeys(algs []Alg) error

func (*KeyManager) JWKS ΒΆ

func (km *KeyManager) JWKS() ([]byte, error)

func (*KeyManager) ReloadCache ΒΆ

func (km *KeyManager) ReloadCache() error

func (*KeyManager) Rotate ΒΆ

func (km *KeyManager) Rotate(alg Alg) error

func (*KeyManager) RotateExpired ΒΆ

func (km *KeyManager) RotateExpired() error

func (*KeyManager) Sign ΒΆ

func (km *KeyManager) Sign(
	alg Alg,
	build func(kid string) ([]byte, error),
) ([]byte, error)

func (*KeyManager) Verify ΒΆ

func (km *KeyManager) Verify(kid string, payload, sig []byte) error

type MockEncryptor ΒΆ

type MockEncryptor struct {
	ForceDecryptError bool
}

func (MockEncryptor) Decrypt ΒΆ

func (m MockEncryptor) Decrypt(e *EncryptedKey) ([]byte, error)

func (MockEncryptor) Encrypt ΒΆ

func (m MockEncryptor) Encrypt(b []byte) (*EncryptedKey, error)

type MockStore ΒΆ

type MockStore struct {
	RotateCount int
	RotateErr   error
	// contains filtered or unexported fields
}

func NewMockStore ΒΆ

func NewMockStore() *MockStore

func (*MockStore) List ΒΆ

func (s *MockStore) List() ([]*Key, error)

func (*MockStore) Rotate ΒΆ

func (s *MockStore) Rotate(newKey *Key, old *Key) error

func (*MockStore) Save ΒΆ

func (s *MockStore) Save(key *Key) error

type RotationConfig ΒΆ

type RotationConfig struct {
	TTL time.Duration
}

type RotationPolicy ΒΆ

type RotationPolicy func() (RotationConfig, error)

type Store ΒΆ

type Store interface {
	List() ([]*Key, error)
	Rotate(newKey *Key, oldKey *Key) error
}

Jump to

Keyboard shortcuts

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