package hash import ( "crypto/rand" "crypto/sha256" "crypto/sha512" "encoding/hex" ) const ( obrimHashTypeCalculate = "calculate" obrimHashTypeCompare = "compare" obrimHashModeStandard = "standard" obrimHashModeSalted = "salted" obrimHashAlgorithmSHA256 = "sha256" obrimHashAlgorithmSHA512 = "sha512" obrimHashAlgorithmSaltedSHA256 = "salted_sha256" obrimHashAlgorithmSaltedSHA512 = "salted_sha512" ObrimHashCodeSuccessHashGenerated = "SUCCESS_HASH_GENERATED" ObrimHashCodeSuccessHashCompared = "SUCCESS_HASH_COMPARED" ObrimHashCodeFailedUnsupportedType = "FAILED_UNSUPPORTED_TYPE" ObrimHashCodeFailedUnsupportedMode = "FAILED_UNSUPPORTED_MODE" ObrimHashCodeFailedUnsupportedAlgorithm = "FAILED_UNSUPPORTED_ALGORITHM" ObrimHashCodeFailedUnsupportedConfigKey = "FAILED_UNSUPPORTED_CONFIG_KEY" ObrimHashCodeFailedMissingMode = "FAILED_MISSING_MODE" ObrimHashCodeFailedMissingAlgorithm = "FAILED_MISSING_ALGORITHM" ObrimHashCodeFailedMissingValue = "FAILED_MISSING_VALUE" ObrimHashCodeFailedMissingHash = "FAILED_MISSING_HASH" ObrimHashCodeFailedMissingSalt = "FAILED_MISSING_SALT" ObrimHashCodeFailedInvalidConfig = "FAILED_INVALID_CONFIGURATION" ObrimHashCodeFailedSaltNotAllowed = "FAILED_SALT_NOT_ALLOWED" ObrimHashCodeFailedHashGeneration = "FAILED_HASH_GENERATION" ObrimHashCodeFailedSaltGeneration = "FAILED_SALT_GENERATION" ) // ObrimHashResponse defines the standard utility response. type ObrimHashResponse struct { Status bool `json:"status"` Code string `json:"code"` Payload any `json:"payload"` } // ObrimHashConfig defines utility configuration. type ObrimHashConfig struct { Mode string Algorithm string Value string Hash string Salt string } // ObrimHashCalculateStandardPayload defines calculate standard payload. type ObrimHashCalculateStandardPayload struct { Algorithm string `json:"algorithm"` Hash string `json:"hash"` } // ObrimHashCalculateSaltedPayload defines calculate salted payload. type ObrimHashCalculateSaltedPayload struct { Algorithm string `json:"algorithm"` Hash string `json:"hash"` Salt string `json:"salt"` } // ObrimHashCompareStandardPayload defines compare standard payload. type ObrimHashCompareStandardPayload struct { Algorithm string `json:"algorithm"` Matched bool `json:"matched"` Hash string `json:"hash"` } // ObrimHashCompareSaltedPayload defines compare salted payload. type ObrimHashCompareSaltedPayload struct { Algorithm string `json:"algorithm"` Matched bool `json:"matched"` Hash string `json:"hash"` Salt string `json:"salt"` } // obrimHashAllowedConfigKeys stores supported configuration keys. var obrimHashAllowedConfigKeys = map[string]struct{}{ "mode": {}, "algorithm": {}, "value": {}, "hash": {}, "salt": {}, } // ObrimHash processes hash generation and verification requests. func ObrimHash( hashType string, config map[string]any, ) map[string]any { if !obrimHashValidateType(hashType) { return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedType, ) } hashConfig, errorCode := obrimHashValidateConfig( hashType, config, ) if errorCode != "" { return obrimHashBuildErrorPayload(errorCode) } if !obrimHashValidateMode(hashConfig.Mode) { return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedMode, ) } if !obrimHashValidateAlgorithm( hashConfig.Mode, hashConfig.Algorithm, ) { return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedAlgorithm, ) } switch hashType { case obrimHashTypeCalculate: return obrimHashCalculate(hashConfig) case obrimHashTypeCompare: return obrimHashCompare(hashConfig) default: return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedType, ) } } // obrimHashValidateType validates operation type. func obrimHashValidateType(hashType string) bool { switch hashType { case obrimHashTypeCalculate: return true case obrimHashTypeCompare: return true default: return false } } // obrimHashValidateMode validates hashing mode. func obrimHashValidateMode(mode string) bool { switch mode { case obrimHashModeStandard: return true case obrimHashModeSalted: return true default: return false } } // obrimHashValidateAlgorithm validates hashing algorithm selection. func obrimHashValidateAlgorithm( mode string, algorithm string, ) bool { switch mode { case obrimHashModeStandard: switch algorithm { case obrimHashAlgorithmSHA256: return true case obrimHashAlgorithmSHA512: return true } case obrimHashModeSalted: switch algorithm { case obrimHashAlgorithmSaltedSHA256: return true case obrimHashAlgorithmSaltedSHA512: return true } } return false } // obrimHashValidateConfig validates configuration keys and values. func obrimHashValidateConfig( hashType string, config map[string]any, ) (ObrimHashConfig, string) { var hashConfig ObrimHashConfig if config == nil { return hashConfig, ObrimHashCodeFailedInvalidConfig } for key := range config { if _, exists := obrimHashAllowedConfigKeys[key]; !exists { return hashConfig, ObrimHashCodeFailedUnsupportedConfigKey } } modeValue, ok := config["mode"].(string) if !ok || modeValue == "" { return hashConfig, ObrimHashCodeFailedMissingMode } algorithmValue, ok := config["algorithm"].(string) if !ok || algorithmValue == "" { return hashConfig, ObrimHashCodeFailedMissingAlgorithm } valueValue, ok := config["value"].(string) if !ok || valueValue == "" { return hashConfig, ObrimHashCodeFailedMissingValue } hashConfig.Mode = modeValue hashConfig.Algorithm = algorithmValue hashConfig.Value = valueValue if hashValue, exists := config["hash"]; exists { hashText, ok := hashValue.(string) if !ok { return hashConfig, ObrimHashCodeFailedInvalidConfig } hashConfig.Hash = hashText } if saltValue, exists := config["salt"]; exists { saltText, ok := saltValue.(string) if !ok { return hashConfig, ObrimHashCodeFailedInvalidConfig } hashConfig.Salt = saltText } switch hashType { case obrimHashTypeCalculate: if hashConfig.Mode == obrimHashModeStandard && hashConfig.Salt != "" { return hashConfig, ObrimHashCodeFailedSaltNotAllowed } case obrimHashTypeCompare: if hashConfig.Hash == "" { return hashConfig, ObrimHashCodeFailedMissingHash } if hashConfig.Mode == obrimHashModeStandard && hashConfig.Salt != "" { return hashConfig, ObrimHashCodeFailedSaltNotAllowed } if hashConfig.Mode == obrimHashModeSalted && hashConfig.Salt == "" { return hashConfig, ObrimHashCodeFailedMissingSalt } } return hashConfig, "" } // obrimHashGenerateHash executes the selected hashing algorithm. func obrimHashGenerateHash( algorithm string, value string, salt string, ) (string, bool) { switch algorithm { case obrimHashAlgorithmSHA256: sum := sha256.Sum256([]byte(value)) return hex.EncodeToString(sum[:]), true case obrimHashAlgorithmSHA512: sum := sha512.Sum512([]byte(value)) return hex.EncodeToString(sum[:]), true case obrimHashAlgorithmSaltedSHA256: sum := sha256.Sum256([]byte(value + salt)) return hex.EncodeToString(sum[:]), true case obrimHashAlgorithmSaltedSHA512: sum := sha512.Sum512([]byte(value + salt)) return hex.EncodeToString(sum[:]), true default: return "", false } } // obrimHashCalculate processes hash generation requests. func obrimHashCalculate( config ObrimHashConfig, ) map[string]any { switch config.Mode { case obrimHashModeStandard: return obrimHashCalculateStandard(config) case obrimHashModeSalted: return obrimHashCalculateSalted(config) default: return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedMode, ) } } // obrimHashCalculateStandard generates a deterministic hash. func obrimHashCalculateStandard( config ObrimHashConfig, ) map[string]any { hashValue, success := obrimHashGenerateHash( config.Algorithm, config.Value, "", ) if !success { return obrimHashBuildErrorPayload( ObrimHashCodeFailedHashGeneration, ) } payload := ObrimHashCalculateStandardPayload{ Algorithm: config.Algorithm, Hash: hashValue, } return obrimHashBuildSuccessPayload( ObrimHashCodeSuccessHashGenerated, payload, ) } // obrimHashCalculateSalted generates a salted hash and salt pair. func obrimHashCalculateSalted( config ObrimHashConfig, ) map[string]any { var activeSalt string activeSalt = config.Salt if activeSalt == "" { generatedSalt, success := obrimHashGenerateSalt() if !success { return obrimHashBuildErrorPayload( ObrimHashCodeFailedSaltGeneration, ) } activeSalt = generatedSalt } hashValue, success := obrimHashGenerateHash( config.Algorithm, config.Value, activeSalt, ) if !success { return obrimHashBuildErrorPayload( ObrimHashCodeFailedHashGeneration, ) } payload := ObrimHashCalculateSaltedPayload{ Algorithm: config.Algorithm, Hash: hashValue, Salt: activeSalt, } return obrimHashBuildSuccessPayload( ObrimHashCodeSuccessHashGenerated, payload, ) } // obrimHashGenerateSalt generates a cryptographically secure salt. func obrimHashGenerateSalt() (string, bool) { var saltBytes = make([]byte, 32) _, err := rand.Read(saltBytes) if err != nil { return "", false } return hex.EncodeToString(saltBytes), true } // obrimHashCompare processes hash verification requests. func obrimHashCompare( config ObrimHashConfig, ) map[string]any { switch config.Mode { case obrimHashModeStandard: return obrimHashCompareStandard(config) case obrimHashModeSalted: return obrimHashCompareSalted(config) default: return obrimHashBuildErrorPayload( ObrimHashCodeFailedUnsupportedMode, ) } } // obrimHashCompareStandard regenerates a standard hash for verification. func obrimHashCompareStandard( config ObrimHashConfig, ) map[string]any { regeneratedHash, success := obrimHashGenerateHash( config.Algorithm, config.Value, "", ) if !success { return obrimHashBuildErrorPayload( ObrimHashCodeFailedHashGeneration, ) } payload := ObrimHashCompareStandardPayload{ Algorithm: config.Algorithm, Matched: obrimHashVerify( regeneratedHash, config.Hash, ), Hash: config.Hash, } return obrimHashBuildSuccessPayload( ObrimHashCodeSuccessHashCompared, payload, ) } // obrimHashCompareSalted regenerates a salted hash for verification. func obrimHashCompareSalted( config ObrimHashConfig, ) map[string]any { regeneratedHash, success := obrimHashGenerateHash( config.Algorithm, config.Value, config.Salt, ) if !success { return obrimHashBuildErrorPayload( ObrimHashCodeFailedHashGeneration, ) } payload := ObrimHashCompareSaltedPayload{ Algorithm: config.Algorithm, Matched: obrimHashVerify( regeneratedHash, config.Hash, ), Hash: config.Hash, Salt: config.Salt, } return obrimHashBuildSuccessPayload( ObrimHashCodeSuccessHashCompared, payload, ) } // obrimHashVerify compares regenerated and supplied hash values. func obrimHashVerify( regeneratedHash string, suppliedHash string, ) bool { return regeneratedHash == suppliedHash } // obrimHashBuildSuccessPayload constructs success response payloads. func obrimHashBuildSuccessPayload( code string, payload any, ) map[string]any { return map[string]any{ "status": true, "code": code, "payload": payload, } } // obrimHashBuildErrorPayload constructs error response payloads. func obrimHashBuildErrorPayload( code string, ) map[string]any { return map[string]any{ "status": false, "code": code, "payload": nil, } }