/
lyra.go
187 lines (151 loc) · 3.72 KB
/
lyra.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package main
import (
"errors"
"flag"
"fmt"
"os"
"reflect"
"strings"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
const (
//BadExit represents an exit with an error(s)
BadExit = 1
//GoodExit represents an exit with no errors
GoodExit = 0
//usage string
usage = `Lyra is a lightweight tool used to protect sensitive data
Usage: lyra [Command]
Commands:
encrypt Encipher a specified file with inputed passphrase
decrypt Decipher a specified file with inputed passphrase
generate Generate passphrase(s)
To get more info on commands do: lyra [Command] --help
`
about = `Lyra is a lightweight tool used to protect sensitive data.
Coded with ❤️ by the Azohra team and made possible with open source software:
* gware by brsmsn (BSD-3-clause) https://github.com/brsmsn/gware
* license available @ https://github.com/brsmsn/gware/blob/master/LICENSE
* memguard by awnumar (Apache 2.0) https://github.com/awnumar/memguard
* License available @ https://github.com/awnumar/memguard/blob/master/LICENSE
* crypto & sys by golang.org (BSD-style) https://github.com/golang/
* license available @ https://github.com/golang/go/blob/master/LICENSE
`
version = `Version: 1.1.0 (May 2018)
`
)
type command interface {
CName() string
Help() string
RegCFlags(*flag.FlagSet)
Run([]string) error
}
//app start point
func main() {
commands := [...]command{
&encryptcmd{},
&decryptcmd{},
&gencmd{},
}
versionSet := flag.Bool("version", false, "")
aboutSet := flag.Bool("about", false, "")
//for lyra --help
flag.Usage = func() {
fmt.Fprint(os.Stderr, usage)
}
flag.Parse()
args := flag.Args()
if *versionSet {
fmt.Fprint(os.Stdout, version)
os.Exit(GoodExit)
} else if *aboutSet {
fmt.Fprint(os.Stdout, about)
os.Exit(GoodExit)
}
cmdName, helpc, exit := parseCmd(args)
if exit {
fmt.Fprint(os.Stderr, usage)
os.Exit(BadExit)
}
for _, val := range commands {
if val.CName() == cmdName {
flags := flag.NewFlagSet(cmdName, flag.ContinueOnError)
flags.SetOutput(os.Stderr)
val.RegCFlags(flags)
if helpc {
fmt.Fprint(os.Stderr, "Available options/flags - see below to learn how to implement them:\n\n")
flags.PrintDefaults()
fmt.Fprint(os.Stderr, val.Help())
os.Exit(BadExit)
}
err := flags.Parse(args[1:])
if err != nil {
handleErr(err)
}
err = val.Run(flags.Args())
if err != nil {
handleErr(err)
}
os.Exit(GoodExit)
}
}
fmt.Fprint(os.Stderr, "Command "+"\""+args[0]+"\" not found\n\n"+usage)
os.Exit(BadExit)
}
func parseCmd(args []string) (name string, helpNd bool, exit bool) {
helpNeeded := func(opt string) bool {
str := strings.ToLower(opt)
return str == "--help" || str == "-h" || str == "-help"
}
switch len(args) {
case 0:
exit = true
case 1:
if helpNeeded(args[0]) {
exit = true
} else {
name = args[0]
}
default:
if helpNeeded(args[1]) {
name = args[0]
helpNd = true
} else {
name = args[0]
}
}
return name, helpNd, exit
}
func handleErr(err error) {
if err != nil {
fmt.Fprint(os.Stderr, "An Error has occurred:\n"+err.Error()+"\n")
os.Exit(BadExit)
}
}
func getPassphrase() []byte {
fmt.Println("Enter passphrase: ")
input, err := terminal.ReadPassword(syscall.Stdin)
handleErr(err)
return input
}
func setPassphrase() ([]byte, error) {
fmt.Println("Enter passphrase: ")
in1, err := terminal.ReadPassword(syscall.Stdin)
handleErr(err)
fmt.Println("Enter passphrase again: ")
in2, err := terminal.ReadPassword(syscall.Stdin)
handleErr(err)
defer wipe(in2)
if !reflect.DeepEqual(in1, in2) {
return nil, errors.New("Inputed passphrases do not match")
}
return in1, nil
}
func wipe(ins ...[]byte) {
for _, val := range ins {
for k := range val {
val[k] = 0
}
}
}