package key import ( "crypto/aes" "crypto/ed25519" "crypto/rand" "encoding/base64" "strings" "time" ) const ( obrimKeyTypeSymmetric = "symmetric" obrimKeyTypeAsymmetric = "asymmetric" obrimKeyAlgorithmAES = "aes" obrimKeyAlgorithmECC = "ecc" obrimKeyCurveEdDSA = "eddsa" ObrimKeyCodeSuccessSymmetricGenerated = "SUCCESS_SYMMETRIC_KEY_GENERATED" ObrimKeyCodeSuccessAsymmetricGenerated = "SUCCESS_ASYMMETRIC_KEY_GENERATED" ObrimKeyCodeFailedMissingType = "FAILED_MISSING_TYPE" ObrimKeyCodeFailedInvalidType = "FAILED_INVALID_TYPE" ObrimKeyCodeFailedUnsupportedType = "FAILED_UNSUPPORTED_TYPE" ObrimKeyCodeFailedMissingConfig = "FAILED_MISSING_CONFIGURATION" ObrimKeyCodeFailedInvalidConfig = "FAILED_INVALID_CONFIGURATION" ObrimKeyCodeFailedUnsupportedField = "FAILED_UNSUPPORTED_CONFIGURATION_FIELD" ObrimKeyCodeFailedMissingAlgorithm = "FAILED_MISSING_ALGORITHM" ObrimKeyCodeFailedInvalidAlgorithm = "FAILED_INVALID_ALGORITHM" ObrimKeyCodeFailedUnsupportedAlgorithm = "FAILED_UNSUPPORTED_ALGORITHM" ObrimKeyCodeFailedMissingKeySize = "FAILED_MISSING_KEY_SIZE" ObrimKeyCodeFailedInvalidKeySize = "FAILED_INVALID_KEY_SIZE" ObrimKeyCodeFailedUnsupportedKeySize = "FAILED_UNSUPPORTED_KEY_SIZE" ObrimKeyCodeFailedKeyGeneration = "FAILED_KEY_GENERATION" ) type ObrimKeyResponse struct { Status bool `json:"status"` Code string `json:"code"` Payload map[string]any `json:"payload"` } // obrimKeyAllowedSymmetricFields stores allowed symmetric configuration fields. var obrimKeyAllowedSymmetricFields = map[string]struct{}{ "algorithm": {}, "key_size": {}, } // obrimKeyAllowedAsymmetricFields stores allowed asymmetric configuration fields. var obrimKeyAllowedAsymmetricFields = map[string]struct{}{ "algorithm": {}, } // ObrimKey dispatches key generation requests and orchestrates validation, generation, and response construction. func ObrimKey(keyType string, config map[string]any) map[string]any { normalizedType, errorResponse := obrimKeyValidate(keyType, config) if errorResponse != nil { return errorResponse } return obrimKeyDispatch(normalizedType, config) } // obrimKeyValidate validates common request structure and schema integrity. func obrimKeyValidate( keyType string, config map[string]any, ) (string, map[string]any) { if strings.TrimSpace(keyType) == "" { return "", obrimKeyBuildError(ObrimKeyCodeFailedMissingType) } if config == nil { return "", obrimKeyBuildError(ObrimKeyCodeFailedMissingConfig) } normalizedType := strings.ToLower(strings.TrimSpace(keyType)) switch normalizedType { case obrimKeyTypeSymmetric: if errorCode := obrimKeyValidateSymmetricConfig(config); errorCode != "" { return "", obrimKeyBuildError(errorCode) } case obrimKeyTypeAsymmetric: if errorCode := obrimKeyValidateAsymmetricConfig(config); errorCode != "" { return "", obrimKeyBuildError(errorCode) } default: return "", obrimKeyBuildError(ObrimKeyCodeFailedUnsupportedType) } return normalizedType, nil } // obrimKeyDispatch routes execution to the appropriate cryptographic workflow. func obrimKeyDispatch( keyType string, config map[string]any, ) map[string]any { switch keyType { case obrimKeyTypeSymmetric: return obrimKeyGenerateSymmetric(config) case obrimKeyTypeAsymmetric: return obrimKeyGenerateAsymmetric(config) default: return obrimKeyBuildError(ObrimKeyCodeFailedUnsupportedType) } } // obrimKeyValidateSymmetricConfig validates symmetric configuration values. func obrimKeyValidateSymmetricConfig(config map[string]any) string { for field := range config { if _, exists := obrimKeyAllowedSymmetricFields[field]; !exists { return ObrimKeyCodeFailedUnsupportedField } } algorithmValue, exists := config["algorithm"] if !exists { return ObrimKeyCodeFailedMissingAlgorithm } algorithm, ok := algorithmValue.(string) if !ok { return ObrimKeyCodeFailedInvalidAlgorithm } algorithm = strings.ToLower(strings.TrimSpace(algorithm)) if algorithm != obrimKeyAlgorithmAES { return ObrimKeyCodeFailedUnsupportedAlgorithm } keySizeValue, exists := config["key_size"] if !exists { return ObrimKeyCodeFailedMissingKeySize } keySize, ok := obrimKeyNormalizeInteger(keySizeValue) if !ok { return ObrimKeyCodeFailedInvalidKeySize } switch keySize { case 128, 192, 256: return "" default: return ObrimKeyCodeFailedUnsupportedKeySize } } // obrimKeyValidateAsymmetricConfig validates asymmetric configuration values. func obrimKeyValidateAsymmetricConfig(config map[string]any) string { for field := range config { if _, exists := obrimKeyAllowedAsymmetricFields[field]; !exists { return ObrimKeyCodeFailedUnsupportedField } } algorithmValue, exists := config["algorithm"] if !exists { return ObrimKeyCodeFailedMissingAlgorithm } algorithm, ok := algorithmValue.(string) if !ok { return ObrimKeyCodeFailedInvalidAlgorithm } algorithm = strings.ToLower(strings.TrimSpace(algorithm)) if algorithm != obrimKeyAlgorithmECC { return ObrimKeyCodeFailedUnsupportedAlgorithm } return "" } // obrimKeyGenerateSymmetric generates symmetric key material. func obrimKeyGenerateSymmetric(config map[string]any) map[string]any { normalizedConfig := obrimKeyNormalizeSymmetricConfig(config) payload, errorCode := obrimKeyGenerateAES(normalizedConfig) if errorCode != "" { return obrimKeyBuildError(errorCode) } return obrimKeyBuildPayload( ObrimKeyCodeSuccessSymmetricGenerated, payload, ) } // obrimKeyGenerateAES generates AES key material. func obrimKeyGenerateAES( config map[string]any, ) (map[string]any, string) { keySize := config["key_size"].(int) // obrimKeyMaterial stores generated AES key bytes. var obrimKeyMaterial = make([]byte, keySize/8) if _, err := rand.Read(obrimKeyMaterial); err != nil { return nil, ObrimKeyCodeFailedKeyGeneration } if _, err := aes.NewCipher(obrimKeyMaterial); err != nil { return nil, ObrimKeyCodeFailedKeyGeneration } return map[string]any{ "type": obrimKeyTypeSymmetric, "algorithm": obrimKeyAlgorithmAES, "key_size": keySize, "key_material": base64.StdEncoding.EncodeToString(obrimKeyMaterial), "generated_at": time.Now().UTC().Format(time.RFC3339), }, "" } // obrimKeyNormalizeSymmetricConfig normalizes symmetric configuration values. func obrimKeyNormalizeSymmetricConfig( config map[string]any, ) map[string]any { keySize, _ := obrimKeyNormalizeInteger(config["key_size"]) return map[string]any{ "algorithm": strings.ToLower( strings.TrimSpace(config["algorithm"].(string)), ), "key_size": keySize, } } // obrimKeyGenerateAsymmetric generates asymmetric key material. func obrimKeyGenerateAsymmetric(config map[string]any) map[string]any { normalizedConfig := obrimKeyNormalizeAsymmetricConfig(config) payload, errorCode := obrimKeyGenerateECC(normalizedConfig) if errorCode != "" { return obrimKeyBuildError(errorCode) } return obrimKeyBuildPayload( ObrimKeyCodeSuccessAsymmetricGenerated, payload, ) } // obrimKeyGenerateECC generates ECC key pair material. func obrimKeyGenerateECC( config map[string]any, ) (map[string]any, string) { _ = config publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, ObrimKeyCodeFailedKeyGeneration } return 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), }, "" } // obrimKeyNormalizeAsymmetricConfig normalizes asymmetric configuration values. func obrimKeyNormalizeAsymmetricConfig( config map[string]any, ) map[string]any { return map[string]any{ "algorithm": strings.ToLower( strings.TrimSpace(config["algorithm"].(string)), ), } } // obrimKeyBuildPayload constructs standardized success payloads. func obrimKeyBuildPayload( code string, payload map[string]any, ) map[string]any { return map[string]any{ "status": true, "code": code, "payload": payload, } } // obrimKeyBuildError constructs standardized error responses. func obrimKeyBuildError(code string) map[string]any { return map[string]any{ "status": false, "code": code, "payload": nil, } } // obrimKeyNormalizeInteger normalizes integer values. func obrimKeyNormalizeInteger(value any) (int, bool) { switch normalizedValue := value.(type) { case int: return normalizedValue, true case int8: return int(normalizedValue), true case int16: return int(normalizedValue), true case int32: return int(normalizedValue), true case int64: return int(normalizedValue), true case uint: return int(normalizedValue), true case uint8: return int(normalizedValue), true case uint16: return int(normalizedValue), true case uint32: return int(normalizedValue), true case uint64: return int(normalizedValue), true default: return 0, false } }