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) } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////