508 lines
10 KiB
Go
508 lines
10 KiB
Go
/*
|
|
|--------------------------------------------------------------------------
|
|
| Manifest
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Name:
|
|
| - Hash
|
|
|
|
|
| Purpose:
|
|
| - Generate and verify cryptographic hash values using standard or
|
|
| salted hashing methods.
|
|
|
|
|
| Guideline:
|
|
| - Use for deterministic hashing workflows.
|
|
| - Use for salted hashing workflows requiring verification support.
|
|
| - Use for integrity verification and fingerprint generation.
|
|
| - Accept exactly two primary parameters: type and config.
|
|
|
|
|
| Example:
|
|
| - 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"
|
|
)
|
|
|
|
// ObrimHash processes hash generation and verification requests.
|
|
func ObrimHash(
|
|
hashType string,
|
|
config map[string]any,
|
|
) map[string]any {
|
|
status.ObrimStatus("INFO", "Hash utility execution started.")
|
|
log.ObrimLog("INIT", "Hash utility execution started.")
|
|
|
|
_, _ = retriever.ObrimRetriever(
|
|
"json",
|
|
map[string]any{
|
|
"resource": "framework/metadata",
|
|
"path": "name",
|
|
},
|
|
)
|
|
|
|
if !obrimHashValidateType(hashType) {
|
|
status.ObrimStatus("ERROR", "Invalid hash type.")
|
|
log.ObrimLog("ERROR", "Invalid hash type.")
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE")
|
|
}
|
|
|
|
if !obrimHashValidateConfig(hashType, config) {
|
|
status.ObrimStatus("ERROR", "Invalid configuration.")
|
|
log.ObrimLog("ERROR", "Invalid configuration.")
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_CONFIG")
|
|
}
|
|
|
|
mode := config["mode"].(string)
|
|
|
|
if !obrimHashValidateMode(mode) {
|
|
status.ObrimStatus("ERROR", "Invalid mode.")
|
|
log.ObrimLog("ERROR", "Invalid mode.")
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
|
|
}
|
|
|
|
algorithm := config["algorithm"].(string)
|
|
|
|
if !obrimHashValidateAlgorithm(mode, algorithm) {
|
|
status.ObrimStatus("ERROR", "Invalid algorithm.")
|
|
log.ObrimLog("ERROR", "Invalid algorithm.")
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_ALGORITHM")
|
|
}
|
|
|
|
switch hashType {
|
|
case "calculate":
|
|
return obrimHashCalculate(config)
|
|
|
|
case "compare":
|
|
return obrimHashCompare(config)
|
|
|
|
default:
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_TYPE")
|
|
}
|
|
}
|
|
|
|
// obrimHashValidateType validates operation type.
|
|
func obrimHashValidateType(hashType string) bool {
|
|
switch hashType {
|
|
case "calculate", "compare":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// obrimHashValidateMode validates hashing mode.
|
|
func obrimHashValidateMode(mode string) bool {
|
|
switch mode {
|
|
case "standard", "salted":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// obrimHashValidateConfig validates configuration keys and values.
|
|
func obrimHashValidateConfig(
|
|
hashType string,
|
|
config map[string]any,
|
|
) bool {
|
|
if config == nil {
|
|
return false
|
|
}
|
|
|
|
// Mutable variable holding supported keys.
|
|
supportedKeys := map[string]bool{
|
|
"mode": true,
|
|
"algorithm": true,
|
|
"value": true,
|
|
"hash": true,
|
|
"salt": true,
|
|
}
|
|
|
|
for key := range config {
|
|
if !supportedKeys[key] {
|
|
return false
|
|
}
|
|
}
|
|
|
|
modeValue, modeExists := config["mode"]
|
|
algorithmValue, algorithmExists := config["algorithm"]
|
|
valueValue, valueExists := config["value"]
|
|
|
|
if !modeExists || !algorithmExists || !valueExists {
|
|
return false
|
|
}
|
|
|
|
mode, modeOK := modeValue.(string)
|
|
algorithm, algorithmOK := algorithmValue.(string)
|
|
value, valueOK := valueValue.(string)
|
|
|
|
if !modeOK || !algorithmOK || !valueOK {
|
|
return false
|
|
}
|
|
|
|
if mode == "" || algorithm == "" || value == "" {
|
|
return false
|
|
}
|
|
|
|
if hashType == "calculate" {
|
|
if mode == "standard" {
|
|
if _, exists := config["salt"]; exists {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
if hashType == "compare" {
|
|
hashValue, hashExists := config["hash"]
|
|
|
|
if !hashExists {
|
|
return false
|
|
}
|
|
|
|
hashString, hashOK := hashValue.(string)
|
|
|
|
if !hashOK || hashString == "" {
|
|
return false
|
|
}
|
|
|
|
if mode == "standard" {
|
|
if _, exists := config["salt"]; exists {
|
|
return false
|
|
}
|
|
}
|
|
|
|
if mode == "salted" {
|
|
saltValue, saltExists := config["salt"]
|
|
|
|
if !saltExists {
|
|
return false
|
|
}
|
|
|
|
saltString, saltOK := saltValue.(string)
|
|
|
|
if !saltOK || saltString == "" {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// obrimHashValidateAlgorithm validates hashing algorithm selection.
|
|
func obrimHashValidateAlgorithm(
|
|
mode string,
|
|
algorithm string,
|
|
) bool {
|
|
if mode == "standard" {
|
|
switch algorithm {
|
|
case "sha256", "sha512":
|
|
return true
|
|
}
|
|
}
|
|
|
|
if mode == "salted" {
|
|
switch algorithm {
|
|
case "salted_sha256", "salted_sha512":
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// obrimHashGenerateHash executes the selected hashing algorithm.
|
|
func obrimHashGenerateHash(
|
|
algorithm string,
|
|
value string,
|
|
salt string,
|
|
) (string, bool) {
|
|
switch algorithm {
|
|
case "sha256":
|
|
sum := sha256.Sum256([]byte(value))
|
|
return hex.EncodeToString(sum[:]), true
|
|
|
|
case "sha512":
|
|
sum := sha512.Sum512([]byte(value))
|
|
return hex.EncodeToString(sum[:]), true
|
|
|
|
case "salted_sha256":
|
|
sum := sha256.Sum256([]byte(value + salt))
|
|
return hex.EncodeToString(sum[:]), true
|
|
|
|
case "salted_sha512":
|
|
sum := sha512.Sum512([]byte(value + salt))
|
|
return hex.EncodeToString(sum[:]), true
|
|
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|
|
|
|
// obrimHashBuildSuccessPayload constructs success response payloads.
|
|
func obrimHashBuildSuccessPayload(
|
|
code string,
|
|
payload map[string]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,
|
|
}
|
|
}
|
|
|
|
// obrimHashCalculate processes hash generation requests.
|
|
func obrimHashCalculate(
|
|
config map[string]any,
|
|
) map[string]any {
|
|
mode := config["mode"].(string)
|
|
|
|
switch mode {
|
|
case "standard":
|
|
return obrimHashCalculateStandard(config)
|
|
|
|
case "salted":
|
|
return obrimHashCalculateSalted(config)
|
|
|
|
default:
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
|
|
}
|
|
}
|
|
|
|
// obrimHashCalculateStandard generates a deterministic hash.
|
|
func obrimHashCalculateStandard(
|
|
config map[string]any,
|
|
) map[string]any {
|
|
algorithm := config["algorithm"].(string)
|
|
value := config["value"].(string)
|
|
|
|
hashValue, success := obrimHashGenerateHash(
|
|
algorithm,
|
|
value,
|
|
"",
|
|
)
|
|
|
|
if !success {
|
|
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
|
|
}
|
|
|
|
payload := map[string]any{
|
|
"algorithm": algorithm,
|
|
"hash": hashValue,
|
|
}
|
|
|
|
status.ObrimStatus("SUCCESS", "Hash generated.")
|
|
log.ObrimLog("SUCCESS", "Standard hash generated.")
|
|
|
|
return obrimHashBuildSuccessPayload(
|
|
"SUCCESS_CALCULATE_STANDARD",
|
|
payload,
|
|
)
|
|
}
|
|
|
|
// obrimHashCalculateSalted generates a salted hash and salt pair.
|
|
func obrimHashCalculateSalted(
|
|
config map[string]any,
|
|
) map[string]any {
|
|
algorithm := config["algorithm"].(string)
|
|
value := config["value"].(string)
|
|
|
|
// Mutable variable holding salt value.
|
|
saltValue := ""
|
|
|
|
if suppliedSalt, exists := config["salt"]; exists {
|
|
saltString, ok := suppliedSalt.(string)
|
|
|
|
if !ok || saltString == "" {
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_SALT")
|
|
}
|
|
|
|
saltValue = saltString
|
|
} else {
|
|
generatedSalt, success := obrimHashGenerateSalt()
|
|
|
|
if !success {
|
|
return obrimHashBuildErrorPayload("FAILED_SALT_GENERATION")
|
|
}
|
|
|
|
saltValue = generatedSalt
|
|
}
|
|
|
|
hashValue, success := obrimHashGenerateHash(
|
|
algorithm,
|
|
value,
|
|
saltValue,
|
|
)
|
|
|
|
if !success {
|
|
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
|
|
}
|
|
|
|
payload := map[string]any{
|
|
"algorithm": algorithm,
|
|
"hash": hashValue,
|
|
"salt": saltValue,
|
|
}
|
|
|
|
status.ObrimStatus("SUCCESS", "Salted hash generated.")
|
|
log.ObrimLog("SUCCESS", "Salted hash generated.")
|
|
|
|
return obrimHashBuildSuccessPayload(
|
|
"SUCCESS_CALCULATE_SALTED",
|
|
payload,
|
|
)
|
|
}
|
|
|
|
// obrimHashGenerateSalt generates a cryptographically secure salt.
|
|
func obrimHashGenerateSalt() (string, bool) {
|
|
// Mutable variable holding salt bytes.
|
|
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 map[string]any,
|
|
) map[string]any {
|
|
mode := config["mode"].(string)
|
|
|
|
switch mode {
|
|
case "standard":
|
|
return obrimHashCompareStandard(config)
|
|
|
|
case "salted":
|
|
return obrimHashCompareSalted(config)
|
|
|
|
default:
|
|
return obrimHashBuildErrorPayload("FAILED_INVALID_MODE")
|
|
}
|
|
}
|
|
|
|
// obrimHashCompareStandard regenerates a standard hash for verification.
|
|
func obrimHashCompareStandard(
|
|
config map[string]any,
|
|
) map[string]any {
|
|
algorithm := config["algorithm"].(string)
|
|
value := config["value"].(string)
|
|
hashValue := config["hash"].(string)
|
|
|
|
regeneratedHash, success := obrimHashGenerateHash(
|
|
algorithm,
|
|
value,
|
|
"",
|
|
)
|
|
|
|
if !success {
|
|
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
|
|
}
|
|
|
|
matched := obrimHashVerify(
|
|
regeneratedHash,
|
|
hashValue,
|
|
)
|
|
|
|
payload := map[string]any{
|
|
"algorithm": algorithm,
|
|
"matched": matched,
|
|
"hash": hashValue,
|
|
}
|
|
|
|
return obrimHashBuildSuccessPayload(
|
|
"SUCCESS_COMPARE_STANDARD",
|
|
payload,
|
|
)
|
|
}
|
|
|
|
// obrimHashCompareSalted regenerates a salted hash for verification.
|
|
func obrimHashCompareSalted(
|
|
config map[string]any,
|
|
) map[string]any {
|
|
algorithm := config["algorithm"].(string)
|
|
value := config["value"].(string)
|
|
hashValue := config["hash"].(string)
|
|
saltValue := config["salt"].(string)
|
|
|
|
regeneratedHash, success := obrimHashGenerateHash(
|
|
algorithm,
|
|
value,
|
|
saltValue,
|
|
)
|
|
|
|
if !success {
|
|
return obrimHashBuildErrorPayload("FAILED_HASH_GENERATION")
|
|
}
|
|
|
|
matched := obrimHashVerify(
|
|
regeneratedHash,
|
|
hashValue,
|
|
)
|
|
|
|
payload := map[string]any{
|
|
"algorithm": algorithm,
|
|
"matched": matched,
|
|
"hash": hashValue,
|
|
"salt": saltValue,
|
|
}
|
|
|
|
return obrimHashBuildSuccessPayload(
|
|
"SUCCESS_COMPARE_SALTED",
|
|
payload,
|
|
)
|
|
}
|
|
|
|
// obrimHashVerify compares regenerated and supplied hash values.
|
|
func obrimHashVerify(
|
|
regeneratedHash string,
|
|
suppliedHash string,
|
|
) bool {
|
|
return strings.Compare(
|
|
regeneratedHash,
|
|
suppliedHash,
|
|
) == 0
|
|
}
|