zxcvbn-hs-0.3.0.0: src/Text/Password/Strength.hs
{-# LANGUAGE OverloadedStrings #-}
{-|
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
This is a native Haskell implementation of
the [zxcvbn](https://github.com/dropbox/zxcvbn) password strength
estimation algorithm as it appears in the 2016 USENIX
Security [paper and presentation](https://www.usenix.org/conference/usenixsecurity16/technical-sessions/presentation/wheeler)
(with some small modifications).
-}
module Text.Password.Strength (
-- * Estimating Guesses
score,
Score(..),
-- * Calculating Password Strength
strength,
Strength(..),
-- * Default Configuration
en_US
) where
--------------------------------------------------------------------------------
-- Library Imports:
import Data.Text (Text)
import Data.Time.Calendar (Day)
import Data.Aeson (ToJSON(..), (.=))
import qualified Data.Aeson as Aeson
--------------------------------------------------------------------------------
-- Project Imports:
import Text.Password.Strength.Internal.Config
import qualified Text.Password.Strength.Internal.Search as Search
--------------------------------------------------------------------------------
-- | A score is an estimate of the number of guesses it would take to
-- crack a password.
newtype Score = Score { getScore :: Integer }
deriving (Show, Eq, Ord)
instance ToJSON Score where
toJSON s = Aeson.object
[ "score" .= getScore s
, "strength" .= show (strength s)
]
--------------------------------------------------------------------------------
-- | Estimate the number of guesses an attacker would need to make to
-- crack the given password.
score :: Config -- ^ Which dictionaries, keyboards, etc. to use.
-> Day -- ^ Reference day for date matches (should be current day).
-> Text -- ^ The password to score.
-> Score -- ^ Estimate.
score c d p = Score $ Search.score (Search.graph c d p)
--------------------------------------------------------------------------------
-- | Measurement of password strength.
data Strength
= Risky
-- ^ Too guessable: risky password. (guesses < \(10^{3}\))
| Weak
-- ^ Very guessable: protection from throttled online
-- attacks. (guesses < \(10^{6}\))
| Moderate
-- ^ Somewhat guessable: protection from unthrottled online
-- attacks. (guesses < \(10^{8}\))
| Safe
-- ^ Safely unguessable: moderate protection from offline
-- slow-hash scenario. (guesses < \(10^{10}\))
| Strong
-- ^ Very unguessable: strong protection from offline slow-hash
-- scenario. (guesses >= \(10^{10}\))
deriving (Show, Read, Eq, Ord, Enum, Bounded)
--------------------------------------------------------------------------------
-- | Calculate the strength of a password given its score.
strength :: Score -> Strength
strength (Score n)
| n < 10 ^ ( 3 :: Int) = Risky
| n < 10 ^ ( 6 :: Int) = Weak
| n < 10 ^ ( 8 :: Int) = Moderate
| n < 10 ^ (10 :: Int) = Safe
| otherwise = Strong