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
|
package main
import (
"errors"
"flag"
"fmt"
"io"
"os"
"strings"
)
func (o *decryptOptions) decrypt(w io.Writer, r io.Reader, password string) error {
_, err := io.Copy(w, newDecryptingReader(r, password))
return err
}
type decryptFlags struct {
password string
force bool
}
func (f *decryptFlags) registerFlags(fs *flag.FlagSet) {
fs.StringVar(&f.password, "p", "", "use the specified password; if not provided, dec will prompt for a password")
fs.BoolVar(&f.force, "f", false, "overwrite output files even if they already exist")
}
type decryptOptions struct {
decryptFlags
passwordIn func() (string, error)
stdin io.Reader
stdout io.Writer
}
func (o *decryptOptions) decryptFile(fileName string, password string) (err error) {
var outFileName string
if name, ok := strings.CutSuffix(fileName, ".enc"); ok {
outFileName = name
} else {
outFileName = fileName + ".dec"
}
fIn, err := os.Open(fileName)
if err != nil {
return err
}
defer fIn.Close()
fileOpts := os.O_CREATE | os.O_WRONLY
if o.force {
fileOpts |= os.O_TRUNC
} else {
fileOpts |= os.O_EXCL
}
fOut, err := os.OpenFile(outFileName, fileOpts, 0644)
if err != nil {
if errors.Is(err, os.ErrExist) {
return fmt.Errorf("output file %q exists (use -f to overwrite)", outFileName)
}
return err
}
defer func() {
fOut.Close()
if err != nil {
os.Remove(fOut.Name())
}
}()
if err := o.decrypt(fOut, fIn, password); err != nil {
return fmt.Errorf("decrypt %q: %s", fileName, err)
}
return fOut.Close()
}
func (o *decryptOptions) readPassword() (string, error) {
fmt.Fprint(os.Stderr, "Enter password: ")
pw, err := o.passwordIn()
fmt.Fprintln(os.Stderr)
return pw, err
}
func (o *decryptOptions) run(args ...string) error {
if len(args) == 0 && o.password == "" {
return fmt.Errorf("-p is required when reading from stdin")
}
var password string
if o.password != "" {
password = o.password
} else {
var err error
password, err = o.readPassword()
if err != nil {
return err
}
}
if len(args) == 0 {
return o.decrypt(o.stdout, o.stdin, password)
}
for _, fileName := range args {
if err := o.decryptFile(fileName, password); err != nil {
return err
}
}
return nil
}
|