Files
opencloud/vendor/github.com/trustelem/zxcvbn/matching/sequence.go
2023-04-19 20:24:34 +02:00

79 lines
1.5 KiB
Go

package matching
import (
"regexp"
"github.com/trustelem/zxcvbn/match"
)
type sequenceMatch struct{}
const maxDelta = 5
func abs(a int) int {
if a < 0 {
return -a
}
return a
}
var reLower = regexp.MustCompile(`^[a-z]+$`)
var reUpper = regexp.MustCompile(`^[A-Z]+$`)
var reDigits = regexp.MustCompile(`^\d+$`)
func (sequenceMatch) Matches(password string) []*match.Match {
matches := []*match.Match{}
if len(password) == 1 {
return matches
}
update := func(i, j, delta int) {
absDelta := abs(delta)
if j-i > 1 || absDelta == 1 {
if absDelta > 0 && absDelta <= maxDelta {
token := password[i : j+1]
// conservatively stick with roman alphabet size.
// (this could be improved)
seqName := "unicode"
seqSpace := 26
if reLower.MatchString(token) {
seqName = "lower"
} else if reUpper.MatchString(token) {
seqName = "upper"
} else if reDigits.MatchString(token) {
seqName = "digits"
seqSpace = 10
}
matches = append(matches, &match.Match{
Pattern: "sequence",
I: i,
J: j,
Token: password[i : j+1],
SequenceName: seqName,
SequenceSpace: seqSpace,
Ascending: delta > 0,
})
}
}
}
i := 0
lastDelta := 0 // null
for k := 1; k <= len(password)-1; k++ {
delta := int(password[k]) - int(password[k-1])
if k == 1 {
lastDelta = delta
}
if delta == lastDelta {
continue
}
j := k - 1
update(i, j, lastDelta)
i = j
lastDelta = delta
}
update(i, len(password)-1, lastDelta)
return matches
}