func Validate(hashed, plain string) (bool, error) {
	parts := strings.SplitN(hashed, "$", 2)
	if len(parts) < 2 {
		return false, errInvalidHash.New()
	}
	typ := parts[0]
	for _, method := range hashValidators {
		if strings.ToLower(typ) == strings.ToLower(method.Name()) {
			return method.Validate(hashed, plain)
		}
	}
	return false, errUnknownHashingMethod.WithAttributes("method", typ)
}
Validate checks if the hash matches the plaintext.
package auth
import (
	"context"
	"strings"
	"go.thethings.network/lorawan-stack/v3/pkg/auth/pbkdf2"
	"go.thethings.network/lorawan-stack/v3/pkg/errors"
)
type HashValidator interface {
	Name() string
	Hash(plain string) (string, error)
	Validate(hashed, plain string) (bool, error)
}
var defaultHashValidator = pbkdf2.Default()
type hashValidatorContextKeyType struct{}
var hashValidatorContextKey hashValidatorContextKeyType
func NewContextWithHashValidator(parent context.Context, hashValidator HashValidator) context.Context {
	return context.WithValue(parent, hashValidatorContextKey, hashValidator)
}
func HashValidatorFromContext(ctx context.Context) HashValidator {
	if hashValidator, ok := ctx.Value(hashValidatorContextKey).(HashValidator); ok {
		return hashValidator
	}
	return defaultHashValidator
}
var hashValidators = []HashValidator{
	defaultHashValidator,
}
func Hash(ctx context.Context, plain string) (string, error) {
	str, err := HashValidatorFromContext(ctx).Hash(plain)
	if err != nil {
		return "", err
	}
	return str, nil
}
var errInvalidHash = errors.DefineInternal(
	"invalid_hash",
	"invalid hash",
)
var errUnknownHashingMethod = errors.DefineInternal(
	"unknown_hashing_method",
	"unknown hashing method `{method}`",
)