This module implements the popular F/OSS password strength check available at rumkin.com. A more detailed description may be found at that link, as well as the rationale behind it.
The results returned by this module should be identical to those obtained from the live version of the strength test at rumkin.com. They will, however, differ from the version available as source for download, as there is a bug in which characters in keyboard punctuation `~-_=+[{]}|;:'",<.>/?\ contribute an additional sequence space of only 20 instead of the correct 22. As this bug is fixed in the live version, it is fixed in this package as well.
Warning: Common password warnings returned by this package are not factored into the overall strength of the password. As such, while a warning of "Common password!" will be returned for the password "raidersofthelostark", its strength will be Strong
and its supposed entropy 70.5 bits, despite it being a weak, common password. Consider using Zxcvbn
/ZxcvbnPlus
if you require common passwords to impact the overall score and not merely be presented as warnings.
The computational performance of this library is quite good, with essentially instantaneous results.
While it does contain a common word list, the library is relatively light. Sizes for an extremely simple example application follow:
For normal usage of this module, only the function getStats
and the returned types RumkinResult
and Strength
are necessary.
getStats : String -> RumkinResult
Given a password, check it for common passwords and score it, returning the result.
{ warnings : List String
, length : Basics.Int
, strength : Strength
, strengthComment : String
, entropy : Basics.Float
, charsetSize : Basics.Int
}
The results returned by getStats
, containing the following fields:
warnings
-- A (possible empty) list of printed warnings, suitable for display to the user. If the password is a common one, a warning will be contained in this list, as will warnings about length.length
-- The length of the password.strength
-- The overall strength of the password, e.g. for display as a growing bar. This does not take into account common passwords.strengthComment
-- A comment on the strength of the password, suitable for display to the user; a list of the comments is found in the documentation for Strength
.entropy
-- The estimated bits of entropy of the password; this does not take into account common passwords, and so the actual entropy is quite possibly considerably lower.charsetSize
-- The total sequence space of the password, e.g. "kjethrsfdsdgf" would be 26, since it consists solely of lowercase Latin characters. This is not Unicode aware, so it is conservative when outside the "standard" range.The overall strength of the password, along with the string that will be found in strengthComment
. These do not take into account common passwords.
VeryWeak
-- "Try making your password longer, including CAPITALS, or adding symbols."Weak
-- "Usually good enough for computer login passwords and to keep out the average person."Reasonable
-- "This password is fairly secure cryptographically and skilled hackers may need some good computing power to crack it. (Depends greatly on implementation!)"Strong
-- "This password is typically good enough to safely guard sensitive information like financial records."VeryStrong
-- "More often than not, this level of security is overkill."The sequence frequency and common password lists used by this package are compressed and require parsing prior to use. If you wish to control exactly when that happens (and cache it in your model), the following functions are available.
getCustomStats : Internal.FrequencyList -> Internal.CommonPasswordList -> String -> RumkinResult
getStats
with a provided frequency list and common password list. This may be used to control the point at which parsing these lists is performed or to run the algorithm with custom frequency/password lists.
parseFrequencyList : String -> Result String Internal.FrequencyList
Given a ompressed/encoded sequence frequency list, try to parse it. In general, this should only be used to parse the list at Rumkin.Frequency.frequencyList
, but it may be used to parse custom frequency lists, if they are encoded the same. The description of the frequency list encoding follows:
The frequency thing is a bit more interesting, but still not too complex. Each three letters are base-95 encoded number representing the chance that this combination comes next. Subtract the value of ' ' from each of the three, then ((((first_value * 95) + second_value) * 95) + third_value) will give you the odds that this pair is grouped together. The first is " " (non-alpha chars), then " a", " b", etc. " y", " z", "a ", "aa", "ab", and so on. If you decrypt the table successfully, you should see a really large number for "qu".
parseCommonList : String -> Result String Internal.CommonPasswordList
Given a compressed/encoded common password list, try to parse it. In general, this should only be used to parse the list at Rumkin.Common.commonList
, but it may be used to parse custom common password lists, if they are encoded the same. The description of the common password list encoding follows:
The compression algorithm is very basic - the first letter is upper case, and it means to copy X letters from the previous word. A = 0, B = 1, etc. So, if I had "apple apricot banana", it would compress to "AappleCricotAbanana".