summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-11-21 18:44:58 -0800
committerRose Hogenson <rosehogenson@posteo.net>2025-11-21 18:44:58 -0800
commit0d640e791493de79b43b050a13b1cf9c081854ec (patch)
treee545cc0db40612260c8a1995d38f6bb600a87c2f
parent4be64dd369b4bbdf3c4c0972c949c6e150377699 (diff)
downloadroseh.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.nix2
-rw-r--r--go.mod3
-rw-r--r--go.sum4
-rw-r--r--internal/pwhash/pwhash.go18
-rw-r--r--roseh.moe.go11
-rw-r--r--tools/finditer/finditer.go43
-rw-r--r--tools/hashpw/hashpw.go46
7 files changed, 7 insertions, 120 deletions
diff --git a/flake.nix b/flake.nix
index 6fa885a..5e3a2ce 100644
--- a/flake.nix
+++ b/flake.nix
@@ -48,7 +48,7 @@
# remember to bump this hash when your dependencies change.
# vendorHash = pkgs.lib.fakeHash;
- vendorHash = "sha256-/Ciog57YcusaM8PvTRnBgxKcbNgxot4R8PhImu5m3Us=";
+ vendorHash = "sha256-Rrtcdtprg0y3oNtCbxvF4QVIGFbx+je6BcQGymsxpIA=";
};
});
diff --git a/go.mod b/go.mod
index c67fe11..ad0556c 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
index 7fd2131..8e8e2b8 100644
--- a/go.sum
+++ b/go.sum
@@ -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)
- }
-}