82 lines
2.5 KiB
Go
82 lines
2.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Known-answer test for the hand-rolled PBKDF2-HMAC-SHA256 core, so a typo
|
|
// in the loop (block index, XOR fold, etc.) fails loudly instead of just
|
|
// producing a hash that happens to round-trip against itself.
|
|
func TestPBKDF2Vector(t *testing.T) {
|
|
got := pbkdf2("password", []byte("salt"), 1, 32)
|
|
want, _ := hex.DecodeString("120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b")
|
|
if hex.EncodeToString(got) != hex.EncodeToString(want) {
|
|
t.Fatalf("pbkdf2(password,salt,1,32) = %x, want %x", got, want)
|
|
}
|
|
}
|
|
|
|
func TestHashAndVerifyPassword(t *testing.T) {
|
|
hash, err := HashPassword("correct horse battery staple")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !VerifyPassword("correct horse battery staple", hash) {
|
|
t.Fatal("VerifyPassword rejected the correct password")
|
|
}
|
|
if VerifyPassword("wrong password", hash) {
|
|
t.Fatal("VerifyPassword accepted the wrong password")
|
|
}
|
|
}
|
|
|
|
// RFC 4226 Appendix D HOTP test vectors (secret "12345678901234567890",
|
|
// 6-digit truncation) — TOTP is just HOTP with counter = unixtime/step, so
|
|
// this pins down the shared HMAC/truncation core.
|
|
func TestHOTPVectors(t *testing.T) {
|
|
secret := []byte("12345678901234567890")
|
|
want := []string{
|
|
"755224", "287082", "359152", "969429", "338314",
|
|
"254676", "287922", "162583", "399871", "520489",
|
|
}
|
|
for counter, code := range want {
|
|
got := hotp(secret, uint64(counter), 6)
|
|
if got != code {
|
|
t.Fatalf("hotp(counter=%d) = %s, want %s", counter, got, code)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateTOTPRoundtrip(t *testing.T) {
|
|
secret, err := NewTOTPSecret()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
code, err := totpAt(secret, time.Now())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !ValidateTOTP(secret, code) {
|
|
t.Fatal("ValidateTOTP rejected a freshly generated code")
|
|
}
|
|
if ValidateTOTP(secret, "000000") {
|
|
t.Fatal("ValidateTOTP accepted an arbitrary wrong code")
|
|
}
|
|
}
|
|
|
|
func TestSessionTokenRoundtrip(t *testing.T) {
|
|
key := []byte("0123456789abcdef0123456789abcdef")
|
|
tok := NewSessionToken(key, "admin", 3, time.Hour)
|
|
user, version, ok := ParseSessionToken(key, tok)
|
|
if !ok || user != "admin" || version != 3 {
|
|
t.Fatalf("roundtrip failed: user=%q version=%d ok=%v", user, version, ok)
|
|
}
|
|
if _, _, ok := ParseSessionToken(key, tok+"tampered"); ok {
|
|
t.Fatal("ParseSessionToken accepted a tampered token")
|
|
}
|
|
otherKey := []byte("ffffffffffffffffffffffffffffffff")
|
|
if _, _, ok := ParseSessionToken(otherKey, tok); ok {
|
|
t.Fatal("ParseSessionToken accepted a token signed with a different key")
|
|
}
|
|
}
|