/* |-------------------------------------------------------------------------- | Manifest |-------------------------------------------------------------------------- | | Name: | - Key | | Purpose: | - Generate cryptographic key material using a type-driven dispatch model. | | Guideline: | - Use explicit configuration values only. | - Validate all inputs before generation. | - Reject unsupported or irrelevant configuration fields. | - Use centralized dispatch for workflow execution. | | Example: | - ObrimKey("symmetric", map[string]any{ | "algorithm": "aes", | "key_size": 256, | }) | | - ObrimKey("asymmetric", map[string]any{ | "algorithm": "ecc", | }) | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Credit |-------------------------------------------------------------------------- | | Contributor: | - Rajon Ahmed | - Scionite | |-------------------------------------------------------------------------- */ package key import ( "crypto/aes" "crypto/ed25519" "crypto/rand" "encoding/base64" "fmt" "strings" "time" "go/module/essential/visible/service/helper/log" "go/module/essential/visible/service/helper/status" ) const ( obrimKeyTypeSymmetric = "symmetric" obrimKeyTypeAsymmetric = "asymmetric" obrimKeyAlgorithmAES = "aes" obrimKeyAlgorithmECC = "ecc" obrimKeyCurveEdDSA = "eddsa" ) // ObrimKey dispatches key generation requests and orchestrates validation, generation, and response construction. func ObrimKey(keyType string, config map[string]any) map[string]any { log.ObrimLog("INIT", "Key generation request received.") status.ObrimStatus("INFO", "Validating key generation request.") if response := obrimKeyValidate(keyType, config); response != nil { return response } return obrimKeyDispatch(keyType, config) } // obrimKeyValidate validates common request structure and schema integrity. func obrimKeyValidate(keyType string, config map[string]any) map[string]any { if strings.TrimSpace(keyType) == "" { return obrimKeyBuildError("FAILED_TYPE_REQUIRED") } if config == nil { return obrimKeyBuildError("FAILED_CONFIG_REQUIRED") } normalizedType := strings.ToLower(strings.TrimSpace(keyType)) switch normalizedType { case obrimKeyTypeSymmetric: return obrimKeyValidateSymmetricConfig(config) case obrimKeyTypeAsymmetric: return obrimKeyValidateAsymmetricConfig(config) default: return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE") } } // obrimKeyDispatch routes execution to the appropriate cryptographic workflow. func obrimKeyDispatch(keyType string, config map[string]any) map[string]any { normalizedType := strings.ToLower(strings.TrimSpace(keyType)) switch normalizedType { case obrimKeyTypeSymmetric: return obrimKeyGenerateSymmetric(config) case obrimKeyTypeAsymmetric: return obrimKeyGenerateAsymmetric(config) default: return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE") } } // obrimKeyValidateSymmetricConfig validates symmetric configuration values. func obrimKeyValidateSymmetricConfig(config map[string]any) map[string]any { if len(config) != 2 { return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION") } for key := range config { if key != "algorithm" && key != "key_size" { return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD") } } algorithmValue, exists := config["algorithm"] if !exists { return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED") } algorithm, ok := algorithmValue.(string) if !ok { return obrimKeyBuildError("FAILED_INVALID_ALGORITHM") } normalizedConfig := obrimKeyNormalizeSymmetricConfig(config) if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmAES { return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM") } keySizeValue, exists := normalizedConfig["key_size"] if !exists { return obrimKeyBuildError("FAILED_KEY_SIZE_REQUIRED") } keySize, ok := keySizeValue.(int) if !ok { return obrimKeyBuildError("FAILED_INVALID_KEY_SIZE") } if keySize != 128 && keySize != 192 && keySize != 256 { return obrimKeyBuildError("FAILED_UNSUPPORTED_KEY_SIZE") } return nil } // obrimKeyValidateAsymmetricConfig validates asymmetric configuration values. func obrimKeyValidateAsymmetricConfig(config map[string]any) map[string]any { if len(config) != 1 { return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION") } for key := range config { if key != "algorithm" { return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD") } } algorithmValue, exists := config["algorithm"] if !exists { return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED") } algorithm, ok := algorithmValue.(string) if !ok { return obrimKeyBuildError("FAILED_INVALID_ALGORITHM") } if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmECC { return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM") } return nil } // obrimKeyGenerateSymmetric generates symmetric key material. func obrimKeyGenerateSymmetric(config map[string]any) map[string]any { log.ObrimLog("INIT", "Generating symmetric key material.") normalizedConfig := obrimKeyNormalizeSymmetricConfig(config) payload, err := obrimKeyGenerateAES(normalizedConfig) if err != nil { log.ObrimLog("ERROR", err.Error()) return obrimKeyBuildError("FAILED_KEY_GENERATION") } log.ObrimLog("SUCCESS", "Symmetric key material generated.") status.ObrimStatus("SUCCESS", "Key generation completed.") return map[string]any{ "status": true, "code": "SUCCESS_KEY_GENERATED", "payload": payload, } } // obrimKeyGenerateAES generates AES key material. func obrimKeyGenerateAES(config map[string]any) (map[string]any, error) { // Mutable variable holding key size. keySize := config["key_size"].(int) // Mutable variable holding key bytes. keyBytes := make([]byte, keySize/8) if _, err := rand.Read(keyBytes); err != nil { return nil, err } if _, err := aes.NewCipher(keyBytes); err != nil { return nil, err } payload := map[string]any{ "type": obrimKeyTypeSymmetric, "algorithm": obrimKeyAlgorithmAES, "key_size": keySize, "key_material": base64.StdEncoding.EncodeToString(keyBytes), "generated_at": time.Now().UTC().Format(time.RFC3339), } return payload, nil } // obrimKeyNormalizeSymmetricConfig normalizes symmetric configuration values. func obrimKeyNormalizeSymmetricConfig(config map[string]any) map[string]any { normalized := map[string]any{} if value, exists := config["algorithm"]; exists { if algorithm, ok := value.(string); ok { normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm)) } } if value, exists := config["key_size"]; exists { switch typed := value.(type) { case int: normalized["key_size"] = typed case int8: normalized["key_size"] = int(typed) case int16: normalized["key_size"] = int(typed) case int32: normalized["key_size"] = int(typed) case int64: normalized["key_size"] = int(typed) case float32: normalized["key_size"] = int(typed) case float64: normalized["key_size"] = int(typed) } } return normalized } // obrimKeyGenerateAsymmetric generates asymmetric key material. func obrimKeyGenerateAsymmetric(config map[string]any) map[string]any { log.ObrimLog("INIT", "Generating asymmetric key material.") normalizedConfig := obrimKeyNormalizeAsymmetricConfig(config) payload, err := obrimKeyGenerateECC(normalizedConfig) if err != nil { log.ObrimLog("ERROR", err.Error()) return obrimKeyBuildError("FAILED_KEY_GENERATION") } log.ObrimLog("SUCCESS", "Asymmetric key material generated.") status.ObrimStatus("SUCCESS", "Key generation completed.") return map[string]any{ "status": true, "code": "SUCCESS_KEY_GENERATED", "payload": payload, } } // obrimKeyGenerateECC generates ECC key pair material. func obrimKeyGenerateECC(config map[string]any) (map[string]any, error) { publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, err } payload := map[string]any{ "type": obrimKeyTypeAsymmetric, "algorithm": obrimKeyAlgorithmECC, "curve": obrimKeyCurveEdDSA, "public_key": base64.StdEncoding.EncodeToString(publicKey), "private_key": base64.StdEncoding.EncodeToString(privateKey), "generated_at": time.Now().UTC().Format(time.RFC3339), } return payload, nil } // obrimKeyNormalizeAsymmetricConfig normalizes asymmetric configuration values. func obrimKeyNormalizeAsymmetricConfig(config map[string]any) map[string]any { normalized := map[string]any{} if value, exists := config["algorithm"]; exists { if algorithm, ok := value.(string); ok { normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm)) } } return normalized } // obrimKeyBuildPayload constructs standardized success payloads. func obrimKeyBuildPayload(payload map[string]any) map[string]any { return map[string]any{ "status": true, "code": "SUCCESS", "payload": payload, } } // obrimKeyBuildError constructs standardized error responses. func obrimKeyBuildError(code string) map[string]any { log.ObrimLog("ERROR", fmt.Sprintf("Key generation failed: %s", code)) status.ObrimStatus("ERROR", code) return map[string]any{ "status": false, "code": code, "payload": nil, } }