diff options
Diffstat (limited to 'internal/player/password_test.go')
| -rw-r--r-- | internal/player/password_test.go | 60 |
1 files changed, 60 insertions, 0 deletions
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) + } + } +} |
