tChange program to generic encrypt/decrypt tool - 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 7c3738080e10f66d9b3892e6ce13cfe8c6fba4e0
(DIR) parent e42736b586fc5a5eef31959a7800af18e9e44b6b
(HTM) Author: Willy Goiffon <contact@z3bra.org>
Date: Wed, 14 Sep 2022 10:13:03 +0200
Change program to generic encrypt/decrypt tool
Diffstat:
M go.mod | 3 ++-
M go.sum | 6 ++++--
M safe.go | 92 +++++++++++++++++--------------
3 files changed, 56 insertions(+), 45 deletions(-)
---
(DIR) diff --git a/go.mod b/go.mod
t@@ -5,6 +5,7 @@ go 1.19
require (
github.com/netfoundry/secretstream v0.1.2
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
+ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
)
-require golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
+require golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
(DIR) diff --git a/go.sum b/go.sum
t@@ -7,6 +7,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
(DIR) diff --git a/safe.go b/safe.go
t@@ -1,21 +1,18 @@
package main
import (
+ "crypto/rand"
"flag"
"fmt"
"io"
"log"
"os"
+ "golang.org/x/term"
"golang.org/x/crypto/argon2"
"github.com/netfoundry/secretstream"
)
-type Safe struct {
- key []byte
- salt []byte
-}
-
const (
BUFSIZ = 8192
t@@ -25,55 +22,51 @@ const (
argon2id_threads = 1
argon2id_salt_len = 16
xchacha20poly1305_key_len = 32
- xchacha20poly1305_iv_len = 24
+ xchacha20poly1305_iv_len = 16
)
func usage() {
- fmt.Printf("usage: %s [-hr] [-s safe] [[-af] entry]\n", os.Args[0])
+ fmt.Printf("usage: %s [-hde] [-s salt] [-p password] [file]\n", os.Args[0])
os.Exit(2)
}
-func readsalt(secret string, safe *Safe) {
- f, err := os.Open(secret)
+func readsalt(file string, salt *[]byte) {
+ f, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer f.Close()
- safe.salt = make([]byte, argon2id_salt_len)
- s := io.NewSectionReader(f, 0, argon2id_salt_len)
-
- _, err = s.Read(safe.salt)
+ _, err = f.Read(*salt)
if err != nil {
log.Fatal(err)
}
}
-func deriv(pw []byte, s *Safe) {
- s.key = make([]byte, xchacha20poly1305_key_len)
- s.key = argon2.IDKey(pw, s.salt,
+func deriv(pw []byte, key *[]byte, salt []byte) {
+ *key = argon2.IDKey(pw, salt,
argon2id_time_cost,
argon2id_memory_cost,
argon2id_threads,
xchacha20poly1305_key_len)
}
-func encrypt(secret string, safe *Safe) {
+func encrypt(secret string, key []byte, salt []byte) {
var tag byte
buf := make([]byte, BUFSIZ)
- enc, nonce, err := secretstream.NewEncryptor(safe.key)
+ enc, nonce, err := secretstream.NewEncryptor(key)
if err != nil {
log.Fatal(err)
}
- f, err := os.OpenFile(secret, os.O_CREATE|os.O_WRONLY, 0600)
+ 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(safe.salt)
+ f.Write(salt)
if err != nil {
log.Fatal(err)
}
t@@ -105,7 +98,7 @@ func encrypt(secret string, safe *Safe) {
}
}
-func decrypt(secret string, safe *Safe) {
+func decrypt(secret string, key []byte) {
buf := make([]byte, BUFSIZ + secretstream.StreamABytes)
header := make([]byte, secretstream.StreamHeaderBytes)
t@@ -121,7 +114,7 @@ func decrypt(secret string, safe *Safe) {
log.Fatal(err)
}
- dec, err := secretstream.NewDecryptor(safe.key, header)
+ dec, err := secretstream.NewDecryptor(key, header)
if err != nil {
log.Fatal(err)
}
t@@ -146,15 +139,15 @@ func decrypt(secret string, safe *Safe) {
}
func main() {
- var safe Safe
-
- var store string
- var aflag, fflag, rflag bool
-
- flag.StringVar(&store, "s", ".secrets", "Set safe store location")
- flag.BoolVar(&aflag, "a", false, "Add a secret to the safe")
- flag.BoolVar(&fflag, "f", false, "Force writing secret (implies -a)")
- flag.BoolVar(&rflag, "r", false, "Save password in a running agent")
+ var err error
+ var key, salt, pass []byte
+ var saltfile, password string
+ var dflag, eflag bool
+
+ flag.StringVar(&saltfile, "s", "", "Read salt from file")
+ flag.StringVar(&password, "p", "", "Password to derivate key from")
+ flag.BoolVar(&eflag, "e", true, "encrypt input (default)")
+ flag.BoolVar(&dflag, "d", false, "decrypt input")
flag.Usage = usage
flag.Parse()
t@@ -163,23 +156,38 @@ func main() {
usage()
}
- err := os.Chdir(store)
+ 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, "")
+ } else {
+ pass = []byte(password)
}
- //fmt.Printf("password:")
- //password, _ := bufio.NewReader(os.Stdin).ReadString('\n')
-
- // read salt from master entry
- readsalt("master", &safe)
+ // read salt from the given file, ir 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 {
+ log.Fatal(err)
+ }
+ }
- deriv([]byte("azerty"), &safe)
+ key = make([]byte, xchacha20poly1305_key_len)
+ deriv(pass, &key, salt)
- if !aflag {
- decrypt(args[0], &safe)
+ if dflag {
+ decrypt(args[0], key)
} else {
- encrypt(args[0], &safe)
+ encrypt(args[0], key, salt)
}
}