lockbox/api/api.go

157 lines
4.2 KiB
Go

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
}