From 466cbd5a1be7d274a45506add79c21e06ee53381 Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Fri, 24 Oct 2025 15:18:39 -0700 Subject: Use argon2 for password hashing --- dec.go | 6 +++--- enc.go | 6 +++--- go.mod | 1 + go.sum | 2 ++ oae.go | 18 +++++++++--------- pwhash.go | 9 ++++----- sym_test.go | 4 ++-- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/dec.go b/dec.go index aa551ad..ae9ec33 100644 --- a/dec.go +++ b/dec.go @@ -10,7 +10,7 @@ import ( ) func (o *decryptOptions) decrypt(w io.Writer, r io.Reader, password string) error { - _, err := io.Copy(w, newDecryptingReader(r, password, o.iterations)) + _, err := io.Copy(w, newDecryptingReader(r, password, o.memory)) return err } @@ -27,14 +27,14 @@ func (f *decryptFlags) registerFlags(fs *flag.FlagSet) { type decryptOptions struct { decryptFlags - iterations int + memory int passwordIn func() (string, error) stdin io.Reader stdout io.Writer } var defaultDecryptOptions = decryptOptions{ - iterations: defaultPBKDF2Iters, + memory: defaultArgon2Memory, passwordIn: termReadPassword, stdin: os.Stdin, stdout: os.Stdout, diff --git a/enc.go b/enc.go index 5990121..c24cba8 100644 --- a/enc.go +++ b/enc.go @@ -28,7 +28,7 @@ func (f *encryptFlags) registerFlags(fs *flag.FlagSet) { type encryptOptions struct { encryptFlags - iterations int + memory int passwordIn func() (string, error) passwordOut io.Writer stdin io.Reader @@ -36,7 +36,7 @@ type encryptOptions struct { } var defaultEncryptOptions = encryptOptions{ - iterations: defaultPBKDF2Iters, + memory: defaultArgon2Memory, passwordIn: termReadPassword, passwordOut: os.Stderr, stdin: os.Stdin, @@ -44,7 +44,7 @@ var defaultEncryptOptions = encryptOptions{ } func (o *encryptOptions) encrypt(w io.Writer, r io.Reader, password string) error { - writer := newEncryptingWriter(w, password, o.iterations) + writer := newEncryptingWriter(w, password, o.memory) if _, err := io.Copy(writer, r); err != nil { return err } diff --git a/go.mod b/go.mod index a1f7c9f..db929f6 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module roseh.moe/cmd/sym go 1.25.0 require ( + golang.org/x/crypto v0.43.0 golang.org/x/term v0.36.0 roseh.moe/pkg/wordlist v1.0.2 ) diff --git a/go.sum b/go.sum index 2b38e1d..56eda83 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= diff --git a/oae.go b/oae.go index 5b6140c..a4eb6c8 100644 --- a/oae.go +++ b/oae.go @@ -21,15 +21,15 @@ const ( ) type segmentEncrypter struct { - password string - iterations int + password string + memory int aead cipher.AEAD nonce [nonceSize]byte } func (se *segmentEncrypter) initialize(salt []byte) error { - key, err := hashPassword(se.password, salt, se.iterations) + key, err := hashPassword(se.password, salt, se.memory) if err != nil { return err } @@ -83,12 +83,12 @@ type encryptingWriter struct { initialized bool } -func newEncryptingWriter(w io.Writer, password string, iterations int) *encryptingWriter { +func newEncryptingWriter(w io.Writer, password string, memory int) *encryptingWriter { return &encryptingWriter{ w: w, encrypter: segmentEncrypter{ - password: password, - iterations: iterations, + password: password, + memory: memory, }, } } @@ -181,12 +181,12 @@ type decryptingReader struct { readFinalBlock bool } -func newDecryptingReader(r io.Reader, password string, iterations int) *decryptingReader { +func newDecryptingReader(r io.Reader, password string, memory int) *decryptingReader { return &decryptingReader{ r: bufio.NewReaderSize(r, 0), // we only need .UnreadByte decrypter: segmentEncrypter{ - password: password, - iterations: iterations, + password: password, + memory: memory, }, } } diff --git a/pwhash.go b/pwhash.go index 31f1487..dabafa7 100644 --- a/pwhash.go +++ b/pwhash.go @@ -1,17 +1,16 @@ package main import ( - "crypto/pbkdf2" - "crypto/sha256" "os" + "golang.org/x/crypto/argon2" "golang.org/x/term" ) -const defaultPBKDF2Iters = 35_000_000 +const defaultArgon2Memory = 64 * 1024 -func hashPassword(password string, salt []byte, iters int) ([]byte, error) { - return pbkdf2.Key(sha256.New, password, salt, iters, 32) +func hashPassword(password string, salt []byte, memory int) ([]byte, error) { + return argon2.IDKey([]byte(password), salt, 1, uint32(memory), 4, 32), nil } func termReadPassword() (string, error) { diff --git a/sym_test.go b/sym_test.go index 4d648d3..bb81ab8 100644 --- a/sym_test.go +++ b/sym_test.go @@ -9,13 +9,13 @@ import ( var testEncryptOptions = func() encryptOptions { opts := defaultEncryptOptions - opts.iterations = 10 + opts.memory = 1 return opts }() var testDecryptOptions = func() decryptOptions { opts := defaultDecryptOptions - opts.iterations = 10 + opts.memory = 1 return opts }() -- cgit v1.3.1