summaryrefslogtreecommitdiffstats
path: root/internal/pwhash
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-10-05 21:58:44 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-10-05 21:58:44 -0700
commitbcbb629db87b6bc0e9a7880ec4ee1c90d284a6c7 (patch)
tree7372c59802fb589f798a9e849d621dac158dc04b /internal/pwhash
parent83d80b0672be886e7c6ccfad60949dbddb1b4173 (diff)
downloadroseh.moe-bcbb629db87b6bc0e9a7880ec4ee1c90d284a6c7.tar.zst
Bring back the notepad
Diffstat (limited to 'internal/pwhash')
-rw-r--r--internal/pwhash/pwhash.go44
1 files changed, 44 insertions, 0 deletions
diff --git a/internal/pwhash/pwhash.go b/internal/pwhash/pwhash.go
new file mode 100644
index 0000000..c3c11ff
--- /dev/null
+++ b/internal/pwhash/pwhash.go
@@ -0,0 +1,44 @@
+package pwhash
+
+import (
+ "crypto/pbkdf2"
+ "crypto/rand"
+ "crypto/sha512"
+ "crypto/subtle"
+ "errors"
+)
+
+const defaultIter = 12504615 // from tools/finditers
+
+func HashIter(pw string, salt []byte, iter int) ([]byte, error) {
+ return pbkdf2.Key(sha512.New, pw, salt, iter, 32)
+}
+
+func Hash(pw string) ([]byte, error) {
+ buf := make([]byte, 40)
+ salt := buf[32:]
+ rand.Read(salt)
+ hash, err := HashIter(pw, salt, defaultIter)
+ if err != nil {
+ return nil, err
+ }
+ copy(buf, hash)
+ return buf, nil
+}
+
+var errBadPassword = errors.New("bad password")
+
+func Check(pwHash []byte, pw string) error {
+ if len(pwHash) < 32 {
+ return errBadPassword
+ }
+ wantHash, salt := pwHash[:32], pwHash[32:]
+ gotHash, err := HashIter(pw, salt, defaultIter)
+ if err != nil {
+ return err
+ }
+ if subtle.ConstantTimeCompare(gotHash, wantHash) == 0 {
+ return errBadPassword
+ }
+ return nil
+}