From 6f3c43aca62a7d33a19f14f6ad7c16891952673a Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 15 Sep 2026 19:55:21 -0400 Subject: fix: outstanding-stake ledger, owner backpressure, editor state preservation --- internal/player/password_test.go | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 internal/player/password_test.go (limited to 'internal/player/password_test.go') diff --git a/internal/player/password_test.go b/internal/player/password_test.go new file mode 100644 index 0000000..82b580b --- /dev/null +++ b/internal/player/password_test.go @@ -0,0 +1,60 @@ +package player + +import ( + "crypto/sha256" + "encoding/base64" + "fmt" + "strings" + "testing" +) + +func TestHashPasswordUsesArgon2idAndVerifies(t *testing.T) { + hash, err := HashPassword("secret password") + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(hash, "argon2id:") { + t.Fatalf("hash format = %q, want argon2id", hash) + } + if !CheckPassword("secret password", hash) { + t.Fatal("correct password rejected") + } + if CheckPassword("wrong password", hash) { + t.Fatal("wrong password accepted") + } + // Salts must be unique per call: two hashes of the same password differ. + other, _ := HashPassword("secret password") + if other == hash { + t.Fatal("two hashes of the same password are identical (salt reuse)") + } +} + +func TestCheckPasswordVerifiesLegacySHA256(t *testing.T) { + salt := make([]byte, 16) + for i := range salt { + salt[i] = byte(i) + } + sum := sha256.Sum256(append(salt, []byte("legacy pw")...)) + legacy := fmt.Sprintf("sha256:%s:%x", base64.RawStdEncoding.EncodeToString(salt), sum) + + if !CheckPassword("legacy pw", legacy) { + t.Fatal("correct legacy password rejected") + } + if CheckPassword("wrong", legacy) { + t.Fatal("wrong legacy password accepted") + } + if !NeedsRehash(legacy) { + t.Fatal("legacy hash not flagged for rehash") + } + if NeedsRehash("argon2id:1:65536:2:c2FsdA:x") { + t.Fatal("argon2id hash flagged for rehash") + } +} + +func TestCheckPasswordRejectsGarbage(t *testing.T) { + for _, stored := range []string{"", "plain", "argon2id:1:2:3:no-salt:zz", "unknown:v1:salt:deadbeef"} { + if CheckPassword("anything", stored) { + t.Fatalf("garbage hash accepted: %q", stored) + } + } +} -- cgit v1.2.3