tDefault to read/write on stdin/out - safe-go - Unnamed repository; edit this file 'description' to name the repository.
(HTM) git clone git://git.z3bra.org/safe-go.git
(DIR) Log
(DIR) Files
(DIR) Refs
---
(DIR) commit 04337385eebc7b17f97ea326e219bbe2365a3a9f
(DIR) parent 7c3738080e10f66d9b3892e6ce13cfe8c6fba4e0
(HTM) Author: Willy Goiffon <contact@z3bra.org>
Date: Wed, 14 Sep 2022 15:40:00 +0200
Default to read/write on stdin/out
Diffstat:
M safe.go | 102 +++++++++++++++++--------------
1 file changed, 57 insertions(+), 45 deletions(-)
---
(DIR) diff --git a/safe.go b/safe.go
t@@ -8,9 +8,9 @@ import (
"log"
"os"
- "golang.org/x/term"
- "golang.org/x/crypto/argon2"
"github.com/netfoundry/secretstream"
+ "golang.org/x/crypto/argon2"
+ "golang.org/x/term"
)
const (
t@@ -26,7 +26,7 @@ const (
)
func usage() {
- fmt.Printf("usage: %s [-hde] [-s salt] [-p password] [file]\n", os.Args[0])
+ fmt.Printf("usage: %s [-hde] [-s salt] [-f file]\n", os.Args[0])
os.Exit(2)
}
t@@ -51,27 +51,21 @@ func deriv(pw []byte, key *[]byte, salt []byte) {
xchacha20poly1305_key_len)
}
-func encrypt(secret string, key []byte, salt []byte) {
+func encrypt(in *os.File, out *os.File, key []byte, salt []byte) {
var tag byte
- buf := make([]byte, BUFSIZ)
+ buf := make([]byte, BUFSIZ)
enc, nonce, err := secretstream.NewEncryptor(key)
if err != nil {
log.Fatal(err)
}
- f, err := os.OpenFile(secret, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
- if err != nil {
- log.Fatal(err)
- }
- defer f.Close()
-
- f.Write(salt)
+ out.Write(salt)
if err != nil {
log.Fatal(err)
}
- f.Write(nonce)
+ out.Write(nonce)
if err != nil {
log.Fatal(err)
}
t@@ -79,7 +73,7 @@ func encrypt(secret string, key []byte, salt []byte) {
loop := 1
tag = secretstream.TagMessage
for loop > 0 {
- n, err := os.Stdin.Read(buf)
+ n, err := in.Read(buf)
if err == io.EOF || n < len(buf) {
tag = secretstream.TagFinal
loop = 0
t@@ -91,28 +85,25 @@ func encrypt(secret string, key []byte, salt []byte) {
log.Fatal(err)
}
- f.Write(cipher)
+ out.Write(cipher)
if err != nil {
log.Fatal(err)
}
}
}
-func decrypt(secret string, key []byte) {
- buf := make([]byte, BUFSIZ + secretstream.StreamABytes)
+func decrypt(in *os.File, out *os.File, key []byte) {
+ buf := make([]byte, BUFSIZ+secretstream.StreamABytes)
header := make([]byte, secretstream.StreamHeaderBytes)
- f, err := os.Open(secret)
- if err != nil {
- log.Fatal(err)
- }
- defer f.Close()
-
- f.Seek(argon2id_salt_len, os.SEEK_SET)
- _, err = f.Read(header)
- if err != nil {
- log.Fatal(err)
- }
+ /*
+ // Skip beginning of file which (supposedly) contains the salt for the key
+ in.Seek(argon2id_salt_len, os.SEEK_SET)
+ _, err := in.Read(header)
+ if err != nil {
+ log.Fatal(err)
+ }
+ */
dec, err := secretstream.NewDecryptor(key, header)
if err != nil {
t@@ -121,7 +112,7 @@ func decrypt(secret string, key []byte) {
loop := 1
for loop > 0 {
- n, err := f.Read(buf)
+ n, err := in.Read(buf)
if err != nil && err != io.EOF {
log.Fatal(err)
}
t@@ -134,47 +125,53 @@ func decrypt(secret string, key []byte) {
if tag == secretstream.TagFinal {
loop = 0
}
- os.Stdout.Write(plain)
+ out.Write(plain)
}
}
func main() {
var err error
var key, salt, pass []byte
- var saltfile, password string
+ var filename, saltfile, password string
var dflag, eflag bool
+ in := os.Stdin
+ out := os.Stdout
+
flag.StringVar(&saltfile, "s", "", "Read salt from file")
flag.StringVar(&password, "p", "", "Password to derivate key from")
+ flag.StringVar(&filename, "f", "", "Encrypt/decrypt to/from file name")
flag.BoolVar(&eflag, "e", true, "encrypt input (default)")
flag.BoolVar(&dflag, "d", false, "decrypt input")
flag.Usage = usage
flag.Parse()
+ if eflag && dflag {
+ log.Fatal("encrypt and decrypt flags are mutually exclusive")
+ }
+
args := flag.Args()
- if len(args) < 1 {
+ if len(args) > 0 {
usage()
}
if len(password) == 0 {
- tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0644)
- if err != nil {
- log.Fatal(err)
- }
- defer tty.Close()
- fmt.Fprint(tty, "password:")
- pass, _ = term.ReadPassword(int(tty.Fd()))
- fmt.Fprintln(tty, "")
+ tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0644)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer tty.Close()
+ fmt.Fprint(tty, "password:")
+ pass, _ = term.ReadPassword(int(tty.Fd()))
+ fmt.Fprintln(tty, "")
} else {
pass = []byte(password)
}
- // read salt from the given file, ir generate a ramdom one
+ // read salt from the given file, or generate a ramdom one
salt = make([]byte, argon2id_salt_len)
if len(saltfile) > 0 {
readsalt(saltfile, &salt)
- } else if dflag {
- readsalt(args[0], &salt)
} else {
_, err = rand.Read(salt)
if err != nil {
t@@ -186,8 +183,23 @@ func main() {
deriv(pass, &key, salt)
if dflag {
- decrypt(args[0], key)
+ if len(filename) > 0 {
+ in, err = os.Open(filename)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer in.Close()
+ }
+
+ decrypt(in, out, key)
} else {
- encrypt(args[0], key, salt)
+ if len(filename) > 0 {
+ out, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer out.Close()
+ }
+ encrypt(in, out, key, salt)
}
}