/* |-------------------------------------------------------------------------- | Description |-------------------------------------------------------------------------- | | Name: | - Hash | | Purpose: | - Generate and verify cryptographic hash values using standard or | salted hashing methods for integrity verification, canonical | fingerprinting, resource identification, comparison workflows, | and security-oriented hashing requirements. | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Instruction |-------------------------------------------------------------------------- | | Guideline: | - Use to generate deterministic hashes in standard mode. | - Use to generate salted hashes when salted hashing is required. | - Use to verify supplied hash values against input values. | - Use standard mode when deterministic hashing without a salt is | required. | - Use salted mode when a supplied or cryptographically secure | generated salt is required. | | Example: | - ObrimHash("calculate", map[string]any{ | "mode": "standard", | "algorithm": "...", | "value": "...", | }) | | - ObrimHash("calculate", map[string]any{ | "mode": "salted", | "algorithm": "...", | "value": "...", | "salt": "...", | }) | | - ObrimHash("compare", map[string]any{ | "mode": "standard", | "algorithm": "...", | "value": "...", | "hash": "...", | }) | | - ObrimHash("compare", map[string]any{ | "mode": "salted", | "algorithm": "...", | "value": "...", | "hash": "...", | "salt": "...", | }) | |-------------------------------------------------------------------------- */ /* |-------------------------------------------------------------------------- | Credit |-------------------------------------------------------------------------- | | Contributor: | - Rajon Ahmed | - Blockonite | |-------------------------------------------------------------------------- */ package hash import ( "crypto/rand" "crypto/sha256" "crypto/sha512" "encoding/hex" "errors" "hash" ) // Hash result codes. const ( ObrimHashSuccessCalculated = "SUCCESS_CALCULATED" ObrimHashSuccessCompared = "SUCCESS_COMPARED" ObrimHashFailureInvalidType = "FAILURE_INVALID_TYPE" ObrimHashFailureInvalidConfig = "FAILURE_INVALID_CONFIG" ObrimHashFailureInvalidMode = "FAILURE_INVALID_MODE" ObrimHashFailureInvalidAlgorithm = "FAILURE_INVALID_ALGORITHM" ObrimHashFailureInvalidValue = "FAILURE_INVALID_VALUE" ObrimHashFailureInvalidHash = "FAILURE_INVALID_HASH" ObrimHashFailureInvalidSalt = "FAILURE_INVALID_SALT" ObrimHashFailureProcessing = "FAILURE_PROCESSING" ) // Hash utility modes. const ( obrimHashModeStandard = "standard" obrimHashModeSalted = "salted" ) // Hash utility algorithms. const ( obrimHashAlgorithmSHA256 = "sha256" obrimHashAlgorithmSHA512 = "sha512" ) // Hash utility configuration keys. const ( obrimHashConfigMode = "mode" obrimHashConfigAlgorithm = "algorithm" obrimHashConfigValue = "value" obrimHashConfigHash = "hash" obrimHashConfigSalt = "salt" ) // Hash utility operation types. const ( obrimHashTypeCalculate = "calculate" obrimHashTypeCompare = "compare" ) // Hash utility output structure. type obrimHashOutput struct { Status bool `json:"status"` Code string `json:"code"` Payload map[string]any `json:"payload"` } // Hash utility request configuration. type obrimHashConfig struct { Mode string Algorithm string Value string Hash string Salt string } // Hash utility execution function. func ObrimHash(Type string, Config map[string]any) map[string]any { ConfigData, Code := obrimHashValidateInput(Type, Config) if Code != "" { return obrimHashBuildOutput(false, Code, nil) } return obrimHashRouteRequest(Type, ConfigData) } // Validate hash utility input. func obrimHashValidateInput(Type string, Config map[string]any) (obrimHashConfig, string) { var ConfigData obrimHashConfig switch Type { case obrimHashTypeCalculate, obrimHashTypeCompare: default: return ConfigData, ObrimHashFailureInvalidType } if Config == nil { return ConfigData, ObrimHashFailureInvalidConfig } ConfigData.Mode = obrimHashReadStringConfig(Config, obrimHashConfigMode) ConfigData.Algorithm = obrimHashReadStringConfig(Config, obrimHashConfigAlgorithm) ConfigData.Value = obrimHashReadStringConfig(Config, obrimHashConfigValue) ConfigData.Hash = obrimHashReadStringConfig(Config, obrimHashConfigHash) ConfigData.Salt = obrimHashReadStringConfig(Config, obrimHashConfigSalt) switch ConfigData.Mode { case obrimHashModeStandard, obrimHashModeSalted: default: return ConfigData, ObrimHashFailureInvalidMode } switch ConfigData.Algorithm { case obrimHashAlgorithmSHA256, obrimHashAlgorithmSHA512: default: return ConfigData, ObrimHashFailureInvalidAlgorithm } if ConfigData.Value == "" { return ConfigData, ObrimHashFailureInvalidValue } switch Type { case obrimHashTypeCalculate: if ConfigData.Mode == obrimHashModeStandard && ConfigData.Salt != "" { return ConfigData, ObrimHashFailureInvalidSalt } case obrimHashTypeCompare: if ConfigData.Hash == "" { return ConfigData, ObrimHashFailureInvalidHash } switch ConfigData.Mode { case obrimHashModeStandard: if ConfigData.Salt != "" { return ConfigData, ObrimHashFailureInvalidSalt } case obrimHashModeSalted: if ConfigData.Salt == "" { return ConfigData, ObrimHashFailureInvalidSalt } } } return ConfigData, "" } // Route the hash utility request. func obrimHashRouteRequest(Type string, Config obrimHashConfig) map[string]any { switch Type { case obrimHashTypeCalculate: return obrimHashCalculate(Config) case obrimHashTypeCompare: return obrimHashCompare(Config) default: return obrimHashBuildOutput(false, ObrimHashFailureInvalidType, nil) } } // Build standardized hash utility output. func obrimHashBuildOutput(Status bool, Code string, Payload map[string]any) map[string]any { Output := obrimHashOutput{ Status: Status, Code: Code, Payload: Payload, } return map[string]any{ "status": Output.Status, "code": Output.Code, "payload": Output.Payload, } } // Process hash generation. func obrimHashCalculate(Config obrimHashConfig) map[string]any { switch Config.Mode { case obrimHashModeStandard: return obrimHashCalculateStandard(Config) case obrimHashModeSalted: return obrimHashCalculateSalted(Config) default: return obrimHashBuildOutput(false, ObrimHashFailureInvalidMode, nil) } } // Generate deterministic standard hash. func obrimHashCalculateStandard(Config obrimHashConfig) map[string]any { HashValue, Error := obrimHashGenerate(Config.Algorithm, Config.Value) if Error != nil { return obrimHashBuildOutput(false, ObrimHashFailureProcessing, nil) } Payload := map[string]any{ "algorithm": Config.Algorithm, "hash": HashValue, } return obrimHashBuildOutput(true, ObrimHashSuccessCalculated, Payload) } // Generate salted hash. func obrimHashCalculateSalted(Config obrimHashConfig) map[string]any { Salt := Config.Salt if Salt == "" { var Error error Salt, Error = obrimHashGenerateSalt() if Error != nil { return obrimHashBuildOutput(false, ObrimHashFailureProcessing, nil) } } HashValue, Error := obrimHashGenerate(Config.Algorithm, Salt+Config.Value) if Error != nil { return obrimHashBuildOutput(false, ObrimHashFailureProcessing, nil) } Payload := map[string]any{ "algorithm": Config.Algorithm, "hash": HashValue, "salt": Salt, } return obrimHashBuildOutput(true, ObrimHashSuccessCalculated, Payload) } // Generate a cryptographically secure random salt. func obrimHashGenerateSalt() (string, error) { Salt := make([]byte, 32) if _, Error := rand.Read(Salt); Error != nil { return "", Error } return hex.EncodeToString(Salt), nil } // Process hash verification. func obrimHashCompare(Config obrimHashConfig) map[string]any { switch Config.Mode { case obrimHashModeStandard: return obrimHashCompareStandard(Config) case obrimHashModeSalted: return obrimHashCompareSalted(Config) default: return obrimHashBuildOutput(false, ObrimHashFailureInvalidMode, nil) } } // Verify standard hash. func obrimHashCompareStandard(Config obrimHashConfig) map[string]any { HashValue, Error := obrimHashGenerate(Config.Algorithm, Config.Value) if Error != nil { return obrimHashBuildOutput(false, ObrimHashFailureProcessing, nil) } Matched := obrimHashVerify(HashValue, Config.Hash) Payload := map[string]any{ "algorithm": Config.Algorithm, "matched": Matched, "hash": Config.Hash, } return obrimHashBuildOutput(true, ObrimHashSuccessCompared, Payload) } // Verify salted hash. func obrimHashCompareSalted(Config obrimHashConfig) map[string]any { HashValue, Error := obrimHashGenerate(Config.Algorithm, Config.Salt+Config.Value) if Error != nil { return obrimHashBuildOutput(false, ObrimHashFailureProcessing, nil) } Matched := obrimHashVerify(HashValue, Config.Hash) Payload := map[string]any{ "algorithm": Config.Algorithm, "matched": Matched, "hash": Config.Hash, "salt": Config.Salt, } return obrimHashBuildOutput(true, ObrimHashSuccessCompared, Payload) } // Verify regenerated and supplied hashes using strict byte comparison. func obrimHashVerify(Expected string, Supplied string) bool { return string([]byte(Expected)) == string([]byte(Supplied)) } // Generate a hash using the selected algorithm. func obrimHashGenerate(Algorithm string, Value string) (string, error) { var HashFunction func() hash.Hash switch Algorithm { case obrimHashAlgorithmSHA256: HashFunction = sha256.New case obrimHashAlgorithmSHA512: HashFunction = sha512.New default: return "", errors.New("unsupported hashing algorithm") } Hasher := HashFunction() if _, Error := Hasher.Write([]byte(Value)); Error != nil { return "", Error } return hex.EncodeToString(Hasher.Sum(nil)), nil } // Read a string configuration value. func obrimHashReadStringConfig(Config map[string]any, Key string) string { Value, Exists := Config[Key] if !Exists || Value == nil { return "" } StringValue, Valid := Value.(string) if !Valid { return "" } return StringValue }