diff --git a/passwd.go b/passwd.go index 4ce9245..3353061 100644 --- a/passwd.go +++ b/passwd.go @@ -62,6 +62,12 @@ func (p *Passwd) Passwd(pass, hash string) (string, error) { func (p *Passwd) IsPreferred(hash string) bool { _, algo := p.getAlgo(hash) if algo != nil && algo == p.d { + + // if the algorithem defines its own check for preference. + if ck, ok := algo.(interface{ IsPreferred(string) bool }); ok { + return ck.IsPreferred(hash) + } + return true } return false diff --git a/pkg/argon2/argon2.go b/pkg/argon2/argon2.go index 628f5b0..1fed682 100644 --- a/pkg/argon2/argon2.go +++ b/pkg/argon2/argon2.go @@ -101,6 +101,36 @@ func (p *argon) Passwd(pass string, check string) (string, error) { func (p *argon) ApplyPasswd(passwd *passwd.Passwd) { passwd.Register(p.name, p) } +func (s *argon) IsPreferred(hash string) bool { + args, err := s.parseArgs(hash) + if err != nil { + return false + } + + if args.version < s.version { + return false + } + if args.time < s.time { + return false + } + if args.memory < s.memory { + return false + } + if args.threads < s.threads { + return false + } + if args.keyLen < s.keyLen { + return false + } + if len(args.salt) < int(s.saltLen) { + return false + } + if len(args.hash) < int(s.keyLen) { + return false + } + + return true +} func (p *argon) defaultArgs() *pwArgs { return &pwArgs{ name: p.name, diff --git a/pkg/scrypt/scrypt.go b/pkg/scrypt/scrypt.go index d07401f..31d85c1 100644 --- a/pkg/scrypt/scrypt.go +++ b/pkg/scrypt/scrypt.go @@ -93,6 +93,30 @@ func (s *scryptpw) ApplyPasswd(p *passwd.Passwd) { p.SetFallthrough(s) } } +func (s *scryptpw) IsPreferred(hash string) bool { + args, err := s.parseArgs(hash) + if err != nil { + return false + } + + if args.N < s.N { + return false + } + if args.R < s.R { + return false + } + if args.P < s.P { + return false + } + if args.SaltLen < s.SaltLen { + return false + } + if args.DKLen < s.DKLen { + return false + } + + return true +} func (s *scryptpw) defaultArgs() *scryptArgs { return &scryptArgs{ name: s.name, @@ -145,11 +169,13 @@ func (s *scryptpw) parseArgs(hash string) (*scryptArgs, error) { if err != nil { return nil, fmt.Errorf("%w: corrupt salt part", passwd.ErrBadHash) } + args.SaltLen = len(args.salt) args.hash, err = s.encoder.DecodeString(hash) if err != nil { return nil, fmt.Errorf("%w: corrupt hash part", passwd.ErrBadHash) } + args.DKLen = len(args.hash) return args, nil }