package api import ( "bufio" "crypto/rand" "encoding/base64" "encoding/json" "fmt" "git.openprivacy.ca/openprivacy/log" "github.com/therecipe/qt/core" "github.com/therecipe/qt/qml" "golang.org/x/crypto/curve25519" "golang.org/x/crypto/nacl/box" "io/ioutil" "os" path "path/filepath" "sort" "strings" ) type LockBoxAPI struct { core.QObject QMLEngine *qml.QQmlApplicationEngine Translator *core.QTranslator _ func(bool, string) `signal:"Decrypted"` _ func(bool, string) `signal:"Saved"` _ func(inputFilename string, outputFilename string, keyfile string) `signal:"decryptFile,auto"` _ func(keyFilename string) `signal:"generateKey,auto"` } func (lapi *LockBoxAPI) decryptFile(inputFilename string, outputFilename string, keyfile string) { log.Infof("Decrypting File...%v to %v", inputFilename, outputFilename) privateKey := [32]byte{} publicKey := [32]byte{} keyencoded, err := ioutil.ReadFile(cleanPath(keyfile)) if err == nil { key, err := base64.StdEncoding.DecodeString(string(keyencoded)) if err == nil { copy(privateKey[:], key[:]) curve25519.ScalarBaseMult(&publicKey, &privateKey) } } file, err := os.Open(cleanPath(inputFilename)) outputfile := []string{} count := 1 if err == nil { defer file.Close() scanner := bufio.NewScanner(file) schemeDefined := false schema := []string{} for scanner.Scan() { line := scanner.Text() lines := strings.Split(line, "|") if len(lines) == 2 { data, err := base64.StdEncoding.DecodeString(lines[1]) if err == nil { message, ok := box.OpenAnonymous([]byte{}, data, &publicKey, &privateKey) if ok { log.Infof("Message: %v, %v\n", string(message), ok) data := make(map[string]string) err := json.Unmarshal(message, &data) if err == nil { outputLine := "num," if schemeDefined == false { for k := range data { schema = append(schema, k) } sort.Strings(schema) for _, k := range schema { parts := strings.SplitN(k, "_", 2) var str string if len(parts) > 1 { str = parts[1] } else { str = k } outputLine += fmt.Sprintf(`"%v",`, strings.ReplaceAll(str, "\"", "\\\"")) } outputfile = append(outputfile, outputLine) schemeDefined = true } outputLine = fmt.Sprintf("%d,", count) for _, k := range schema { outputLine += fmt.Sprintf(`"%v",`, strings.ReplaceAll(data[k], "\"", "\\\"")) } outputfile = append(outputfile, outputLine) count++ } } else { lapi.Decrypted(false, "Error Decrypting File: You might be using the wrong decryption key with this file") return } } } } if err := scanner.Err(); err != nil { } err := ioutil.WriteFile(cleanPath(outputFilename), []byte(strings.Join(outputfile, "\n")), 0644) if err == nil { lapi.Decrypted(true, "File Decrypted Successfully!") return } } lapi.Decrypted(false, err.Error()) } func (lapi *LockBoxAPI) generateKey(keyPath string) { log.Infof("Saving Key to Path to %v", keyPath) _,err := os.Stat(cleanPath(path.Join(cleanPath(keyPath), "key.private"))) if err == nil { lapi.Saved(false, "Cannot generate keys without deleting keys that already exist. Please choose a different directory or remove the existing keys.") return } if os.IsNotExist(err) { public, private, err := box.GenerateKey(rand.Reader) if err == nil { publicStr := base64.StdEncoding.EncodeToString(public[:]) privateStr := base64.StdEncoding.EncodeToString(private[:]) err = ioutil.WriteFile(cleanPath(path.Join(cleanPath(keyPath), "key.public")), []byte(publicStr), 0644) if err == nil { err = ioutil.WriteFile(cleanPath(path.Join(cleanPath(keyPath), "key.private")), []byte(privateStr), 0644) if err == nil { lapi.Saved(true, "Key File Saved") return } else { lapi.Saved(false, err.Error()) return } } else { lapi.Saved(false, err.Error()) return } } } lapi.Saved(false, err.Error()) } func cleanPath(uncleanPath string) string { cleanPath := path.Join(strings.Replace(uncleanPath, "file://", "", 1)) if len(cleanPath) > 1 && cleanPath[0] == '\\' { return cleanPath[1:] } return cleanPath }