package auth import ( "encoding/base64" "strings" "testing" ) func TestHashPassword_Check(t *testing.T) { t.Parallel() encoded, err := HashPassword("s3cret") if err != nil { t.Fatalf("HashPassword error: %v", err) } if !strings.HasPrefix(encoded, passwordScheme+"$") { t.Errorf("encoded = %q, want %q prefix", encoded, passwordScheme+"$") } if !CheckPassword("s3cret", encoded) { t.Error("CheckPassword(correct) = false, want true") } if CheckPassword("wrong", encoded) { t.Error("CheckPassword(wrong) = true, want false") } } func TestHashPassword_SaltRandomizes(t *testing.T) { t.Parallel() a, err := HashPassword("s3cret") if err != nil { t.Fatalf("HashPassword error: %v", err) } b, err := HashPassword("s3cret") if err != nil { t.Fatalf("HashPassword error: %v", err) } if a == b { t.Error("equal passwords produced identical encodings; salt not random") } } func TestCheckPassword_Malformed(t *testing.T) { t.Parallel() salt := base64.RawStdEncoding.EncodeToString([]byte("saltsaltsaltsalts")) digest := base64.RawStdEncoding.EncodeToString([]byte("digestdigestdigestdigest")) cases := []struct { name string enc string }{ {"empty", ""}, {"too few parts", "sha256$onlyone"}, {"wrong scheme", "md5$" + salt + "$" + digest}, {"bad base64 salt", "sha256$!!$" + digest}, {"bad base64 digest", "sha256$" + salt + "$!!"}, } for _, tc := range cases { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() if CheckPassword("s3cret", tc.enc) { t.Errorf("CheckPassword(%q) = true, want false", tc.enc) } }) } }