package passwd import ( "github.com/pkg/errors" ) var ErrAlgoNotFound = errors.New("algo not found") type Registry struct { hashers map[Algo]Hasher } func (r *Registry) Register(algo Algo, hasher Hasher) { r.hashers[algo] = hasher } func (r *Registry) Match(algo Algo, plaintext string, hash string) (bool, error) { hasher, exists := r.hashers[algo] if !exists { return false, errors.WithStack(ErrAlgoNotFound) } matches, err := hasher.Match(plaintext, hash) if err != nil { return false, errors.WithStack(err) } return matches, nil } func (r *Registry) Hash(algo Algo, plaintext string) (string, error) { hasher, exists := r.hashers[algo] if !exists { return "", errors.WithStack(ErrAlgoNotFound) } hash, err := hasher.Hash(plaintext) if err != nil { return "", errors.WithStack(err) } return hash, nil } func (r *Registry) Algorithms() []Algo { algorithms := make([]Algo, 0, len(r.hashers)) for algo := range r.hashers { algorithms = append(algorithms, algo) } return algorithms } func NewRegistry() *Registry { return &Registry{ hashers: make(map[Algo]Hasher), } } var defaultRegistry = NewRegistry() func Match(algo Algo, plaintext string, hash string) (bool, error) { matches, err := defaultRegistry.Match(algo, plaintext, hash) if err != nil { return false, errors.WithStack(err) } return matches, nil } func Hash(algo Algo, plaintext string) (string, error) { hash, err := defaultRegistry.Hash(algo, plaintext) if err != nil { return "", errors.WithStack(err) } return hash, nil } func Algorithms() []Algo { return defaultRegistry.Algorithms() } func Register(algo Algo, hasher Hasher) { defaultRegistry.Register(algo, hasher) }