Initial commit
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
|
||||
package password
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHashAndVerifyRoundTrip(t *testing.T) {
|
||||
encoded, err := Hash("correct horse battery staple")
|
||||
if err != nil {
|
||||
t.Fatalf("Hash: %v", err)
|
||||
}
|
||||
if !strings.HasPrefix(encoded, "scrypt$16384$8$1$") {
|
||||
t.Fatalf("encoded = %q, want scrypt$16384$8$1$ prefix", encoded)
|
||||
}
|
||||
if !Verify("correct horse battery staple", encoded) {
|
||||
t.Fatal("Verify returned false for the correct password")
|
||||
}
|
||||
if Verify("wrong password", encoded) {
|
||||
t.Fatal("Verify returned true for a wrong password")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashRejectsEmpty(t *testing.T) {
|
||||
if _, err := Hash(""); err != ErrEmpty {
|
||||
t.Fatalf("err = %v, want ErrEmpty", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashRejectsTooLong(t *testing.T) {
|
||||
if _, err := Hash(strings.Repeat("x", MaxPasswordLength+1)); err == nil {
|
||||
t.Fatal("want error for over-long password")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyRejectsMalformed(t *testing.T) {
|
||||
for _, encoded := range []string{
|
||||
"",
|
||||
"not-a-hash",
|
||||
"bcrypt$16384$8$1$c2FsdA==$aGFzaA==",
|
||||
"scrypt$16384$8$c2FsdA==$aGFzaA==",
|
||||
"scrypt$abc$8$1$c2FsdA==$aGFzaA==",
|
||||
"scrypt$16384$8$1$!!!notb64==$aGFzaA==",
|
||||
} {
|
||||
if Verify("secret", encoded) {
|
||||
t.Fatalf("Verify(%q) = true, want false", encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyRejectsWeakParameters(t *testing.T) {
|
||||
// N=1024, r=8, p=1 with a well-formed 32-byte hash: below the floor.
|
||||
encoded := "scrypt$1024$8$1$c2FsdHNhbHRzYWx0c2E=$aGFzaGhhc2hoYXNoaGFzaGhhc2hoYXNoaGFzaA=="
|
||||
if Verify("secret", encoded) {
|
||||
t.Fatal("Verify accepted weak scrypt parameters")
|
||||
}
|
||||
if !NeedsRehash(encoded) {
|
||||
t.Fatal("NeedsRehash = false for weak parameters")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyRejectsExcessiveMemory(t *testing.T) {
|
||||
// N and r parse and clear the floor, but 128*N*r exceeds the bound.
|
||||
encoded := "scrypt$1048576$1024$1$c2FsdHNhbHRzYWx0c2E=$aGFzaGhhc2hoYXNoaGFzaGhhc2hoYXNoaGFzaA=="
|
||||
if Verify("secret", encoded) {
|
||||
t.Fatal("Verify accepted an excessive-memory hash")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeedsRehash(t *testing.T) {
|
||||
encoded, err := Hash("password123")
|
||||
if err != nil {
|
||||
t.Fatalf("Hash: %v", err)
|
||||
}
|
||||
if NeedsRehash(encoded) {
|
||||
t.Fatal("NeedsRehash = true for a current-policy hash")
|
||||
}
|
||||
if !NeedsRehash("garbage") {
|
||||
t.Fatal("NeedsRehash = false for garbage")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user