obrimbaseapi/essential/visible/service/helper/key/key.go

277 lines
7.4 KiB
Go

package key
import (
"crypto/aes"
"crypto/ed25519"
"crypto/rand"
"encoding/base64"
"strings"
"time"
)
// ObrimKeyResponse represents the standardized utility response.
type ObrimKeyResponse struct {
Status bool `json:"status"`
Code string `json:"code"`
Payload map[string]any `json:"payload"`
}
// obrimKeyAllowedSymmetricFields defines allowed symmetric configuration fields.
var obrimKeyAllowedSymmetricFields = map[string]struct{}{
"algorithm": {},
"key_size": {},
}
// obrimKeyAllowedAsymmetricFields defines allowed asymmetric configuration fields.
var obrimKeyAllowedAsymmetricFields = map[string]struct{}{
"algorithm": {},
}
// ObrimKey dispatches key generation requests and orchestrates validation, generation, and response construction.
func ObrimKey(keyType string, config map[string]any) map[string]any {
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_MISSING_TYPE")
}
if config == nil {
return obrimKeyBuildError("FAILED_MISSING_CONFIG")
}
normalizedType := strings.ToLower(strings.TrimSpace(keyType))
switch normalizedType {
case "symmetric":
return obrimKeyValidateSymmetricConfig(config)
case "asymmetric":
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 {
switch strings.ToLower(strings.TrimSpace(keyType)) {
case "symmetric":
return obrimKeyGenerateSymmetric(config)
case "asymmetric":
return obrimKeyGenerateAsymmetric(config)
default:
return obrimKeyBuildError("FAILED_UNSUPPORTED_TYPE")
}
}
// obrimKeyValidateSymmetricConfig validates symmetric configuration values.
func obrimKeyValidateSymmetricConfig(config map[string]any) map[string]any {
for field := range config {
if _, exists := obrimKeyAllowedSymmetricFields[field]; !exists {
return obrimKeyBuildError("FAILED_INVALID_CONFIG_FIELD")
}
}
algorithmValue, exists := config["algorithm"]
if !exists {
return obrimKeyBuildError("FAILED_MISSING_ALGORITHM")
}
algorithm, ok := algorithmValue.(string)
if !ok {
return obrimKeyBuildError("FAILED_INVALID_ALGORITHM")
}
if strings.ToLower(strings.TrimSpace(algorithm)) != "aes" {
return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM")
}
keySizeValue, exists := config["key_size"]
if !exists {
return obrimKeyBuildError("FAILED_MISSING_KEY_SIZE")
}
keySize, ok := obrimKeyConvertInt(keySizeValue)
if !ok {
return obrimKeyBuildError("FAILED_INVALID_KEY_SIZE")
}
switch keySize {
case 128, 192, 256:
return nil
default:
return obrimKeyBuildError("FAILED_UNSUPPORTED_KEY_SIZE")
}
}
// obrimKeyValidateAsymmetricConfig validates asymmetric configuration values.
func obrimKeyValidateAsymmetricConfig(config map[string]any) map[string]any {
for field := range config {
if _, exists := obrimKeyAllowedAsymmetricFields[field]; !exists {
return obrimKeyBuildError("FAILED_INVALID_CONFIG_FIELD")
}
}
algorithmValue, exists := config["algorithm"]
if !exists {
return obrimKeyBuildError("FAILED_MISSING_ALGORITHM")
}
algorithm, ok := algorithmValue.(string)
if !ok {
return obrimKeyBuildError("FAILED_INVALID_ALGORITHM")
}
if strings.ToLower(strings.TrimSpace(algorithm)) != "ecc" {
return obrimKeyBuildError("FAILED_UNSUPPORTED_ALGORITHM")
}
return nil
}
// obrimKeyGenerateSymmetric generates symmetric key material.
func obrimKeyGenerateSymmetric(config map[string]any) map[string]any {
normalizedConfig := obrimKeyNormalizeSymmetricConfig(config)
payload, errorCode := obrimKeyGenerateAES(normalizedConfig)
if errorCode != "" {
return obrimKeyBuildError(errorCode)
}
return obrimKeyBuildPayload(payload)
}
// obrimKeyGenerateAES generates AES key material.
func obrimKeyGenerateAES(config map[string]any) (map[string]any, string) {
keySize := config["key_size"].(int)
// obrimKeyMaterial stores generated AES key bytes.
keyMaterial := make([]byte, keySize/8)
if _, err := rand.Read(keyMaterial); err != nil {
return nil, "FAILED_KEY_GENERATION"
}
if _, err := aes.NewCipher(keyMaterial); err != nil {
return nil, "FAILED_KEY_GENERATION"
}
return map[string]any{
"type": "symmetric",
"algorithm": "aes",
"key_size": keySize,
"key_material": base64.StdEncoding.EncodeToString(keyMaterial),
"generated_at": time.Now().UTC().Format(time.RFC3339),
}, ""
}
// obrimKeyNormalizeSymmetricConfig normalizes symmetric configuration values.
func obrimKeyNormalizeSymmetricConfig(config map[string]any) map[string]any {
keySize, _ := obrimKeyConvertInt(config["key_size"])
return map[string]any{
"algorithm": strings.ToLower(strings.TrimSpace(config["algorithm"].(string))),
"key_size": keySize,
}
}
// obrimKeyGenerateAsymmetric generates asymmetric key material.
func obrimKeyGenerateAsymmetric(config map[string]any) map[string]any {
normalizedConfig := obrimKeyNormalizeAsymmetricConfig(config)
payload, errorCode := obrimKeyGenerateECC(normalizedConfig)
if errorCode != "" {
return obrimKeyBuildError(errorCode)
}
return obrimKeyBuildPayload(payload)
}
// obrimKeyGenerateECC generates ECC key pair material.
func obrimKeyGenerateECC(config map[string]any) (map[string]any, string) {
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
return nil, "FAILED_KEY_GENERATION"
}
return map[string]any{
"type": "asymmetric",
"algorithm": "ecc",
"curve": "eddsa",
"public_key": base64.StdEncoding.EncodeToString(publicKey),
"private_key": base64.StdEncoding.EncodeToString(privateKey),
"generated_at": time.Now().UTC().Format(time.RFC3339),
}, ""
}
// obrimKeyNormalizeAsymmetricConfig normalizes asymmetric configuration values.
func obrimKeyNormalizeAsymmetricConfig(config map[string]any) map[string]any {
return map[string]any{
"algorithm": strings.ToLower(strings.TrimSpace(config["algorithm"].(string))),
}
}
// obrimKeyBuildPayload constructs standardized success payloads.
func obrimKeyBuildPayload(payload map[string]any) map[string]any {
return map[string]any{
"status": true,
"code": "SUCCESS_KEY_GENERATED",
"payload": payload,
}
}
// obrimKeyBuildError constructs standardized error responses.
func obrimKeyBuildError(code string) map[string]any {
return map[string]any{
"status": false,
"code": code,
"payload": nil,
}
}
// obrimKeyConvertInt converts supported numeric values to int.
func obrimKeyConvertInt(value any) (int, bool) {
switch converted := value.(type) {
case int:
return converted, true
case int8:
return int(converted), true
case int16:
return int(converted), true
case int32:
return int(converted), true
case int64:
return int(converted), true
case uint:
return int(converted), true
case uint8:
return int(converted), true
case uint16:
return int(converted), true
case uint32:
return int(converted), true
case uint64:
return int(converted), true
case float32:
if float32(int(converted)) == converted {
return int(converted), true
}
case float64:
if float64(int(converted)) == converted {
return int(converted), true
}
}
return 0, false
}