349 lines
9.2 KiB
Go
349 lines
9.2 KiB
Go
/*
|
|
|--------------------------------------------------------------------------
|
|
| Manifest
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Name:
|
|
| - Key
|
|
|
|
|
| Purpose:
|
|
| - Generate cryptographic key material using a type-driven dispatch model.
|
|
|
|
|
| Guideline:
|
|
| - Use explicit configuration values only.
|
|
| - Validate all inputs before generation.
|
|
| - Reject unsupported or irrelevant configuration fields.
|
|
| - Use centralized dispatch for workflow execution.
|
|
|
|
|
| Example:
|
|
| - ObrimKey("symmetric", map[string]any{
|
|
| "algorithm": "aes",
|
|
| "key_size": 256,
|
|
| })
|
|
|
|
|
| - ObrimKey("asymmetric", map[string]any{
|
|
| "algorithm": "ecc",
|
|
| })
|
|
|
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Credit
|
|
|--------------------------------------------------------------------------
|
|
|
|
|
| Contributor:
|
|
| - Rajon Ahmed
|
|
| - Scionite
|
|
|
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
package key
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"go/module/essential/visible/service/helper/log"
|
|
"go/module/essential/visible/service/helper/status"
|
|
)
|
|
|
|
const (
|
|
obrimKeyTypeSymmetric = "symmetric"
|
|
obrimKeyTypeAsymmetric = "asymmetric"
|
|
|
|
obrimKeyAlgorithmAES = "aes"
|
|
obrimKeyAlgorithmECC = "ecc"
|
|
|
|
obrimKeyCurveEdDSA = "eddsa"
|
|
)
|
|
|
|
// ObrimKey dispatches key generation requests and orchestrates validation, generation, and response construction.
|
|
func ObrimKey(keyType string, config map[string]any) map[string]any {
|
|
log.ObrimLog("INIT", "Key generation request received.")
|
|
status.ObrimStatus("INFO", "Validating key generation request.")
|
|
|
|
if response := obrimKeyValidate(keyType, config); response != nil {
|
|
return response
|
|
}
|
|
|
|
return obrimKeyDispatch(keyType, config)
|
|
}
|
|
|
|
// obrimKeyValidate validates common request structure and schema integrity.
|
|
func obrimKeyValidate(keyType string, config map[string]any) map[string]any {
|
|
if strings.TrimSpace(keyType) == "" {
|
|
return obrimKeyBuildError("FAILED_TYPE_REQUIRED")
|
|
}
|
|
|
|
if config == nil {
|
|
return obrimKeyBuildError("FAILED_CONFIG_REQUIRED")
|
|
}
|
|
|
|
normalizedType := strings.ToLower(strings.TrimSpace(keyType))
|
|
|
|
switch normalizedType {
|
|
case obrimKeyTypeSymmetric:
|
|
return obrimKeyValidateSymmetricConfig(config)
|
|
|
|
case obrimKeyTypeAsymmetric:
|
|
return obrimKeyValidateAsymmetricConfig(config)
|
|
|
|
default:
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE")
|
|
}
|
|
}
|
|
|
|
// obrimKeyDispatch routes execution to the appropriate cryptographic workflow.
|
|
func obrimKeyDispatch(keyType string, config map[string]any) map[string]any {
|
|
normalizedType := strings.ToLower(strings.TrimSpace(keyType))
|
|
|
|
switch normalizedType {
|
|
case obrimKeyTypeSymmetric:
|
|
return obrimKeyGenerateSymmetric(config)
|
|
|
|
case obrimKeyTypeAsymmetric:
|
|
return obrimKeyGenerateAsymmetric(config)
|
|
|
|
default:
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE")
|
|
}
|
|
}
|
|
|
|
// obrimKeyValidateSymmetricConfig validates symmetric configuration values.
|
|
func obrimKeyValidateSymmetricConfig(config map[string]any) map[string]any {
|
|
if len(config) != 2 {
|
|
return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION")
|
|
}
|
|
|
|
for key := range config {
|
|
if key != "algorithm" && key != "key_size" {
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD")
|
|
}
|
|
}
|
|
|
|
algorithmValue, exists := config["algorithm"]
|
|
if !exists {
|
|
return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED")
|
|
}
|
|
|
|
algorithm, ok := algorithmValue.(string)
|
|
if !ok {
|
|
return obrimKeyBuildError("FAILED_INVALID_ALGORITHM")
|
|
}
|
|
|
|
normalizedConfig := obrimKeyNormalizeSymmetricConfig(config)
|
|
|
|
if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmAES {
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM")
|
|
}
|
|
|
|
keySizeValue, exists := normalizedConfig["key_size"]
|
|
if !exists {
|
|
return obrimKeyBuildError("FAILED_KEY_SIZE_REQUIRED")
|
|
}
|
|
|
|
keySize, ok := keySizeValue.(int)
|
|
if !ok {
|
|
return obrimKeyBuildError("FAILED_INVALID_KEY_SIZE")
|
|
}
|
|
|
|
if keySize != 128 && keySize != 192 && keySize != 256 {
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_KEY_SIZE")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// obrimKeyValidateAsymmetricConfig validates asymmetric configuration values.
|
|
func obrimKeyValidateAsymmetricConfig(config map[string]any) map[string]any {
|
|
if len(config) != 1 {
|
|
return obrimKeyBuildError("FAILED_INVALID_CONFIGURATION")
|
|
}
|
|
|
|
for key := range config {
|
|
if key != "algorithm" {
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_CONFIGURATION_FIELD")
|
|
}
|
|
}
|
|
|
|
algorithmValue, exists := config["algorithm"]
|
|
if !exists {
|
|
return obrimKeyBuildError("FAILED_ALGORITHM_REQUIRED")
|
|
}
|
|
|
|
algorithm, ok := algorithmValue.(string)
|
|
if !ok {
|
|
return obrimKeyBuildError("FAILED_INVALID_ALGORITHM")
|
|
}
|
|
|
|
if strings.ToLower(strings.TrimSpace(algorithm)) != obrimKeyAlgorithmECC {
|
|
return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// obrimKeyGenerateSymmetric generates symmetric key material.
|
|
func obrimKeyGenerateSymmetric(config map[string]any) map[string]any {
|
|
log.ObrimLog("INIT", "Generating symmetric key material.")
|
|
|
|
normalizedConfig := obrimKeyNormalizeSymmetricConfig(config)
|
|
|
|
payload, err := obrimKeyGenerateAES(normalizedConfig)
|
|
if err != nil {
|
|
log.ObrimLog("ERROR", err.Error())
|
|
return obrimKeyBuildError("FAILED_KEY_GENERATION")
|
|
}
|
|
|
|
log.ObrimLog("SUCCESS", "Symmetric key material generated.")
|
|
status.ObrimStatus("SUCCESS", "Key generation completed.")
|
|
|
|
return map[string]any{
|
|
"status": true,
|
|
"code": "SUCCESS_KEY_GENERATED",
|
|
"payload": payload,
|
|
}
|
|
}
|
|
|
|
// obrimKeyGenerateAES generates AES key material.
|
|
func obrimKeyGenerateAES(config map[string]any) (map[string]any, error) {
|
|
// Mutable variable holding key size.
|
|
keySize := config["key_size"].(int)
|
|
|
|
// Mutable variable holding key bytes.
|
|
keyBytes := make([]byte, keySize/8)
|
|
|
|
if _, err := rand.Read(keyBytes); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if _, err := aes.NewCipher(keyBytes); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
payload := map[string]any{
|
|
"type": obrimKeyTypeSymmetric,
|
|
"algorithm": obrimKeyAlgorithmAES,
|
|
"key_size": keySize,
|
|
"key_material": base64.StdEncoding.EncodeToString(keyBytes),
|
|
"generated_at": time.Now().UTC().Format(time.RFC3339),
|
|
}
|
|
|
|
return payload, nil
|
|
}
|
|
|
|
// obrimKeyNormalizeSymmetricConfig normalizes symmetric configuration values.
|
|
func obrimKeyNormalizeSymmetricConfig(config map[string]any) map[string]any {
|
|
normalized := map[string]any{}
|
|
|
|
if value, exists := config["algorithm"]; exists {
|
|
if algorithm, ok := value.(string); ok {
|
|
normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm))
|
|
}
|
|
}
|
|
|
|
if value, exists := config["key_size"]; exists {
|
|
switch typed := value.(type) {
|
|
case int:
|
|
normalized["key_size"] = typed
|
|
case int8:
|
|
normalized["key_size"] = int(typed)
|
|
case int16:
|
|
normalized["key_size"] = int(typed)
|
|
case int32:
|
|
normalized["key_size"] = int(typed)
|
|
case int64:
|
|
normalized["key_size"] = int(typed)
|
|
case float32:
|
|
normalized["key_size"] = int(typed)
|
|
case float64:
|
|
normalized["key_size"] = int(typed)
|
|
}
|
|
}
|
|
|
|
return normalized
|
|
}
|
|
|
|
// obrimKeyGenerateAsymmetric generates asymmetric key material.
|
|
func obrimKeyGenerateAsymmetric(config map[string]any) map[string]any {
|
|
log.ObrimLog("INIT", "Generating asymmetric key material.")
|
|
|
|
normalizedConfig := obrimKeyNormalizeAsymmetricConfig(config)
|
|
|
|
payload, err := obrimKeyGenerateECC(normalizedConfig)
|
|
if err != nil {
|
|
log.ObrimLog("ERROR", err.Error())
|
|
return obrimKeyBuildError("FAILED_KEY_GENERATION")
|
|
}
|
|
|
|
log.ObrimLog("SUCCESS", "Asymmetric key material generated.")
|
|
status.ObrimStatus("SUCCESS", "Key generation completed.")
|
|
|
|
return map[string]any{
|
|
"status": true,
|
|
"code": "SUCCESS_KEY_GENERATED",
|
|
"payload": payload,
|
|
}
|
|
}
|
|
|
|
// obrimKeyGenerateECC generates ECC key pair material.
|
|
func obrimKeyGenerateECC(config map[string]any) (map[string]any, error) {
|
|
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
payload := map[string]any{
|
|
"type": obrimKeyTypeAsymmetric,
|
|
"algorithm": obrimKeyAlgorithmECC,
|
|
"curve": obrimKeyCurveEdDSA,
|
|
"public_key": base64.StdEncoding.EncodeToString(publicKey),
|
|
"private_key": base64.StdEncoding.EncodeToString(privateKey),
|
|
"generated_at": time.Now().UTC().Format(time.RFC3339),
|
|
}
|
|
|
|
return payload, nil
|
|
}
|
|
|
|
// obrimKeyNormalizeAsymmetricConfig normalizes asymmetric configuration values.
|
|
func obrimKeyNormalizeAsymmetricConfig(config map[string]any) map[string]any {
|
|
normalized := map[string]any{}
|
|
|
|
if value, exists := config["algorithm"]; exists {
|
|
if algorithm, ok := value.(string); ok {
|
|
normalized["algorithm"] = strings.ToLower(strings.TrimSpace(algorithm))
|
|
}
|
|
}
|
|
|
|
return normalized
|
|
}
|
|
|
|
// obrimKeyBuildPayload constructs standardized success payloads.
|
|
func obrimKeyBuildPayload(payload map[string]any) map[string]any {
|
|
return map[string]any{
|
|
"status": true,
|
|
"code": "SUCCESS",
|
|
"payload": payload,
|
|
}
|
|
}
|
|
|
|
// obrimKeyBuildError constructs standardized error responses.
|
|
func obrimKeyBuildError(code string) map[string]any {
|
|
log.ObrimLog("ERROR", fmt.Sprintf("Key generation failed: %s", code))
|
|
status.ObrimStatus("ERROR", code)
|
|
|
|
return map[string]any{
|
|
"status": false,
|
|
"code": code,
|
|
"payload": nil,
|
|
}
|
|
}
|