Browse Source

Initial Commit

tags/v0.1
Sarah Jamie Lewis 2 months ago
commit
cbe0e65472
6 changed files with 490 additions and 0 deletions
  1. +10
    -0
      .gitignore
  2. +127
    -0
      api/api.go
  3. +10
    -0
      go.mod
  4. +62
    -0
      go.sum
  5. +36
    -0
      lockbox.go
  6. +245
    -0
      qml/main.qml

+ 10
- 0
.gitignore View File

@@ -0,0 +1,10 @@
*moc.cpp
moc_*.go
*cpp
*.h
rcc*
.idea/
vendor/
deploy/
tor/
*moc.go

+ 127
- 0
api/api.go View File

@@ -0,0 +1,127 @@
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"
"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{}
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 := ""
if schemeDefined == false {
for k := range data {
schema = append(schema, k)
outputLine += fmt.Sprintf(`"%v",`, strings.ReplaceAll(k, "\"", "\\\""))
}
outputfile = append(outputfile, outputLine)
schemeDefined = true
}
outputLine = ""
for _, k := range schema {
outputLine += fmt.Sprintf(`"%v",`, strings.ReplaceAll(data[k], "\"", "\\\""))
}
outputfile = append(outputfile, outputLine)
}
} 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)
public, private, err := box.GenerateKey(rand.Reader)
if err == nil {
publicStr := base64.StdEncoding.EncodeToString(public[:])
privateStr := base64.StdEncoding.EncodeToString(private[:])
err = ioutil.WriteFile(path.Join(cleanPath(keyPath), "key.public"), []byte(publicStr), 0644)
if err == nil {
err = ioutil.WriteFile(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(path string) string {
return strings.Replace(path, "file://", "", 1)
}

+ 10
- 0
go.mod View File

@@ -0,0 +1,10 @@
module git.openprivacy.ca/openprivacy/lockbox

go 1.13

require (
cwtch.im/tapir v0.1.17 // indirect
git.openprivacy.ca/openprivacy/log v1.0.0
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a
)

+ 62
- 0
go.sum View File

@@ -0,0 +1,62 @@
cwtch.im/tapir v0.1.17 h1:2jVZUe1a88tMI4aJPvRTO4Id3NN3PsM62cT5lntEChk=
cwtch.im/tapir v0.1.17/go.mod h1:HzezugpEx+nZ3LdyDsl0w6n45IJYnOt8uqldkLWmaqs=
git.openprivacy.ca/openprivacy/connectivity v1.1.0 h1:9PEeKuPdoIRYeA62BUkBW2BfK4KqKEXz1fvUxZoP4xs=
git.openprivacy.ca/openprivacy/connectivity v1.1.0/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
git.openprivacy.ca/openprivacy/connectivity v1.1.1 h1:hKxBOmxP7Jdu3K1BJ93mRtKNiWUoP6YHt/o2snE2Z0w=
git.openprivacy.ca/openprivacy/connectivity v1.1.1/go.mod h1:4P8mirZZslKbo2zBrXXVjgEdqGwHo/6qoFBwFQW6d6E=
git.openprivacy.ca/openprivacy/libricochet-go v1.0.11 h1:C7QFFzG0p5XKu0zcOIdLGwEpA9uU0BceBM7CfVK5D40=
git.openprivacy.ca/openprivacy/log v1.0.0 h1:Rvqm1weUdR4AOnJ79b1upHCc9vC/QF1rhSD2Um7sr1Y=
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca h1:Q2r7AxHdJwWfLtBZwvW621M3sPqxPc6ITv2j1FGsYpw=
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e h1:XWcjeEtTFTOVA9Fs1w7n2XBftk5ib4oZrhzWk0B+3eA=
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f h1:06ICDSmDOBUC9jwgv44ngvyHzwudJNLa5H+rbCyDFRY=
github.com/therecipe/qt v0.0.0-20191101232336-18864661ae4f/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a h1:aczoJ0HPNE92XKa7DrIzkNN6esOKO2TBwiiYoKcINhA=
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 36
- 0
lockbox.go View File

@@ -0,0 +1,36 @@
package main

import (
"git.openprivacy.ca/openprivacy/lockbox/api"
"git.openprivacy.ca/openprivacy/log"
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/qml"
"github.com/therecipe/qt/quickcontrols2"
"github.com/therecipe/qt/widgets"
"os"
)

func main() {
log.SetLevel(log.LevelDebug)

core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)

app := widgets.NewQApplication(len(os.Args), os.Args)
app.SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)
quickcontrols2.QQuickStyle_SetStyle("Material")
engine := qml.NewQQmlApplicationEngine(nil)

lockapi := api.NewLockBoxAPI(nil)

engine.RootContext().SetContextProperty("lockbox", lockapi)
// load the embedded qml file
// created by either qtrcc or qtdeploy
//engine.Load(core.NewQUrl3("qrc:/qml/main.qml", 0))
// you can also load a local file like this instead:
engine.Load(core.QUrl_FromLocalFile("./qml/main.qml"))

// start the main Qt event loop
// and block until app.Exit() is called
// or the window is closed by the user
widgets.QApplication_Exec()
}

+ 245
- 0
qml/main.qml View File

@@ -0,0 +1,245 @@
import QtQuick 2.7 //ApplicationWindow
import QtQuick.Controls 2.1 //Dialog
import QtQuick.Controls 2.12
import QtQuick 2.12
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.12


ApplicationWindow {
id: root
visible: true
title: "Open Privacy LockBox"
minimumWidth: 640
minimumHeight: 640

FileDialog {
id: fileDialog
title: "Please choose a file to decrypt"
nameFilters: [ "Dat File (*.dat)", "All files (*)" ]
folder: shortcuts.home
selectFolder: false
selectMultiple: false
onAccepted: {
console.log("You chose: " + fileDialog.fileUrls)
inputFileLabel.text = fileDialog.fileUrls[0]
}
onRejected: {
console.log("Canceled")
}
Component.onCompleted: visible = false
}

Column {
anchors.horizontalCenter: parent.horizontalCenter
width:parent.width
padding:10

Row {
width:parent.width
padding:10
Label {
text: "Decrypt a File"
font.pixelSize: 22
}
}

Row {
width:parent.width
padding:10
TextField {
width:parent.width * 0.50
id:inputFileLabel
placeholderText: "Select an Input File"
}
Button {
Layout.alignment: Qt.AlignRight
text: "Select File To Decrypt"
onClicked: fileDialog.visible = true
}
}
Row {
width:parent.width
padding:10
TextField {
id:outputFileLabel
width:parent.width * 0.50
placeholderText: "Select an Output File"
}
Button {
Layout.alignment: Qt.AlignRight
text: "Select File To Output"
onClicked: outputFileDialog.visible = true
}
}
Row {
width:parent.width
padding:10
TextField {
width:parent.width * 0.50
id:keyFileLabel
placeholderText: "Select a Key File"
}
Button {
Layout.alignment: Qt.AlignRight
text: "Select Private Key"
onClicked: keyFileDialog.visible = true
}
}
Row {
width:parent.width
padding:10
Button {
text: "Decrypt"
onClicked: function() {
lockbox.decryptFile(fileDialog.fileUrls[0],outputFileDialog.fileUrls[0],keyFileDialog.fileUrls[0])
}
}
}
Row {
width:parent.width
padding:10
Rectangle {
width: parent.width-20
height: 1
color: "black"
border.color: "black"
border.width: 1
}
}

Row {
width:parent.width
padding:10
Label {
text: "Generate New Encryption Keys"
font.pixelSize: 22
}
}
Row {
width:parent.width
padding:10
TextField {
width:parent.width * 0.50
id:keyFileGenLabel
placeholderText: "Select a Key File"
}
Button {
Layout.alignment: Qt.AlignRight
text: "Select a Folder to Save Keys"
onClicked: function() {
keyFileCreateDialog.visible = true
}
}
}

Row {
width:parent.width
Button {
text: "Generate a Decryption Key"
onClicked: function() {
lockbox.generateKey(keyFileCreateDialog.fileUrls[0])
}
}
}

}


FileDialog {
id: outputFileDialog
title: "Please choose a file save to"
nameFilters: [ "CSV File (*.csv)", "All files (*)" ]
folder: shortcuts.home
selectFolder: false
selectMultiple: false
selectExisting:false
onAccepted: {
console.log("You chose: " + outputFileDialog.fileUrls)
outputFileLabel.text = outputFileDialog.fileUrls[0]
}
onRejected: {
console.log("Canceled")
}
Component.onCompleted: visible = false


}


FileDialog {
id: keyFileDialog
title: "Please choose an encryption key file"
nameFilters: [ "Key File (*.private)", "All files (*)" ]
folder: shortcuts.home
selectFolder: false
selectMultiple: false
onAccepted: {
console.log("You chose: " + keyFileDialog.fileUrls)
keyFileLabel.text = keyFileDialog.fileUrls[0]
}
onRejected: {
console.log("Canceled")
}
Component.onCompleted: visible = false
}

FileDialog {
id: keyFileCreateDialog
title: "Please choose where to save the encryption key file"
nameFilters: [ "Key File (*.private)", "All files (*)" ]
folder: shortcuts.home
selectFolder: true
selectMultiple: false
onAccepted: {
console.log("You chose: " + keyFileCreateDialog.fileUrls)
keyFileGenLabel.text = keyFileCreateDialog.fileUrls[0]
}
onRejected: {
console.log("Canceled")
}
Component.onCompleted: visible = false
}

Connections { // POPUPS ARE INVOKED BY GO FUNCS
target: lockbox

onDecrypted: function(status, message) {
if (status) {
messageDialog.icon = StandardIcon.Information
messageDialog.title = "Decrypted Successfully"
} else {
messageDialog.icon = StandardIcon.Critical
messageDialog.title = "Error Decrypting"
}

messageDialog.text = message
messageDialog.open()
}

onSaved: function(status, message) {
if (status) {
messageDialog.icon = StandardIcon.Information
messageDialog.title = "Encryption Keys Generating Successfully"
} else {
messageDialog.icon = StandardIcon.Critical
messageDialog.title = "Error Generating Encryption Keys"
}

messageDialog.text = message
messageDialog.open()
}
}


MessageDialog {
id: messageDialog
title: "May I have your attention please"
text: "It's so cool that you are using Qt Quick."
onAccepted: {
messageDialog.close()
}
Component.onCompleted: visible = false
}

}

Loading…
Cancel
Save