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)
                }
        }