Personal Git forge.
package libimport ( "errors" "regexp" "strconv" "strings" "testing" "unicode/utf8" "golang.org/x/crypto/argon2")var tokenRegex = regexp.MustCompile("^[a-zA-Z0-9]+$")func TestGenerateToken(t *testing.T) { for i := range 20 { i++ token := AlphanumericToken(uint(i)) if utf8.RuneCountInString(token) != i { t.Errorf(`GenerateToken("%v") FAILED. Mismatched lengths.`, i) } if !tokenRegex.Match([]byte(token)) { t.Errorf(`GenerateToken("%v") FAILED. Not alphanumerical. Returned: %s`, i, token) } }}func TestGenerateSalt(t *testing.T) { salt, err := GenerateSalt(16) if err != nil { t.Fatalf("GenerateSalt(16): %v", err) } if len(salt) != 16 { t.Errorf("GenerateSalt(16) returned %d bytes, want 16", len(salt)) } salt2, err := GenerateSalt(16) if err != nil { t.Fatalf("GenerateSalt(16) #2: %v", err) } if string(salt) == string(salt2) { t.Error("GenerateSalt returned the same salt twice") }}func TestGenerateHashValidateHash(t *testing.T) { hash, err := GenerateHash("hunter2") if err != nil { t.Fatalf("GenerateHash: %v", err) } if !strings.HasPrefix(hash, "$argon2id$v=") { t.Errorf("hash %q does not start with $argon2id$v=", hash) } match, err := ValidateHash("hunter2", hash) if err != nil { t.Fatalf("ValidateHash(correct): %v", err) } if !match { t.Error("ValidateHash(correct password) = false, want true") } match, err = ValidateHash("wrong", hash) if err != nil { t.Fatalf("ValidateHash(wrong): %v", err) } if match { t.Error("ValidateHash(wrong password) = true, want false") }}func TestDecodeHash(t *testing.T) { if _, _, _, err := DecodeHash("not a hash"); !errors.Is(err, ErrInvalidHash) { t.Errorf("DecodeHash(garbage) = %v, want ErrInvalidHash", err) } // a valid-looking hash but for an argon2 version we don't know wrongVersion := "$argon2id$v=99$m=65536,t=4,p=4$c2FsdHNhbHRzYWx0c2FsdA$c2FsdHNhbHRzYWx0c2FsdHNhbHRzYWx0c2FsdA" if _, _, _, err := DecodeHash(wrongVersion); !errors.Is(err, ErrIncompatibleVersion) { t.Errorf("DecodeHash(wrong version) = %v, want ErrIncompatibleVersion", err) } // a valid version but undecodable base64 salt badBase64 := "$argon2id$v=" + strconv.Itoa(argon2.Version) + "$m=65536,t=4,p=4$@@@$c2FsdA" if _, _, _, err := DecodeHash(badBase64); err == nil { t.Error("DecodeHash(bad base64) = nil error, want error") } // roundtrip through DecodeHash hash, err := GenerateHash("pw") if err != nil { t.Fatalf("GenerateHash: %v", err) } p, salt, decoded, err := DecodeHash(hash) if err != nil { t.Fatalf("DecodeHash(own hash): %v", err) } if len(salt) == 0 || len(decoded) == 0 { t.Error("DecodeHash returned empty salt or hash") } if p.hash_len != uint32(len(decoded)) { t.Errorf("p.hash_len = %d, want %d", p.hash_len, len(decoded)) }}