upd: essential/file updated
helper hash updated
This commit is contained in:
parent
f6694cb17d
commit
e0d950b130
@ -0,0 +1,396 @@
|
|||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| 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
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user