Enchantrix/pkg/keyserver/interface.go
Claude 447f3ccaca
feat: add Keyserver Secure Environment (SE) for key isolation
Introduces an in-process keyserver that holds cryptographic key material
and exposes operations by opaque key ID — callers (including AI agents)
never see raw key bytes.

New packages:
- pkg/keystore: Trix-based encrypted key store with Argon2id master key
- pkg/keyserver: KeyServer interface, composite crypto ops, session/ACL,
  audit logging

New CLI commands:
- trix keystore init/import/generate/list/delete
- trix keyserver start, trix keyserver session create

Specification: RFC-0005-Keyserver-Secure-Environment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 21:30:31 +00:00

87 lines
3.8 KiB
Go

// Package keyserver provides a Secure Environment (SE) service that performs
// cryptographic operations by key reference. Callers never see raw key material;
// they pass a key ID and the server performs the operation internally.
package keyserver
import (
"context"
"github.com/Snider/Enchantrix/pkg/keystore"
)
// KeyServer defines the interface for a key management and crypto operations
// service. All operations reference keys by ID — raw key material never leaves
// the server boundary.
type KeyServer interface {
// --- Key lifecycle ---
// GenerateKey creates a new random key of the specified type and stores it.
// Returns the key ID for future reference.
GenerateKey(ctx context.Context, keyType keystore.KeyType, label string) (keyID string, err error)
// ImportPassword derives a symmetric key from a password (SHA-256, matching
// Borg's DeriveKey) and stores the derived key. The raw password is never
// persisted.
ImportPassword(ctx context.Context, password string, label string) (keyID string, err error)
// DeleteKey removes a key from the store and zeroes its material.
DeleteKey(ctx context.Context, keyID string) error
// ListKeys returns metadata for all stored keys. KeyData is never included.
ListKeys(ctx context.Context) ([]keystore.Entry, error)
// GetPublicKey returns the public component of an asymmetric key.
// Returns an error for symmetric key types.
GetPublicKey(ctx context.Context, keyID string) ([]byte, error)
// --- Primitive crypto operations ---
// Encrypt encrypts plaintext using the key identified by keyID.
Encrypt(ctx context.Context, keyID string, plaintext []byte) ([]byte, error)
// Decrypt decrypts ciphertext using the key identified by keyID.
Decrypt(ctx context.Context, keyID string, ciphertext []byte) ([]byte, error)
// Sign signs data using the key identified by keyID (HMAC for symmetric keys).
Sign(ctx context.Context, keyID string, data []byte) ([]byte, error)
// Verify verifies a signature against data using the key identified by keyID.
Verify(ctx context.Context, keyID string, data, signature []byte) error
// --- TIM composite operations (Borg calls these) ---
// EncryptTIM encrypts a TIM's config and rootfs atomically with the same key.
// The key never leaves the server boundary.
EncryptTIM(ctx context.Context, keyID string, config []byte, rootfs []byte) ([]byte, error)
// DecryptTIM decrypts a TIM payload back into config and rootfs.
DecryptTIM(ctx context.Context, keyID string, payload []byte) (config []byte, rootfs []byte, err error)
// --- SMSG composite operations ---
// EncryptSMSG encrypts a message payload using the key identified by keyID.
EncryptSMSG(ctx context.Context, keyID string, message []byte) ([]byte, error)
// DecryptSMSG decrypts a message payload using the key identified by keyID.
DecryptSMSG(ctx context.Context, keyID string, ciphertext []byte) ([]byte, error)
// --- Stream key derivation (for SMSG V3) ---
// DeriveStreamKey derives a stream key from license+date+fingerprint and
// stores it temporarily. Returns the key ID.
DeriveStreamKey(ctx context.Context, license, date, fingerprint string) (keyID string, err error)
// WrapCEK wraps a Content Encryption Key with the stream key identified
// by streamKeyID. Returns a base64-encoded wrapped key.
WrapCEK(ctx context.Context, streamKeyID string, cek []byte) (string, error)
// UnwrapCEK unwraps a Content Encryption Key using the stream key.
// Takes base64-encoded wrapped key, returns raw CEK bytes.
UnwrapCEK(ctx context.Context, streamKeyID string, wrapped string) ([]byte, error)
// --- STMF composite operations ---
// DecryptSTMF performs ECDH with the server's private key and the ephemeral
// public key embedded in the STMF payload, then decrypts the form data.
DecryptSTMF(ctx context.Context, keyID string, stmfPayload []byte) ([]byte, error)
}