diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2025-11-21 18:44:58 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2025-11-21 18:44:58 -0800 |
| commit | 0d640e791493de79b43b050a13b1cf9c081854ec (patch) | |
| tree | e545cc0db40612260c8a1995d38f6bb600a87c2f | |
| parent | 4be64dd369b4bbdf3c4c0972c949c6e150377699 (diff) | |
| download | roseh.moe-0d640e791493de79b43b050a13b1cf9c081854ec.tar.zst | |
Simplify the password hash and get rid of pbkdf2
Since the password already has 16 bytes of security, pbkdf2 isn't
necessary here. We can use a simple sha256. I promise to pick a
secure password.
| -rw-r--r-- | flake.nix | 2 | ||||
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | internal/pwhash/pwhash.go | 18 | ||||
| -rw-r--r-- | roseh.moe.go | 11 | ||||
| -rw-r--r-- | tools/finditer/finditer.go | 43 | ||||
| -rw-r--r-- | tools/hashpw/hashpw.go | 46 |
7 files changed, 7 insertions, 120 deletions
@@ -48,7 +48,7 @@ # remember to bump this hash when your dependencies change. # vendorHash = pkgs.lib.fakeHash; - vendorHash = "sha256-/Ciog57YcusaM8PvTRnBgxKcbNgxot4R8PhImu5m3Us="; + vendorHash = "sha256-Rrtcdtprg0y3oNtCbxvF4QVIGFbx+je6BcQGymsxpIA="; }; }); @@ -4,9 +4,6 @@ go 1.24.0 require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e - golang.org/x/term v0.36.0 roseh.moe/pkg/ccl v0.1.1 roseh.moe/pkg/wordlist v1.0.2 ) - -require golang.org/x/sys v0.37.0 // indirect @@ -2,10 +2,6 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= roseh.moe/pkg/ccl v0.1.1 h1:WSrG+AqOlUymdbeCD4D22zEvQ8fJLNU4SLQW6WtvL0Y= roseh.moe/pkg/ccl v0.1.1/go.mod h1:OCcZ30pQDtjXgqgpN8eLo6f/pTi6XVKIHPs1k+gups0= roseh.moe/pkg/wordlist v1.0.2 h1:riB2RqCU5zXfCQjaPHYTXV/688FV9/Bp6Hnb0IAkP9c= diff --git a/internal/pwhash/pwhash.go b/internal/pwhash/pwhash.go deleted file mode 100644 index 576d052..0000000 --- a/internal/pwhash/pwhash.go +++ /dev/null @@ -1,18 +0,0 @@ -package pwhash - -import ( - "crypto/pbkdf2" - "crypto/sha512" -) - -const SaltSize = 8 - -const defaultIter = 12059332 // from tools/finditer - -func HashIter(password string, salt []byte, iter int) ([]byte, error) { - return pbkdf2.Key(sha512.New, password, salt, iter, 32) -} - -func Hash(password string, salt []byte) ([]byte, error) { - return HashIter(password, salt, defaultIter) -} diff --git a/roseh.moe.go b/roseh.moe.go index 64d5e83..ffca9d5 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -25,7 +25,6 @@ import ( "github.com/skip2/go-qrcode" "roseh.moe/pkg/ccl" - "roseh.moe/pkg/roseh.moe/internal/pwhash" "roseh.moe/pkg/wordlist" ) @@ -40,6 +39,8 @@ var ( serverStartTime = time.Now() ) +const targetSecurityLevel = 16 + var notepadPassword, secretKey []byte func loadSecrets() error { @@ -322,7 +323,7 @@ func wormholeQR(w http.ResponseWriter, r *http.Request) { w.Write(qr) } -const macSize = 16 // sorry +const macSize = targetSecurityLevel func mac(msg []byte) []byte { mac := hmac.New(sha256.New, secretKey) @@ -473,9 +474,9 @@ func checkCSRFToken(r *http.Request) error { } func checkPassword(password string) bool { - expectedHash, salt := notepadPassword[:len(notepadPassword)-pwhash.SaltSize], notepadPassword[len(notepadPassword)-pwhash.SaltSize:] - hash, err := pwhash.Hash(password, salt) - return err == nil && subtle.ConstantTimeCompare(hash, expectedHash) != 0 + const pwHashSize = targetSecurityLevel + hash := sha256.Sum256([]byte(password)) + return subtle.ConstantTimeCompare(hash[:pwHashSize], notepadPassword) != 0 } var ( diff --git a/tools/finditer/finditer.go b/tools/finditer/finditer.go deleted file mode 100644 index 114785d..0000000 --- a/tools/finditer/finditer.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "encoding/hex" - "fmt" - "sort" - "testing" - "time" - - "roseh.moe/pkg/roseh.moe/internal/pwhash" -) - -func mustHex(s string) []byte { - b, err := hex.DecodeString(s) - if err != nil { - panic(err) - } - return b -} - -const password = "emcee polio cardiac disclose superglue clapper cruelness stonework tingly unarmored" - -var salt = mustHex("a0aa6971f38827e5") - -var iterations int - -func BenchmarkHashIter(b *testing.B) { - for b.Loop() { - pwhash.HashIter(password, salt, iterations) - } -} - -func main() { - const targetDuration = 5 * time.Second - for iterations = 8192; time.Duration(testing.Benchmark(BenchmarkHashIter).NsPerOp()) < targetDuration; iterations *= 2 { - } - lo := iterations / 2 - hi := iterations - fmt.Println(lo + sort.Search(hi-lo, func(i int) bool { - iterations = lo + i - return time.Duration(testing.Benchmark(BenchmarkHashIter).NsPerOp()) > targetDuration - })) -} diff --git a/tools/hashpw/hashpw.go b/tools/hashpw/hashpw.go deleted file mode 100644 index f1e76db..0000000 --- a/tools/hashpw/hashpw.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "bytes" - "crypto/rand" - "encoding/base64" - "fmt" - "os" - "slices" - - "golang.org/x/term" - "roseh.moe/pkg/roseh.moe/internal/pwhash" -) - -func hashpw() error { - fmt.Fprint(os.Stderr, "Enter password: ") - password, err := term.ReadPassword(int(os.Stdin.Fd())) - fmt.Fprintln(os.Stderr) - if err != nil { - return err - } - fmt.Fprint(os.Stderr, "Confirm password: ") - pwConfirm, err := term.ReadPassword(int(os.Stdin.Fd())) - fmt.Fprintln(os.Stderr) - if err != nil { - return err - } - if !bytes.Equal(password, pwConfirm) { - return fmt.Errorf("passwords do not match") - } - salt := make([]byte, pwhash.SaltSize) - rand.Read(salt) - hash, err := pwhash.Hash(string(password), salt) - if err != nil { - return err - } - fmt.Printf("NotepadPassword:%q\n", base64.StdEncoding.EncodeToString(slices.Concat(hash, salt))) - return nil -} - -func main() { - if err := hashpw(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} |
