-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathcommands.go
More file actions
201 lines (164 loc) · 6.66 KB
/
commands.go
File metadata and controls
201 lines (164 loc) · 6.66 KB
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Package commands implements the processing of the command line flags and
// processing of the encryption operation.
package commands
import (
"flag"
"fmt"
"log"
"os"
"github.com/kelseyhightower/envconfig"
)
// Default settings.
const (
defaultNetwork = "https://api.drand.sh/"
defaultChain = "dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493"
)
// =============================================================================
const usage = `tlock v1.0.0 -- github.com/drand/tlock
Usage:
tle [--encrypt] (-r round)... [--armor] [-o OUTPUT] [INPUT]
If input is a string (not a file)
tle [--encrypt] (-r round)... [--armor] [-o OUTPUT] [--input INPUT]
tle --decrypt [-o OUTPUT] [INPUT]
Options:
-e, --encrypt Encrypt the input to the output. Default if omitted.
-d, --decrypt Decrypt the input to the output.
-n, --network The drand API endpoint to use.
-c, --chain The chain to use. Can use either beacon ID name or beacon hash. Use beacon hash in order to ensure public key integrity.
-r, --round The specific round to use to encrypt the message. Cannot be used with --duration.
-f, --force Forces to encrypt against past rounds.
-D, --duration How long to wait before the message can be decrypted.
-t, --time Exact time (UTC) when the message can be decrypted
-o, --output Write the result to the file at path OUTPUT.
-a, --armor Encrypt to a PEM encoded format.
-I, --input Encrypt the input string to the output
If the OUTPUT exists, it will be overwritten.
NETWORK defaults to the drand mainnet endpoint https://api.drand.sh/.
CHAIN defaults to the chainhash of the fastnet network:
dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493
You can also use the drand test network:
https://pl-us.testnet.drand.sh/
and its unchained network with chain hash 7672797f548f3f4748ac4bf3352fc6c6b6468c9ad40ad456a397545c6e2df5bf
Note that if you encrypted something prior to March 2023, this was the only available network and used to be the default.
DURATION, when specified, expects a number followed by one of these units:
"ns", "us" (or "µs"), "ms", "s", "m", "h", "d", "M", "y".
Example:
$ tle -D 10d -o encrypted_file data_to_encrypt
After the specified duration:
$ tle -d -o dencrypted_file.txt encrypted_file`
// PrintUsage displays the usage information.
func PrintUsage(log *log.Logger) {
log.Println(usage)
}
// =============================================================================
// Flags represent the values from the command line.
type Flags struct {
Encrypt bool
Decrypt bool
Force bool
Network string
Chain string
Round uint64
Time string
Duration string
Output string
RawInput string
Armor bool
}
// Parse will parse the environment variables and command line flags. The command
// line flags will overwrite environment variables. Validation takes place.
func Parse() (Flags, error) {
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }
f := Flags{
Network: defaultNetwork,
Chain: defaultChain,
}
err := envconfig.Process("tle", &f)
if err != nil {
return f, err
}
parseCmdline(&f)
if err := validateFlags(&f); err != nil {
return Flags{}, err
}
return f, nil
}
// parseCmdline will parse all the command line flags.
// The default value is set to the values parsed by the environment variables.
func parseCmdline(f *Flags) {
flag.BoolVar(&f.Encrypt, "e", f.Encrypt, "encrypt the input to the output")
flag.BoolVar(&f.Encrypt, "encrypt", f.Encrypt, "encrypt the input to the output")
flag.BoolVar(&f.Decrypt, "d", f.Decrypt, "decrypt the input to the output")
flag.BoolVar(&f.Decrypt, "decrypt", f.Decrypt, "decrypt the input to the output")
flag.BoolVar(&f.Force, "f", f.Force, "Forces to encrypt against past rounds")
flag.BoolVar(&f.Force, "force", f.Force, "Forces to encrypt against past rounds.")
flag.StringVar(&f.Network, "n", f.Network, "the drand API endpoint")
flag.StringVar(&f.Network, "network", f.Network, "the drand API endpoint")
flag.StringVar(&f.Chain, "c", f.Chain, "chain to use")
flag.StringVar(&f.Chain, "chain", f.Chain, "chain to use")
flag.Uint64Var(&f.Round, "r", f.Round, "the specific round to use; cannot be used with --duration")
flag.Uint64Var(&f.Round, "round", f.Round, "the specific round to use; cannot be used with --duration")
flag.StringVar(&f.Duration, "D", f.Duration, "how long to wait before being able to decrypt")
flag.StringVar(&f.Duration, "duration", f.Duration, "how long to wait before being able to decrypt")
flag.StringVar(&f.Time, "T", f.Time, "a UTC time value in RFC3339 format")
flag.StringVar(&f.Time, "time", f.Time, "a UTC time value in RFC3339 format")
flag.StringVar(&f.Output, "o", f.Output, "the path to the output file")
flag.StringVar(&f.Output, "output", f.Output, "the path to the output file")
flag.StringVar(&f.RawInput, "I", f.RawInput, "raw input to be encrypted")
flag.StringVar(&f.RawInput, "input", f.RawInput, "raw input to be encrypted")
flag.BoolVar(&f.Armor, "a", f.Armor, "encrypt to a PEM encoded format")
flag.BoolVar(&f.Armor, "armor", f.Armor, "encrypt to a PEM encoded format")
flag.Parse()
}
// validateFlags performs a sanity check of the provided flag information.
func validateFlags(f *Flags) error {
switch {
case f.Decrypt:
if f.Encrypt {
return fmt.Errorf("-e/--encrypt can't be used with -d/--decrypt")
}
if f.Duration != "" {
return fmt.Errorf("-D/--duration can't be used with -d/--decrypt")
}
if f.Time != "" {
return fmt.Errorf("-T/--time can't be used with -d/--decrypt")
}
if f.Round != 0 {
return fmt.Errorf("-r/--round can't be used with -d/--decrypt")
}
if f.Armor {
return fmt.Errorf("-a/--armor can't be used with -d/--decrypt")
}
if f.Network != defaultNetwork {
if f.Chain == defaultChain {
fmt.Fprintf(os.Stderr,
"You've specified a non-default network endpoint but still use the default chain hash.\n"+
"You might want to also specify a custom chainhash with the -c/--chain flag.\n\n")
}
}
default:
if f.Chain == "" {
return fmt.Errorf("-c/--chain can't be empty")
}
if f.Duration == "" && f.Round == 0 && f.Time == "" {
return fmt.Errorf("one of -D/--duration, -r/--round or -T/--time must be specified")
}
if f.Duration != "" && f.Round != 0 {
return fmt.Errorf("-D/--duration can't be used with -r/--round")
}
if f.Duration != "" && f.Time != "" {
return fmt.Errorf("-D/--duration can't be used with -T/--time")
}
if f.Time != "" && f.Round != 0 {
return fmt.Errorf("-T/--time can't be used with -r/--round")
}
if f.Time != "" {
duration, err := timestampToDuration(f.Time)
if err != nil {
return err
}
f.Duration = duration
}
}
return nil
}