2026-07-26 15:18:48 +08:00
|
|
|
package password
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestBcryptHashesAndVerifiesWithoutStoringPlaintext(t *testing.T) {
|
|
|
|
|
manager, err := NewBcrypt(bcrypt.MinCost)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("NewBcrypt() error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
encoded, err := manager.Hash("correct horse battery staple")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("Hash() error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
if encoded == "correct horse battery staple" {
|
|
|
|
|
t.Fatal("Hash() returned plaintext")
|
|
|
|
|
}
|
|
|
|
|
if err := manager.Verify(encoded, "correct horse battery staple"); err != nil {
|
|
|
|
|
t.Fatalf("Verify(correct) error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
if err := manager.Verify(encoded, "wrong"); !errors.Is(
|
|
|
|
|
err,
|
|
|
|
|
ErrPasswordMismatch,
|
|
|
|
|
) {
|
|
|
|
|
t.Fatalf("Verify(wrong) error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestBcryptRejectsInvalidCostAndOversizedPasswords(t *testing.T) {
|
|
|
|
|
if _, err := NewBcrypt(bcrypt.MinCost - 1); err == nil {
|
|
|
|
|
t.Fatal("NewBcrypt(invalid) error = nil")
|
|
|
|
|
}
|
|
|
|
|
manager, err := NewBcrypt(bcrypt.MinCost)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatalf("NewBcrypt() error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
oversized := strings.Repeat("x", 73)
|
2026-07-29 08:43:35 +08:00
|
|
|
if _, err := manager.Hash("tiny"); !errors.Is(
|
2026-07-26 15:18:48 +08:00
|
|
|
err,
|
|
|
|
|
ErrInvalidPassword,
|
|
|
|
|
) {
|
|
|
|
|
t.Fatalf("Hash(short) error = %v", err)
|
|
|
|
|
}
|
2026-07-29 08:43:35 +08:00
|
|
|
if _, err := manager.Hash("admin"); err != nil {
|
|
|
|
|
t.Fatalf("Hash(five-byte password) error = %v", err)
|
2026-07-27 15:02:44 +08:00
|
|
|
}
|
2026-07-26 15:18:48 +08:00
|
|
|
if _, err := manager.Hash(oversized); !errors.Is(
|
|
|
|
|
err,
|
|
|
|
|
ErrInvalidPassword,
|
|
|
|
|
) {
|
|
|
|
|
t.Fatalf("Hash(oversized) error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
if _, err := manager.Hash(
|
|
|
|
|
string([]byte{0xff, 0xfe, 0xfd}),
|
|
|
|
|
); !errors.Is(err, ErrInvalidPassword) {
|
|
|
|
|
t.Fatalf("Hash(invalid UTF-8) error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
if err := manager.Verify("$2a$04$invalid", oversized); !errors.Is(
|
|
|
|
|
err,
|
|
|
|
|
ErrPasswordMismatch,
|
|
|
|
|
) {
|
|
|
|
|
t.Fatalf("Verify(oversized) error = %v", err)
|
|
|
|
|
}
|
|
|
|
|
manager.VerifyDummy("password-123")
|
|
|
|
|
}
|