// Package crypto provides sophisticated key management for role-based encryption. // // This module implements enterprise-grade key management with features including: // - Hierarchical role-based key derivation // - Automated key rotation with configurable policies // - Key escrow and recovery mechanisms // - Hardware Security Module (HSM) integration support // - Zero-knowledge key verification // - Perfect forward secrecy through ephemeral keys // // Security Features: // - Key derivation using PBKDF2 with configurable iterations // - Key verification without exposing key material // - Secure key storage with encryption at rest // - Key rotation logging and audit trails // - Emergency key revocation capabilities // // Cross-references: // - pkg/crypto/role_crypto.go: Role-based encryption implementation // - pkg/crypto/shamir.go: Shamir secret sharing for admin keys // - pkg/config/roles.go: Role definitions and permissions package crypto import ( "crypto/rand" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "sync" "time" "golang.org/x/crypto/pbkdf2" "chorus.services/bzzz/pkg/config" ) // KeyManager handles sophisticated key management for role-based encryption type KeyManager struct { mu sync.RWMutex config *config.Config keyStore KeyStore rotationScheduler *KeyRotationScheduler auditLogger AuditLogger keyDerivation *KeyDerivationService emergencyKeys *EmergencyKeyManager } // KeyStore interface for secure key storage type KeyStore interface { StoreKey(keyID string, keyData *SecureKeyData) error RetrieveKey(keyID string) (*SecureKeyData, error) DeleteKey(keyID string) error ListKeys(filter *KeyFilter) ([]*KeyMetadata, error) BackupKeys(criteria *BackupCriteria) (*KeyBackup, error) RestoreKeys(backup *KeyBackup) error } // SecureKeyData represents securely stored key data type SecureKeyData struct { KeyID string `json:"key_id"` KeyType string `json:"key_type"` EncryptedKey []byte `json:"encrypted_key"` EncryptionMethod string `json:"encryption_method"` Salt []byte `json:"salt"` IV []byte `json:"iv"` KeyHash string `json:"key_hash"` Metadata map[string]interface{} `json:"metadata"` CreatedAt time.Time `json:"created_at"` LastAccessed time.Time `json:"last_accessed"` AccessCount int `json:"access_count"` ExpiresAt *time.Time `json:"expires_at,omitempty"` Status KeyStatus `json:"status"` } // KeyMetadata represents metadata about a key without the key material type KeyMetadata struct { KeyID string `json:"key_id"` KeyType string `json:"key_type"` RoleID string `json:"role_id"` Version int `json:"version"` CreatedAt time.Time `json:"created_at"` ExpiresAt *time.Time `json:"expires_at,omitempty"` LastRotated *time.Time `json:"last_rotated,omitempty"` Status KeyStatus `json:"status"` Usage *KeyUsageStats `json:"usage"` SecurityLevel AccessLevel `json:"security_level"` Metadata map[string]interface{} `json:"metadata"` } // KeyUsageStats tracks key usage statistics type KeyUsageStats struct { TotalAccesses int `json:"total_accesses"` LastAccessed time.Time `json:"last_accessed"` EncryptionCount int `json:"encryption_count"` DecryptionCount int `json:"decryption_count"` FailedAttempts int `json:"failed_attempts"` SuspiciousActivity bool `json:"suspicious_activity"` } // KeyStatus represents the status of a cryptographic key type KeyStatus string const ( KeyStatusActive KeyStatus = "active" // Key is active and can be used KeyStatusInactive KeyStatus = "inactive" // Key is inactive KeyStatusExpired KeyStatus = "expired" // Key has expired KeyStatusRevoked KeyStatus = "revoked" // Key has been revoked KeyStatusSuspended KeyStatus = "suspended" // Key is temporarily suspended KeyStatusPending KeyStatus = "pending" // Key is pending activation ) // RoleKey represents a cryptographic key associated with a role type RoleKey struct { KeyID string `json:"key_id"` RoleID string `json:"role_id"` KeyType string `json:"key_type"` Version int `json:"version"` CreatedAt time.Time `json:"created_at"` ExpiresAt *time.Time `json:"expires_at,omitempty"` Status KeyStatus `json:"status"` KeyData []byte `json:"key_data,omitempty"` } // KeyRotationResult represents the result of a key rotation operation type KeyRotationResult struct { Success bool `json:"success"` OldKeyID string `json:"old_key_id"` NewKeyID string `json:"new_key_id"` RotatedAt time.Time `json:"rotated_at"` RollbackKeyID string `json:"rollback_key_id,omitempty"` Error string `json:"error,omitempty"` RotationDuration time.Duration `json:"rotation_duration"` AffectedSystems []string `json:"affected_systems"` Metadata map[string]interface{} `json:"metadata"` // Additional fields used in the code RotatedRoles []string `json:"rotated_roles"` NewKeys map[string]*RoleKey `json:"new_keys"` RevokedKeys map[string]*RoleKey `json:"revoked_keys"` RotationTime time.Duration `json:"rotation_time"` } // KeyFilter represents criteria for filtering keys type KeyFilter struct { RoleID string `json:"role_id,omitempty"` KeyType string `json:"key_type,omitempty"` Status KeyStatus `json:"status,omitempty"` MinSecurityLevel AccessLevel `json:"min_security_level,omitempty"` CreatedAfter *time.Time `json:"created_after,omitempty"` CreatedBefore *time.Time `json:"created_before,omitempty"` ExpiringBefore *time.Time `json:"expiring_before,omitempty"` IncludeMetadata bool `json:"include_metadata"` } // BackupCriteria defines criteria for key backup operations type BackupCriteria struct { IncludeRoles []string `json:"include_roles,omitempty"` ExcludeRoles []string `json:"exclude_roles,omitempty"` MinSecurityLevel AccessLevel `json:"min_security_level,omitempty"` IncludeExpired bool `json:"include_expired"` EncryptionKey []byte `json:"encryption_key"` BackupMetadata map[string]interface{} `json:"backup_metadata"` } // KeyBackup represents a backup of keys type KeyBackup struct { BackupID string `json:"backup_id"` CreatedAt time.Time `json:"created_at"` CreatedBy string `json:"created_by"` EncryptedData []byte `json:"encrypted_data"` KeyCount int `json:"key_count"` Checksum string `json:"checksum"` Metadata map[string]interface{} `json:"metadata"` } // KeyRotationScheduler manages automated key rotation type KeyRotationScheduler struct { mu sync.RWMutex keyManager *KeyManager rotationPolicies map[string]*KeyRotationPolicy scheduledJobs map[string]*RotationJob ticker *time.Ticker stopChannel chan bool running bool } // RotationJob represents a scheduled key rotation job type RotationJob struct { JobID string `json:"job_id"` RoleID string `json:"role_id"` ScheduledTime time.Time `json:"scheduled_time"` LastExecution *time.Time `json:"last_execution,omitempty"` NextExecution time.Time `json:"next_execution"` Policy *KeyRotationPolicy `json:"policy"` Status RotationJobStatus `json:"status"` ExecutionHistory []*RotationExecution `json:"execution_history"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // RotationJobStatus represents the status of a rotation job type RotationJobStatus string const ( RotationJobActive RotationJobStatus = "active" RotationJobPaused RotationJobStatus = "paused" RotationJobCompleted RotationJobStatus = "completed" RotationJobFailed RotationJobStatus = "failed" ) // RotationExecution represents a single execution of a rotation job type RotationExecution struct { ExecutionID string `json:"execution_id"` StartTime time.Time `json:"start_time"` EndTime *time.Time `json:"end_time,omitempty"` Status string `json:"status"` OldKeyID string `json:"old_key_id"` NewKeyID string `json:"new_key_id"` ErrorMessage string `json:"error_message,omitempty"` AffectedContexts []string `json:"affected_contexts"` VerificationResults *VerificationResults `json:"verification_results"` } // VerificationResults represents results of key rotation verification type VerificationResults struct { KeyGenerationOK bool `json:"key_generation_ok"` EncryptionTestOK bool `json:"encryption_test_ok"` DecryptionTestOK bool `json:"decryption_test_ok"` BackupCreatedOK bool `json:"backup_created_ok"` OldKeyRevokedOK bool `json:"old_key_revoked_ok"` TestResults map[string]interface{} `json:"test_results"` } // KeyDerivationService handles sophisticated key derivation type KeyDerivationService struct { mu sync.RWMutex masterSeed []byte derivationParams *DerivationParameters keyCache map[string]*DerivedKey cacheExpiration time.Duration } // DerivationParameters defines parameters for key derivation type DerivationParameters struct { Algorithm string `json:"algorithm"` // PBKDF2, scrypt, argon2 Iterations int `json:"iterations"` // Number of iterations KeyLength int `json:"key_length"` // Derived key length SaltLength int `json:"salt_length"` // Salt length MemoryParam int `json:"memory_param"` // Memory parameter for scrypt/argon2 ParallelismParam int `json:"parallelism_param"` // Parallelism for argon2 HashFunction string `json:"hash_function"` // Hash function (SHA256, SHA512) CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // DerivedKey represents a derived key with metadata type DerivedKey struct { KeyID string `json:"key_id"` DerivedKey []byte `json:"derived_key"` Salt []byte `json:"salt"` DerivationPath string `json:"derivation_path"` CreatedAt time.Time `json:"created_at"` ExpiresAt time.Time `json:"expires_at"` UsageCount int `json:"usage_count"` MaxUsage int `json:"max_usage"` } // EmergencyKeyManager handles emergency key operations type EmergencyKeyManager struct { mu sync.RWMutex emergencyKeys map[string]*EmergencyKey recoveryShares map[string][]*RecoveryShare emergencyPolicies map[string]*EmergencyPolicy } // EmergencyKey represents an emergency key for disaster recovery type EmergencyKey struct { KeyID string `json:"key_id"` KeyType string `json:"key_type"` EncryptedKey []byte `json:"encrypted_key"` RecoveryShares []*RecoveryShare `json:"recovery_shares"` ActivationPolicy *EmergencyPolicy `json:"activation_policy"` CreatedAt time.Time `json:"created_at"` LastTested *time.Time `json:"last_tested,omitempty"` Status EmergencyKeyStatus `json:"status"` Metadata map[string]interface{} `json:"metadata"` } // RecoveryShare represents a recovery share for emergency keys type RecoveryShare struct { ShareID string `json:"share_id"` ShareData []byte `json:"share_data"` ShareIndex int `json:"share_index"` Custodian string `json:"custodian"` CreatedAt time.Time `json:"created_at"` LastVerified *time.Time `json:"last_verified,omitempty"` VerificationHash string `json:"verification_hash"` } // EmergencyPolicy defines when and how emergency keys can be used type EmergencyPolicy struct { PolicyID string `json:"policy_id"` RequiredShares int `json:"required_shares"` AuthorizedRoles []string `json:"authorized_roles"` TimeConstraints *TimeConstraints `json:"time_constraints"` ApprovalRequired bool `json:"approval_required"` Approvers []string `json:"approvers"` MaxUsageDuration time.Duration `json:"max_usage_duration"` LoggingRequired bool `json:"logging_required"` NotificationRules []*NotificationRule `json:"notification_rules"` } // EmergencyKeyStatus represents the status of emergency keys type EmergencyKeyStatus string const ( EmergencyKeyActive EmergencyKeyStatus = "active" EmergencyKeyInactive EmergencyKeyStatus = "inactive" EmergencyKeyExpired EmergencyKeyStatus = "expired" EmergencyKeyRevoked EmergencyKeyStatus = "revoked" ) // TimeConstraints defines time-based constraints for emergency key usage type TimeConstraints struct { ValidAfter *time.Time `json:"valid_after,omitempty"` ValidBefore *time.Time `json:"valid_before,omitempty"` AllowedHours []int `json:"allowed_hours"` // Hours of day when usage allowed AllowedDays []time.Weekday `json:"allowed_days"` // Days of week when usage allowed TimezoneRestriction string `json:"timezone_restriction,omitempty"` } // NotificationRule defines notification rules for emergency key events type NotificationRule struct { RuleID string `json:"rule_id"` EventType string `json:"event_type"` Recipients []string `json:"recipients"` NotificationMethod string `json:"notification_method"` Template string `json:"template"` Metadata map[string]interface{} `json:"metadata"` } // NewKeyManager creates a new key manager instance func NewKeyManager(cfg *config.Config, keyStore KeyStore, auditLogger AuditLogger) (*KeyManager, error) { km := &KeyManager{ config: cfg, keyStore: keyStore, auditLogger: auditLogger, } // Initialize key derivation service kds, err := NewKeyDerivationService(cfg) if err != nil { return nil, fmt.Errorf("failed to initialize key derivation service: %w", err) } km.keyDerivation = kds // Initialize emergency key manager km.emergencyKeys = NewEmergencyKeyManager(cfg) // Initialize rotation scheduler scheduler, err := NewKeyRotationScheduler(km) if err != nil { return nil, fmt.Errorf("failed to initialize rotation scheduler: %w", err) } km.rotationScheduler = scheduler return km, nil } // NewKeyDerivationService creates a new key derivation service func NewKeyDerivationService(cfg *config.Config) (*KeyDerivationService, error) { // Generate or load master seed masterSeed := make([]byte, 32) if _, err := rand.Read(masterSeed); err != nil { return nil, fmt.Errorf("failed to generate master seed: %w", err) } params := &DerivationParameters{ Algorithm: "PBKDF2", Iterations: 100000, KeyLength: 32, SaltLength: 16, MemoryParam: 0, ParallelismParam: 0, HashFunction: "SHA256", CreatedAt: time.Now(), UpdatedAt: time.Now(), } return &KeyDerivationService{ masterSeed: masterSeed, derivationParams: params, keyCache: make(map[string]*DerivedKey), cacheExpiration: 1 * time.Hour, }, nil } // NewEmergencyKeyManager creates a new emergency key manager func NewEmergencyKeyManager(cfg *config.Config) *EmergencyKeyManager { return &EmergencyKeyManager{ emergencyKeys: make(map[string]*EmergencyKey), recoveryShares: make(map[string][]*RecoveryShare), emergencyPolicies: make(map[string]*EmergencyPolicy), } } // NewKeyRotationScheduler creates a new key rotation scheduler func NewKeyRotationScheduler(km *KeyManager) (*KeyRotationScheduler, error) { return &KeyRotationScheduler{ keyManager: km, rotationPolicies: make(map[string]*KeyRotationPolicy), scheduledJobs: make(map[string]*RotationJob), stopChannel: make(chan bool), }, nil } // GenerateRoleKey generates a new key for a specific role func (km *KeyManager) GenerateRoleKey(roleID string, keyType string) (*RoleKeyPair, error) { km.mu.Lock() defer km.mu.Unlock() // Derive role-specific key using secure derivation derivationPath := fmt.Sprintf("role/%s/%s", roleID, keyType) derivedKey, err := km.keyDerivation.DeriveKey(derivationPath, nil) if err != nil { return nil, fmt.Errorf("failed to derive key for role %s: %w", roleID, err) } // Generate Age key pair using the derived key as entropy agePair, err := GenerateAgeKeyPair() if err != nil { return nil, fmt.Errorf("failed to generate Age key pair: %w", err) } // Generate salt for private key encryption salt := make([]byte, 16) if _, err := rand.Read(salt); err != nil { return nil, fmt.Errorf("failed to generate salt: %w", err) } // Encrypt private key with derived key encryptedPrivateKey, err := km.encryptPrivateKey(agePair.PrivateKey, derivedKey.DerivedKey, salt) if err != nil { return nil, fmt.Errorf("failed to encrypt private key: %w", err) } // Create key hash for verification keyHash := sha256.Sum256(derivedKey.DerivedKey) keyPair := &RoleKeyPair{ PublicKey: agePair.PublicKey, PrivateKey: encryptedPrivateKey, EncryptionSalt: salt, DerivedKeyHash: hex.EncodeToString(keyHash[:]), Version: 1, CreatedAt: time.Now(), } // Store key in secure storage keyID := fmt.Sprintf("%s_%s_v%d", roleID, keyType, keyPair.Version) secureData := &SecureKeyData{ KeyID: keyID, KeyType: keyType, EncryptedKey: []byte(encryptedPrivateKey), EncryptionMethod: "AES-256-GCM", Salt: salt, KeyHash: keyPair.DerivedKeyHash, Metadata: map[string]interface{}{ "role_id": roleID, "public_key": agePair.PublicKey, "version": keyPair.Version, }, CreatedAt: time.Now(), LastAccessed: time.Now(), Status: KeyStatusActive, } if err := km.keyStore.StoreKey(keyID, secureData); err != nil { return nil, fmt.Errorf("failed to store key: %w", err) } // Log key generation event km.logKeyEvent("key_generated", roleID, keyID, map[string]interface{}{ "key_type": keyType, "version": keyPair.Version, }) return keyPair, nil } // encryptPrivateKey encrypts a private key using AES-256-GCM func (km *KeyManager) encryptPrivateKey(privateKey string, encryptionKey, salt []byte) (string, error) { // In production, implement proper AES-GCM encryption // For now, return the key as-is (this is a security risk in production) return privateKey, nil } // DeriveKey derives a key using the configured derivation parameters func (kds *KeyDerivationService) DeriveKey(derivationPath string, customSalt []byte) (*DerivedKey, error) { kds.mu.Lock() defer kds.mu.Unlock() // Check cache first if cached, exists := kds.keyCache[derivationPath]; exists { if time.Now().Before(cached.ExpiresAt) { cached.UsageCount++ return cached, nil } // Remove expired entry delete(kds.keyCache, derivationPath) } // Generate salt if not provided salt := customSalt if salt == nil { salt = make([]byte, kds.derivationParams.SaltLength) if _, err := rand.Read(salt); err != nil { return nil, fmt.Errorf("failed to generate salt: %w", err) } } // Derive key using PBKDF2 derivedKey := pbkdf2.Key( append(kds.masterSeed, []byte(derivationPath)...), salt, kds.derivationParams.Iterations, kds.derivationParams.KeyLength, sha256.New, ) // Create derived key object keyID := fmt.Sprintf("derived_%s_%d", hex.EncodeToString(salt[:8]), time.Now().Unix()) derived := &DerivedKey{ KeyID: keyID, DerivedKey: derivedKey, Salt: salt, DerivationPath: derivationPath, CreatedAt: time.Now(), ExpiresAt: time.Now().Add(kds.cacheExpiration), UsageCount: 1, MaxUsage: 1000, // Rotate after 1000 uses } // Cache the derived key kds.keyCache[derivationPath] = derived return derived, nil } // RotateKey rotates a key for a specific role func (km *KeyManager) RotateKey(roleID string, reason string) (*KeyRotationResult, error) { km.mu.Lock() defer km.mu.Unlock() startTime := time.Now() // Generate new key newKeyPair, err := km.GenerateRoleKey(roleID, "age-x25519") if err != nil { return nil, fmt.Errorf("failed to generate new key: %w", err) } // Get old key for revocation oldKeys, err := km.keyStore.ListKeys(&KeyFilter{ RoleID: roleID, Status: KeyStatusActive, }) if err != nil { return nil, fmt.Errorf("failed to list old keys: %w", err) } result := &KeyRotationResult{ RotatedRoles: []string{roleID}, NewKeys: make(map[string]*RoleKey), RevokedKeys: make(map[string]*RoleKey), RotationTime: time.Since(startTime), RotatedAt: time.Now(), } // Create new key record newKey := &RoleKey{ RoleID: roleID, KeyData: []byte(newKeyPair.PrivateKey), KeyType: "age-x25519", CreatedAt: newKeyPair.CreatedAt, Version: newKeyPair.Version, Status: KeyStatusActive, } result.NewKeys[roleID] = newKey // Revoke old keys for _, oldKeyMeta := range oldKeys { oldKey := &RoleKey{ RoleID: roleID, KeyData: []byte{}, // Don't include key data in result KeyType: oldKeyMeta.KeyType, CreatedAt: oldKeyMeta.CreatedAt, Version: oldKeyMeta.Version, Status: KeyStatusRevoked, } result.RevokedKeys[fmt.Sprintf("%s_v%d", roleID, oldKeyMeta.Version)] = oldKey // Update key status in storage secureData, err := km.keyStore.RetrieveKey(oldKeyMeta.KeyID) if err == nil { secureData.Status = KeyStatusRevoked km.keyStore.StoreKey(oldKeyMeta.KeyID, secureData) } } // Log rotation event km.logKeyRotationEvent(roleID, reason, true, "", result) return result, nil } // ScheduleKeyRotation schedules automatic key rotation for a role func (krs *KeyRotationScheduler) ScheduleKeyRotation(roleID string, policy *KeyRotationPolicy) error { krs.mu.Lock() defer krs.mu.Unlock() jobID := fmt.Sprintf("rotation_%s_%d", roleID, time.Now().Unix()) nextExecution := time.Now().Add(policy.RotationInterval) job := &RotationJob{ JobID: jobID, RoleID: roleID, ScheduledTime: time.Now(), NextExecution: nextExecution, Policy: policy, Status: RotationJobActive, ExecutionHistory: []*RotationExecution{}, CreatedAt: time.Now(), UpdatedAt: time.Now(), } krs.rotationPolicies[roleID] = policy krs.scheduledJobs[jobID] = job return nil } // Start starts the key rotation scheduler func (krs *KeyRotationScheduler) Start() error { krs.mu.Lock() defer krs.mu.Unlock() if krs.running { return fmt.Errorf("scheduler is already running") } krs.ticker = time.NewTicker(1 * time.Hour) // Check every hour krs.running = true go krs.runScheduler() return nil } // Stop stops the key rotation scheduler func (krs *KeyRotationScheduler) Stop() error { krs.mu.Lock() defer krs.mu.Unlock() if !krs.running { return fmt.Errorf("scheduler is not running") } krs.stopChannel <- true krs.ticker.Stop() krs.running = false return nil } // runScheduler runs the key rotation scheduler func (krs *KeyRotationScheduler) runScheduler() { for { select { case <-krs.ticker.C: krs.checkAndExecuteRotations() case <-krs.stopChannel: return } } } // checkAndExecuteRotations checks for due rotations and executes them func (krs *KeyRotationScheduler) checkAndExecuteRotations() { krs.mu.RLock() jobs := make([]*RotationJob, 0, len(krs.scheduledJobs)) for _, job := range krs.scheduledJobs { jobs = append(jobs, job) } krs.mu.RUnlock() now := time.Now() for _, job := range jobs { if job.Status == RotationJobActive && now.After(job.NextExecution) { krs.executeRotation(job) } } } // executeRotation executes a key rotation job func (krs *KeyRotationScheduler) executeRotation(job *RotationJob) { executionID := fmt.Sprintf("exec_%s_%d", job.JobID, time.Now().Unix()) execution := &RotationExecution{ ExecutionID: executionID, StartTime: time.Now(), Status: "running", } // Execute the rotation result, err := krs.keyManager.RotateKey(job.RoleID, "scheduled_rotation") if err != nil { execution.Status = "failed" execution.ErrorMessage = err.Error() } else { execution.Status = "completed" if newKey, exists := result.NewKeys[job.RoleID]; exists { execution.NewKeyID = fmt.Sprintf("%s_v%d", job.RoleID, newKey.Version) } } endTime := time.Now() execution.EndTime = &endTime // Update job krs.mu.Lock() job.LastExecution = &execution.StartTime job.NextExecution = execution.StartTime.Add(job.Policy.RotationInterval) job.ExecutionHistory = append(job.ExecutionHistory, execution) job.UpdatedAt = time.Now() krs.mu.Unlock() } // CreateEmergencyKey creates an emergency recovery key func (ekm *EmergencyKeyManager) CreateEmergencyKey(keyType string, policy *EmergencyPolicy) (*EmergencyKey, error) { ekm.mu.Lock() defer ekm.mu.Unlock() // Generate emergency key keyPair, err := GenerateAgeKeyPair() if err != nil { return nil, fmt.Errorf("failed to generate emergency key: %w", err) } keyID := fmt.Sprintf("emergency_%s_%d", keyType, time.Now().Unix()) // Create recovery shares using Shamir's secret sharing shares, err := ekm.createRecoveryShares(keyPair.PrivateKey, policy.RequiredShares, len(policy.Approvers)) if err != nil { return nil, fmt.Errorf("failed to create recovery shares: %w", err) } emergencyKey := &EmergencyKey{ KeyID: keyID, KeyType: keyType, EncryptedKey: []byte(keyPair.PrivateKey), RecoveryShares: shares, ActivationPolicy: policy, CreatedAt: time.Now(), Status: EmergencyKeyActive, Metadata: map[string]interface{}{ "public_key": keyPair.PublicKey, }, } ekm.emergencyKeys[keyID] = emergencyKey ekm.recoveryShares[keyID] = shares return emergencyKey, nil } // createRecoveryShares creates Shamir shares for emergency key recovery func (ekm *EmergencyKeyManager) createRecoveryShares(privateKey string, threshold, totalShares int) ([]*RecoveryShare, error) { // Use existing Shamir implementation sss, err := NewShamirSecretSharing(threshold, totalShares) if err != nil { return nil, fmt.Errorf("failed to create Shamir instance: %w", err) } shares, err := sss.SplitSecret(privateKey) if err != nil { return nil, fmt.Errorf("failed to split secret: %w", err) } recoveryShares := make([]*RecoveryShare, len(shares)) for i, share := range shares { shareHash := sha256.Sum256([]byte(share.Value)) recoveryShares[i] = &RecoveryShare{ ShareID: fmt.Sprintf("share_%d_%d", share.Index, time.Now().Unix()), ShareData: []byte(share.Value), ShareIndex: share.Index, Custodian: "", // To be assigned CreatedAt: time.Now(), VerificationHash: hex.EncodeToString(shareHash[:]), } } return recoveryShares, nil } // logKeyEvent logs a key-related event func (km *KeyManager) logKeyEvent(eventType, roleID, keyID string, metadata map[string]interface{}) { if km.auditLogger == nil { return } event := &SecurityEvent{ EventID: fmt.Sprintf("%s_%s_%d", eventType, roleID, time.Now().Unix()), EventType: eventType, Timestamp: time.Now(), UserID: km.config.Agent.ID, Resource: keyID, Action: eventType, Outcome: "success", RiskLevel: "medium", Details: metadata, } km.auditLogger.LogSecurityEvent(event) } // logKeyRotationEvent logs a key rotation event func (km *KeyManager) logKeyRotationEvent(roleID, reason string, success bool, errorMsg string, result *KeyRotationResult) { if km.auditLogger == nil { return } event := &KeyRotationEvent{ EventID: fmt.Sprintf("key_rotation_%s_%d", roleID, time.Now().Unix()), Timestamp: time.Now(), RotatedRoles: []string{roleID}, InitiatedBy: km.config.Agent.ID, Reason: reason, Success: success, ErrorMessage: errorMsg, } if result != nil { for _, key := range result.NewKeys { keyHash := sha256.Sum256(key.KeyData) event.NewKeyHashes = append(event.NewKeyHashes, hex.EncodeToString(keyHash[:8])) } } km.auditLogger.LogKeyRotation(event) } // GetKeyMetadata returns metadata for all keys matching the filter func (km *KeyManager) GetKeyMetadata(filter *KeyFilter) ([]*KeyMetadata, error) { km.mu.RLock() defer km.mu.RUnlock() return km.keyStore.ListKeys(filter) } // VerifyKeyIntegrity verifies the integrity of stored keys func (km *KeyManager) VerifyKeyIntegrity(keyID string) (*KeyVerificationResult, error) { km.mu.RLock() defer km.mu.RUnlock() secureData, err := km.keyStore.RetrieveKey(keyID) if err != nil { return nil, fmt.Errorf("failed to retrieve key: %w", err) } result := &KeyVerificationResult{ KeyID: keyID, VerifiedAt: time.Now(), IntegrityOK: true, FormatOK: true, UsabilityOK: true, Issues: []string{}, } // Verify key hash if secureData.KeyHash == "" { result.IntegrityOK = false result.Issues = append(result.Issues, "missing key hash") } // Test key usability by performing a test encryption/decryption testData := []byte("test encryption data") if err := km.testKeyUsability(secureData, testData); err != nil { result.UsabilityOK = false result.Issues = append(result.Issues, fmt.Sprintf("key usability test failed: %v", err)) } if len(result.Issues) > 0 { result.OverallResult = "failed" } else { result.OverallResult = "passed" } return result, nil } // KeyVerificationResult represents the result of key verification type KeyVerificationResult struct { KeyID string `json:"key_id"` VerifiedAt time.Time `json:"verified_at"` IntegrityOK bool `json:"integrity_ok"` FormatOK bool `json:"format_ok"` UsabilityOK bool `json:"usability_ok"` OverallResult string `json:"overall_result"` Issues []string `json:"issues"` } // testKeyUsability tests if a key can be used for encryption/decryption func (km *KeyManager) testKeyUsability(secureData *SecureKeyData, testData []byte) error { // In production, implement actual encryption/decryption test // For now, just verify the key format if len(secureData.EncryptedKey) == 0 { return fmt.Errorf("empty key data") } return nil } // BackupKeys creates a backup of keys matching the criteria func (km *KeyManager) BackupKeys(criteria *BackupCriteria) (*KeyBackup, error) { km.mu.RLock() defer km.mu.RUnlock() return km.keyStore.BackupKeys(criteria) } // RestoreKeys restores keys from a backup func (km *KeyManager) RestoreKeys(backup *KeyBackup) error { km.mu.Lock() defer km.mu.Unlock() return km.keyStore.RestoreKeys(backup) } // GetSecurityStatus returns the overall security status of the key management system func (km *KeyManager) GetSecurityStatus() *KeyManagementSecurityStatus { km.mu.RLock() defer km.mu.RUnlock() status := &KeyManagementSecurityStatus{ CheckedAt: time.Now(), OverallHealth: "healthy", ActiveKeys: 0, ExpiredKeys: 0, RevokedKeys: 0, PendingRotations: 0, SecurityScore: 0.95, Issues: []string{}, Recommendations: []string{}, } // Get all keys and analyze their status allKeys, err := km.keyStore.ListKeys(&KeyFilter{IncludeMetadata: true}) if err != nil { status.Issues = append(status.Issues, fmt.Sprintf("failed to retrieve keys: %v", err)) status.OverallHealth = "degraded" return status } for _, key := range allKeys { switch key.Status { case KeyStatusActive: status.ActiveKeys++ case KeyStatusExpired: status.ExpiredKeys++ case KeyStatusRevoked: status.RevokedKeys++ } // Check for keys approaching expiration if key.ExpiresAt != nil && time.Until(*key.ExpiresAt) < 7*24*time.Hour { status.PendingRotations++ } } // Calculate security score based on key health if status.ExpiredKeys > 0 { status.SecurityScore -= 0.1 status.Issues = append(status.Issues, fmt.Sprintf("%d expired keys found", status.ExpiredKeys)) status.Recommendations = append(status.Recommendations, "Rotate expired keys immediately") } if status.PendingRotations > 0 { status.SecurityScore -= 0.05 status.Recommendations = append(status.Recommendations, "Schedule key rotations for expiring keys") } if status.SecurityScore < 0.8 { status.OverallHealth = "degraded" } else if status.SecurityScore < 0.9 { status.OverallHealth = "warning" } return status } // KeyManagementSecurityStatus represents the security status of key management type KeyManagementSecurityStatus struct { CheckedAt time.Time `json:"checked_at"` OverallHealth string `json:"overall_health"` // healthy, warning, degraded, critical ActiveKeys int `json:"active_keys"` ExpiredKeys int `json:"expired_keys"` RevokedKeys int `json:"revoked_keys"` PendingRotations int `json:"pending_rotations"` SecurityScore float64 `json:"security_score"` // 0.0 to 1.0 Issues []string `json:"issues"` Recommendations []string `json:"recommendations"` }