505 lines
14 KiB
Go
Executable File
505 lines
14 KiB
Go
Executable File
package keygen
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"time"
|
|
|
|
"sources.truenas.cloud/code/syscrypt/internal/utils"
|
|
"sources.truenas.cloud/code/syscrypt/internal/vars"
|
|
)
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func FirstRun() {
|
|
|
|
defaultFolder := configuration.ConfigKeyFolder
|
|
|
|
//fmt.Printf("default folder: %s\n", defaultFolder)
|
|
|
|
//fmt.Printf("[DEBUG KEYGEN] Value: %s | Addr: %p\n", config.KeyFolder, &config.KeyFolder)
|
|
|
|
//defaultFolder := config.KeyFolder
|
|
|
|
//defaultKey := config.KeyFolder + "/" + config.MasterKey
|
|
//defaultKeyExists := utils.FileExists(defaultKey)
|
|
//defaultFolderExists := utils.FolderExists(defaultFolder)
|
|
|
|
//fmt.Printf("CONFIG KEY FOLDER: %s\n", config.KeyFolder)
|
|
|
|
_ = defaultFolder
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func Validate() {
|
|
|
|
keygenAllowedFlags := map[string]struct{}{
|
|
"-C": {},
|
|
"-i": {},
|
|
"-c": {},
|
|
"-PQ": {},
|
|
"-k": {},
|
|
"-f": {},
|
|
}
|
|
|
|
utils.ValidateAllowedFlags(keygenAllowedFlags)
|
|
|
|
keygenRequiredFlags := []vars.FlagRequirement{
|
|
{Flag: "-f", IsRequired: true},
|
|
}
|
|
|
|
// friendly name -f
|
|
// keypath -K
|
|
// output -o
|
|
|
|
utils.ValidateRequiredFlags(keygenRequiredFlags, "keygen")
|
|
|
|
// friendlyname
|
|
|
|
isFriendlySet, friendlyHasValue := utils.IsFlagPassed("f")
|
|
friendlyValue, _ := utils.GetFlagValue("f")
|
|
isFriendlyValid := utils.IsAlphaNumeric(friendlyValue)
|
|
|
|
if isFriendlySet && !friendlyHasValue {
|
|
msg := fmt.Sprintf("%s: -f FRIENDLYNAME: requires a value.\n"+
|
|
"Do not enter spaces or special characters. e.g. 'masterkey'", vars.CommandFlag)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if isFriendlySet && friendlyHasValue && !isFriendlyValid {
|
|
msg := fmt.Sprintf("%s: -f FRIENDLYNAME: invalid friendly name.\n"+
|
|
"The friendly name requires an alphanumeric value. e.g. 'masterkey'\n"+
|
|
"Do not enter paths, spaces, special characters or file extensions.", vars.CommandFlag)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// check default keys
|
|
|
|
// keypath
|
|
|
|
isKeyPathSet, keyPathHasValue := utils.IsFlagPassed("k")
|
|
keyPathValue, _ := utils.GetFlagValue("k")
|
|
keyPathIsValid := utils.IsValidPath(keyPathValue)
|
|
keyPathExists := utils.FolderExists(keyPathValue)
|
|
|
|
if isKeyPathSet && !keyPathHasValue {
|
|
msg := fmt.Sprintf("%s: -k KEYPATH: requires a value.", vars.CommandFlag)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if isKeyPathSet && !keyPathIsValid {
|
|
msg := fmt.Sprintf("%s: -k KEYPATH: requires a valid folder path.", vars.CommandFlag)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if isKeyPathSet && keyPathIsValid && !keyPathExists {
|
|
msg := fmt.Sprintf("%s: -k KEYPATH: folder path '%s' does not exist.", vars.CommandFlag, keyPathValue)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
var keyFolder string
|
|
var defaultSet bool
|
|
|
|
if isKeyPathSet {
|
|
defaultSet = false
|
|
keyFolder = keyPathValue
|
|
} else {
|
|
defaultSet = true
|
|
keyFolder = config.KeyFolder
|
|
}
|
|
|
|
if defaultSet {
|
|
keyPathIsValid = utils.IsValidPath(keyFolder)
|
|
}
|
|
|
|
if defaultSet && !keyPathIsValid {
|
|
msg := fmt.Sprintf("%s: DEFAULT KEYPATH '%s' was not found.", vars.CommandFlag, config.KeyFolder)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// comment
|
|
|
|
isCommentSet, commentHasValue := utils.IsFlagPassed("C")
|
|
if isCommentSet && !commentHasValue {
|
|
msg := fmt.Sprintf("%s: -C COMMENT: flag is set but no value was provided.", vars.CommandFlag)
|
|
utils.HandleFailure(msg)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Printf("key folder: %s\n", keyFolder)
|
|
|
|
_ = isKeyPathSet
|
|
_ = keyPathHasValue
|
|
_ = keyPathIsValid
|
|
_ = keyPathExists
|
|
_ = keyFolder
|
|
|
|
// comment
|
|
|
|
// output
|
|
|
|
KeyGen()
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func generateRandomSerial() string {
|
|
token := make([]byte, 15)
|
|
rand.Read(token)
|
|
return hex.EncodeToString(token)
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func getCurrentDate() string {
|
|
return time.Now().Format("2006-01-02 15:04:05")
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func saveKeyFile(filename string, permission string, data interface{}) {
|
|
|
|
fmt.Printf("%v\n", data)
|
|
os.Exit(1)
|
|
|
|
if permission == "" {
|
|
fmt.Printf("error: permission code required.\n")
|
|
return
|
|
}
|
|
|
|
fileData, err := json.MarshalIndent(data, "", " ")
|
|
if err != nil {
|
|
fmt.Printf("error encoding json: %v\n", err)
|
|
return
|
|
}
|
|
|
|
err = os.WriteFile(filename, fileData, 0600)
|
|
if err != nil {
|
|
fmt.Printf("Error writing %s: %v\n", filename, err)
|
|
return
|
|
}
|
|
|
|
permUint, _ := strconv.ParseUint(permission, 8, 32)
|
|
err = os.Chmod(filename, os.FileMode(permUint))
|
|
if err != nil {
|
|
fmt.Printf("Error adjusting permissions on %s: %v\n", filename, err)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("Success: '%s' saved successfully.\n", filename)
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func KeyGen() {
|
|
|
|
outputFolder, _ := utils.GetFlagValue("o")
|
|
isPQSet, _ := utils.IsFlagPassed("PQ")
|
|
commentValue, _ := utils.GetFlagValue("C")
|
|
|
|
if outputFolder == "" {
|
|
outputFolder = config.KeyFolder
|
|
}
|
|
|
|
_ = isPQSet
|
|
_ = commentValue
|
|
|
|
//fmt.Printf("%s", config.KeyFolder)
|
|
|
|
//outputValue, _ := utils.GetFlagValue("o")
|
|
//isPQSet, _ := utils.IsFlagPassed("PQ")
|
|
//commentValue, _ := utils.GetFlagValue("C")
|
|
|
|
//pubWrap := syscrypt.PublicKeyWrapper{}
|
|
//privWrap := syscrypt.PrivateKeyWrapper{}
|
|
//apiWrap := syscrypt.ApiKeyWrapper{}
|
|
///
|
|
//var privX, pubX [32]byte
|
|
//io.ReadFull(rand.Reader, privX[:])
|
|
//curve25519.ScalarBaseMult(&pubX, &privX)
|
|
|
|
//serial := generateRandomSerial()
|
|
//date := getCurrentDate()
|
|
|
|
//password := (generatepassword)
|
|
|
|
//pubWrap.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubX[:])
|
|
//pubWrap.PublicKey.Serial = serial
|
|
//pubWrap.PublicKey.Date = date
|
|
//pubWrap.PublicKey.Comment = commentValue
|
|
|
|
//privWrap.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privX[:])
|
|
//privWrap.PrivateKey.Serial = serial
|
|
//privWrap.PrivateKey.Date = date
|
|
//privWrap.PrivateKey.Comment = commentValue
|
|
|
|
//apiWrap.ApiKey.Key = ""
|
|
//apiWrap.ApiKey.Serial = serial
|
|
//apiWrap.ApiKey.Date = date
|
|
//apiWrap.ApiKey.Comment = commentValue
|
|
|
|
/*
|
|
type ApiKeyWrapper struct {
|
|
ApiKey struct {
|
|
Key string `json:"key"`
|
|
Serial string `json:"serial"`
|
|
Date string `json:"date"`
|
|
Comment string `json:"comment"`
|
|
} `json:"APIKey"`
|
|
}
|
|
|
|
*/
|
|
|
|
//if isPQSet {
|
|
// scheme := kyber768.Scheme()
|
|
// pkK, skK, err := scheme.GenerateKeyPair()
|
|
// if err != nil {
|
|
// fmt.Printf("error: keygen failed: %v\n", err)
|
|
// return
|
|
// }
|
|
|
|
// pkBytes, _ := pkK.MarshalBinary()
|
|
// skBytes, _ := skK.MarshalBinary()
|
|
|
|
// pubWrap.PublicKey.MLKEMKey = vars.PQPublicKeyPrefixLabel + hex.EncodeToString(pkBytes)
|
|
// privWrap.PrivateKey.MLKEMKey = vars.PQPrivateKeyPrefixLabel + hex.EncodeToString(skBytes)
|
|
//}
|
|
|
|
//pubJSON, err := json.MarshalIndent(pubWrap, "", " ")
|
|
//if err != nil {
|
|
// fmt.Printf("Marshal Error: %v\n", err)
|
|
// return
|
|
//}
|
|
|
|
//privJSON, err := json.MarshalIndent(privWrap, "", " ")
|
|
//if err != nil {
|
|
// fmt.Printf("Marshal Error: %v\n", err)
|
|
// return
|
|
//}
|
|
|
|
//MasterFolder := config.KeyFolder
|
|
|
|
// Public Key File
|
|
|
|
//pubFullPath := outputValue
|
|
//pubDir := filepath.Dir(pubFullPath)
|
|
//pubBase := filepath.Base(pubFullPath)
|
|
//pubExt := filepath.Ext(pubBase)
|
|
//pubFileName := strings.TrimSuffix(pubBase, pubExt)
|
|
//pubFilePath := MasterFolder + "/" + pubFileName + ".pub" + pubExt
|
|
|
|
// API Key File
|
|
|
|
//apiFullPath := outputValue
|
|
//apiDir := filepath.Dir(apiFullPath)
|
|
//apiBase := filepath.Base(apiFullPath)
|
|
//apiExt := filepath.Ext(apiBase)
|
|
//apiFileName := strings.TrimSuffix(apiBase, apiExt)
|
|
//apiFilePath := MasterFolder + "/" + apiFileName + ".api" + apiExt
|
|
|
|
// Master Password
|
|
/*
|
|
passFullPath := outputValue
|
|
passDir := filepath.Dir(passFullPath)
|
|
passBase := filepath.Base(passFullPath)
|
|
passExt := filepath.Ext(passBase)
|
|
passFileName := strings.TrimSuffix(passBase, passExt)
|
|
passFilePath := MasterFolder + "/" + passFileName + ".secret" + passExt
|
|
|
|
fmt.Printf("fullpath: %s\n", passFullPath)
|
|
fmt.Printf("dir: %s\n", passDir)
|
|
fmt.Printf("base: %s\n", passBase)
|
|
fmt.Printf("ext: %s\n", passExt)
|
|
fmt.Printf("filename: %s\n", passFileName)
|
|
fmt.Printf("path: %s\n", passFilePath)
|
|
|
|
*/
|
|
|
|
// Save to disk
|
|
|
|
//err = os.WriteFile(pubFilePath, pubJSON, 0644)
|
|
//if err != nil {
|
|
// fmt.Printf("File Error: %v\n", err)
|
|
// os.Exit(1)
|
|
//}
|
|
|
|
//err = os.WriteFile(outputValue, privJSON, 0600)
|
|
//if err != nil {
|
|
// fmt.Printf("File Error: %v\n", err)
|
|
// os.Exit(1)
|
|
//}
|
|
|
|
//saveKeyFile(outputValue, "600", privJSON)
|
|
|
|
//saveKeyFile(filename string, permission string, data interface{})
|
|
|
|
////pubFullPath := outputValue
|
|
////pubDir := filepath.Dir(pubFullPath)
|
|
////pubBase := filepath.Base(pubFullPath)
|
|
////pubExt := filepath.Ext(pubBase)
|
|
////pubClean := strings.TrimSuffix(pubBase, pubExt)
|
|
////pubFileOut := pubClean + ".pub" + pubExt
|
|
////pubFileOut = pubDir + "/" + pubFileOut
|
|
|
|
//_ = outputValue
|
|
//_ = commentValue
|
|
//_ = pubJSON
|
|
//_ = privJSON
|
|
//_ = pubDir
|
|
//_ = pubFilePath
|
|
//_ = apiDir
|
|
//_ = apiFilePath
|
|
//_ = apiWrap
|
|
//_ = passDir
|
|
//_ = passFilePath
|
|
|
|
//fmt.Printf("%v\n", pkK)
|
|
//fmt.Printf("%v\n", skK)
|
|
|
|
////outputValue, _ := utils.GetFlagValue("o")
|
|
|
|
////isPQSet, _ := utils.IsFlagPassed("PQ")
|
|
////commentValue, _ := utils.GetFlagValue("C")
|
|
|
|
////privX := make([]byte, 32)
|
|
////rand.Read(privX)
|
|
////pubX, _ := curve25519.X25519(privX, curve25519.Basepoint)
|
|
|
|
////pubWrap := syscrypt.PublicKeyWrapper{}
|
|
////privWrap := syscrypt.PrivateKeyWrapper{}
|
|
////apiWrap := syscrypt.ApiKeyWrapper{}
|
|
|
|
////_ = apiWrap
|
|
///
|
|
////serial := generateRandomSerial()
|
|
////date := getCurrentDate()
|
|
|
|
////if isPQSet {
|
|
//// pubK, privK, _ := kyber768.GenerateKeyPair(rand.Reader)
|
|
//// pBytes, _ := pubK.MarshalBinary()
|
|
//// sBytes, _ := privK.MarshalBinary()
|
|
//// pubWrap.PublicKey.MLKEMKey = vars.PQPublicKeyPrefixLabel + hex.EncodeToString(pBytes)
|
|
//// privWrap.PrivateKey.MLKEMKey = vars.PQPrivateKeyPrefixLabel + hex.EncodeToString(sBytes)
|
|
////}
|
|
|
|
////pubWrap.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubX)
|
|
////pubWrap.PublicKey.Serial = serial
|
|
////pubWrap.PublicKey.Date = date
|
|
////pubWrap.PublicKey.Comment = commentValue
|
|
|
|
////privWrap.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privX)
|
|
////privWrap.PrivateKey.Serial = serial
|
|
////privWrap.PrivateKey.Date = date
|
|
////privWrap.PrivateKey.Comment = commentValue
|
|
|
|
//apiWrap.ApiKey.Key = GenerateAPIKey(xxx, )
|
|
//apiWrap.ApiKey.Serial = serial
|
|
//apiWrap.ApiKey.Date = date
|
|
//apiWrap.ApiKey.Comment = commentValue
|
|
|
|
//type ApiKeyWrapper struct {
|
|
// ApiKey struct {
|
|
// Key string `json:"key"`
|
|
// Serial string `json:"serial"`
|
|
// Date string `json:"date"`
|
|
// Comment string `json:"comment"`
|
|
// } `json:"APIKey"`
|
|
//}
|
|
|
|
////fmt.Printf("public key: %s\n", pubWrap.PublicKey.Key)
|
|
////fmt.Printf("private key: %s\n", privWrap.PrivateKey.Key)
|
|
////fmt.Printf("pq: %s\n", pubWrap.PublicKey.MLKEMKey)
|
|
|
|
//preview, _ := json.MarshalIndent(privWrap, "", " ")
|
|
//fmt.Println(string(preview))
|
|
|
|
////pubFullPath := outputValue
|
|
////pubDir := filepath.Dir(pubFullPath)
|
|
////pubBase := filepath.Base(pubFullPath)
|
|
////pubExt := filepath.Ext(pubBase)
|
|
////pubClean := strings.TrimSuffix(pubBase, pubExt)
|
|
////pubFileOut := pubClean + ".pub" + pubExt
|
|
////pubFileOut = pubDir + "/" + pubFileOut
|
|
|
|
////apiFullPath := outputValue
|
|
////apiDir := filepath.Dir(apiFullPath)
|
|
////apiBase := filepath.Base(apiFullPath)
|
|
////apiExt := filepath.Ext(apiBase)
|
|
////apiClean := strings.TrimSuffix(apiBase, apiExt)
|
|
////apiFileOut := apiClean + ".api" + apiExt
|
|
////apiFileOut = apiDir + "/" + apiFileOut
|
|
|
|
// Generate Master Password if one doesnt already exist
|
|
|
|
//mpExists := utils.ReadJson("config.masterpass", config.ConfigPath)
|
|
|
|
////_ = pubDir
|
|
////_ = apiDir
|
|
////_ = apiFileOut
|
|
|
|
////fmt.Printf("public out: %s\n", pubDir+"/"+pubFileOut)
|
|
////fmt.Printf("api out: %s\n", apiDir+"/"+apiFileOut)
|
|
|
|
////saveKeyFile(pubFileOut, "0600", pubWrap)
|
|
////saveKeyFile(outputValue, "0644", privWrap)
|
|
//saveKeyFile(xxxx, 0600, xxxxxx)
|
|
|
|
//func saveKeyFile(filename string, permission string, data interface{}) {
|
|
|
|
//type PublicKeyWrapper struct {
|
|
// PublicKey struct {
|
|
// Key string `json:"key"`
|
|
// MLKEMKey string `json:"mlkem_key,omitempty"`
|
|
// Serial string `json:"serial"`
|
|
// Date string `json:"date"`
|
|
// Comment string `json:"comment"`
|
|
// } `json:"PublicKey"`
|
|
//}
|
|
|
|
//privRaw := make([]byte, 32)
|
|
//serial := utils.GenerateSerial(27)
|
|
//io.ReadFull(rand.Reader, privRaw)
|
|
//pubRaw, _ := curve25519.X25519(privRaw, curve25519.Basepoint)
|
|
//dateStr := time.Now().Format("2006-01-02 15:04:05")
|
|
|
|
//privStruct := syscrypt.PrivateKeyWrapper{}
|
|
//privStruct.PrivateKey.Key = vars.PrivateKeyPrefixLabel + hex.EncodeToString(privRaw)
|
|
//privStruct.PrivateKey.Serial = serial
|
|
//privStruct.PrivateKey.Date = dateStr
|
|
//privStruct.PrivateKey.Comment = vars.Comment
|
|
|
|
//pubStruct := syscrypt.PublicKeyWrapper{}
|
|
//pubStruct.PublicKey.Key = vars.DefaultPrefixLabel + hex.EncodeToString(pubRaw)
|
|
//pubStruct.PublicKey.Serial = serial
|
|
//pubStruct.PublicKey.Date = dateStr
|
|
//pubStruct.PublicKey.Comment = vars.Comment
|
|
|
|
//pBytes, _ := json.MarshalIndent(privStruct, "", " ")
|
|
//pubBytes, _ := json.MarshalIndent(pubStruct, "", " ")
|
|
|
|
//fmt.Printf("%s\n", pBytes)
|
|
//fmt.Printf("%s\n", pubBytes)
|
|
//fmt.Printf("%s\n", pubStruct.PublicKey.Serial)
|
|
|
|
//utils.GenerateKeys(pubStruct.PublicKey.Key, privStruct.PrivateKey.Key, serial)
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|