obrimbasecli/essential/visible/service/helper/hash/hash.go

443 lines
9.6 KiB
Go

/*
|--------------------------------------------------------------------------
| Hash
|--------------------------------------------------------------------------
|
| Name:
| - Hash
|
| Purpose:
| - Generate and verify cryptographic hash values using standard or
| salted hashing methods.
|
| Guidelines:
| - Accept exactly two primary parameters: type and config.
| - Validate all inputs before processing.
| - Return all results through the standard output structure.
| - Never panic or terminate execution.
|
| Examples:
| - ObrimHash("calculate", config)
| - ObrimHash("compare", config)
|
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| Credit
|--------------------------------------------------------------------------
|
| Contributor:
| - Rajon Ahmed
| - Scionite
|
|--------------------------------------------------------------------------
*/
package hash
import (
"crypto/rand"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"strings"
"go/module/essential/visible/service/helper/log"
"go/module/essential/visible/service/helper/retriever"
"go/module/essential/visible/service/helper/status"
)
const (
obrimHashTypeCalculate = "calculate"
obrimHashTypeCompare = "compare"
obrimHashModeStandard = "standard"
obrimHashModeSalted = "salted"
)
var obrimHashSupportedAlgorithms = map[string]bool{
"sha256": true,
"sha512": true,
"salted_sha256": true,
"salted_sha512": true,
}
var obrimHashSupportedConfigKeys = map[string]bool{
"mode": true,
"algorithm": true,
"value": true,
"hash": true,
"salt": true,
}
// Function Name: ObrimHash
// Function Purpose: Process hash generation and verification requests.
func ObrimHash(
hashType string,
config map[string]any,
) map[string]any {
_, _ = retriever.ObrimRetriever, status.ObrimStatus
log.ObrimLog("INIT", "Hash utility request received.")
if !obrimHashValidateType(hashType) {
return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE")
}
if !obrimHashValidateConfig(hashType, config) {
return obrimHashBuildErrorPayload("FAILED_INVALID_CONFIG")
}
mode := config["mode"].(string)
if !obrimHashValidateMode(mode) {
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
}
algorithm := config["algorithm"].(string)
if !obrimHashValidateAlgorithm(algorithm) {
return obrimHashBuildErrorPayload("FAILED_INVALID_ALGORITHM")
}
switch hashType {
case obrimHashTypeCalculate:
return obrimHashCalculate(config)
case obrimHashTypeCompare:
return obrimHashCompare(config)
default:
return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE")
}
}
// Function Name: obrimHashValidateType
// Function Purpose: Validate operation type.
func obrimHashValidateType(hashType string) bool {
return hashType == obrimHashTypeCalculate ||
hashType == obrimHashTypeCompare
}
// Function Name: obrimHashValidateMode
// Function Purpose: Validate hashing mode.
func obrimHashValidateMode(mode string) bool {
return mode == obrimHashModeStandard ||
mode == obrimHashModeSalted
}
// Function Name: obrimHashValidateConfig
// Function Purpose: Validate configuration keys and values.
func obrimHashValidateConfig(
hashType string,
config map[string]any,
) bool {
if config == nil {
return false
}
for key := range config {
if !obrimHashSupportedConfigKeys[key] {
return false
}
}
requiredKeys := []string{
"mode",
"algorithm",
"value",
}
for _, key := range requiredKeys {
value, exists := config[key]
if !exists || value == nil {
return false
}
stringValue, ok := value.(string)
if !ok || stringValue == "" {
return false
}
}
mode := config["mode"].(string)
if hashType == obrimHashTypeCompare {
hashValue, exists := config["hash"]
if !exists || hashValue == nil {
return false
}
hashString, ok := hashValue.(string)
if !ok || hashString == "" {
return false
}
if mode == obrimHashModeSalted {
saltValue, exists := config["salt"]
if !exists || saltValue == nil {
return false
}
saltString, ok := saltValue.(string)
if !ok || saltString == "" {
return false
}
}
if mode == obrimHashModeStandard {
if _, exists := config["salt"]; exists {
return false
}
}
}
return true
}
// Function Name: obrimHashValidateAlgorithm
// Function Purpose: Validate hashing algorithm selection.
func obrimHashValidateAlgorithm(algorithm string) bool {
return obrimHashSupportedAlgorithms[algorithm]
}
// Function Name: obrimHashGenerateHash
// Function Purpose: Execute the selected hashing algorithm.
func obrimHashGenerateHash(
algorithm string,
value string,
salt string,
) (string, bool) {
input := value
switch algorithm {
case "salted_sha256", "salted_sha512":
input = value + salt
}
switch algorithm {
case "sha256", "salted_sha256":
hash := sha256.Sum256([]byte(input))
return hex.EncodeToString(hash[:]), true
case "sha512", "salted_sha512":
hash := sha512.Sum512([]byte(input))
return hex.EncodeToString(hash[:]), true
default:
return "", false
}
}
// Function Name: obrimHashBuildSuccessPayload
// Function Purpose: Construct success response payloads.
func obrimHashBuildSuccessPayload(
code string,
payload map[string]any,
) map[string]any {
return map[string]any{
"status": true,
"code": code,
"payload": payload,
}
}
// Function Name: obrimHashBuildErrorPayload
// Function Purpose: Construct error response payloads.
func obrimHashBuildErrorPayload(code string) map[string]any {
return map[string]any{
"status": false,
"code": code,
"payload": nil,
}
}
// Function Name: obrimHashCalculate
// Function Purpose: Process hash generation requests.
func obrimHashCalculate(
config map[string]any,
) map[string]any {
mode := config["mode"].(string)
switch mode {
case obrimHashModeStandard:
return obrimHashCalculateStandard(config)
case obrimHashModeSalted:
return obrimHashCalculateSalted(config)
default:
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
}
}
// Function Name: obrimHashCalculateStandard
// Function Purpose: Generate a deterministic hash.
func obrimHashCalculateStandard(
config map[string]any,
) map[string]any {
hashValue, ok := obrimHashGenerateHash(
config["algorithm"].(string),
config["value"].(string),
"",
)
if !ok {
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
}
return obrimHashBuildSuccessPayload(
"SUCCESS_HASH_CALCULATED",
map[string]any{
"algorithm": config["algorithm"].(string),
"hash": hashValue,
},
)
}
// Function Name: obrimHashCalculateSalted
// Function Purpose: Generate a salted hash and salt pair.
func obrimHashCalculateSalted(
config map[string]any,
) map[string]any {
// Logic: Resolve salt.
salt := ""
if value, exists := config["salt"]; exists {
salt = value.(string)
}
if salt == "" {
generatedSalt, ok := obrimHashGenerateSalt()
if !ok {
return obrimHashBuildErrorPayload("FAILED_SALT_GENERATION")
}
salt = generatedSalt
}
hashValue, ok := obrimHashGenerateHash(
config["algorithm"].(string),
config["value"].(string),
salt,
)
if !ok {
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
}
return obrimHashBuildSuccessPayload(
"SUCCESS_HASH_CALCULATED",
map[string]any{
"algorithm": config["algorithm"].(string),
"hash": hashValue,
"salt": salt,
},
)
}
// Function Name: obrimHashGenerateSalt
// Function Purpose: Generate a cryptographically secure salt.
func obrimHashGenerateSalt() (string, bool) {
// Logic: Generate secure random bytes.
saltBytes := make([]byte, 32)
if _, err := rand.Read(saltBytes); err != nil {
return "", false
}
return hex.EncodeToString(saltBytes), true
}
// Function Name: obrimHashCompare
// Function Purpose: Process hash verification requests.
func obrimHashCompare(
config map[string]any,
) map[string]any {
mode := config["mode"].(string)
switch mode {
case obrimHashModeStandard:
return obrimHashCompareStandard(config)
case obrimHashModeSalted:
return obrimHashCompareSalted(config)
default:
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
}
}
// Function Name: obrimHashCompareStandard
// Function Purpose: Regenerate a standard hash for verification.
func obrimHashCompareStandard(
config map[string]any,
) map[string]any {
regeneratedHash, ok := obrimHashGenerateHash(
config["algorithm"].(string),
config["value"].(string),
"",
)
if !ok {
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
}
matched := obrimHashVerify(
regeneratedHash,
config["hash"].(string),
)
return obrimHashBuildSuccessPayload(
"SUCCESS_HASH_COMPARED",
map[string]any{
"algorithm": config["algorithm"].(string),
"matched": matched,
"hash": config["hash"].(string),
},
)
}
// Function Name: obrimHashCompareSalted
// Function Purpose: Regenerate a salted hash for verification.
func obrimHashCompareSalted(
config map[string]any,
) map[string]any {
salt := config["salt"].(string)
regeneratedHash, ok := obrimHashGenerateHash(
config["algorithm"].(string),
config["value"].(string),
salt,
)
if !ok {
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
}
matched := obrimHashVerify(
regeneratedHash,
config["hash"].(string),
)
return obrimHashBuildSuccessPayload(
"SUCCESS_HASH_COMPARED",
map[string]any{
"algorithm": config["algorithm"].(string),
"matched": matched,
"hash": config["hash"].(string),
"salt": salt,
},
)
}
// Function Name: obrimHashVerify
// Function Purpose: Compare regenerated and supplied hash values.
func obrimHashVerify(
regeneratedHash string,
suppliedHash string,
) bool {
return strings.Compare(regeneratedHash, suppliedHash) == 0
}