{-| Copyright: This file is part of the package zxcvbn-hs. It is subject to the license terms in the LICENSE file found in the top-level directory of this distribution and at: https://code.devalot.com/sthenauth/zxcvbn-hs No part of this package, including this file, may be copied, modified, propagated, or distributed except according to the terms contained in the LICENSE file. License: MIT -} module Text.Password.Strength.Internal.Sequence ( -- * Sequence Matches Delta, isSequence, estimateSequence ) where -------------------------------------------------------------------------------- -- Library Imports: import Data.Char (ord, isDigit) import Data.Text (Text) import qualified Data.Text as Text -------------------------------------------------------------------------------- -- | Type alias to represent the distance between characters. type Delta = Int -------------------------------------------------------------------------------- -- | If the delta between all of the characters in the given text are -- the same, that delta is returned. isSequence :: Text -> Maybe Delta isSequence t = case map measure offset of [] -> Nothing x:xs -> if all (== x) xs then Just x else Nothing where offset :: [(Char, Char)] offset = Text.zip t (Text.drop 1 t) measure :: (Char, Char) -> Delta measure (x, y) = ord y - ord x -------------------------------------------------------------------------------- -- | Estimate a sequence. -- -- Uses the scoring equation from the paper and not from the other -- implementations which don't even use the calculated delta. The -- only change from the paper is to compensated for a delta of 0, -- which isn't accounted for in the paper. estimateSequence :: (Char -> Bool) -> Text -> Delta -> Integer estimateSequence f t d = let len = toInteger $ Text.length t start = if len > 0 then Text.head t else '\0' delta = toInteger (if d == 0 then 1 else abs d) base = case () of () | f start -> 4 | isDigit start -> 10 | otherwise -> 26 in base * len * delta