Created
December 23, 2011 18:25
-
-
Save MetroWind/1514997 to your computer and use it in GitHub Desktop.
Calculate password strength.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8; -*- | |
# Calculate password strength. Algorithm is based on the | |
# Wolfram|Alpha’s, without dictionary and “extra critira”. | |
# | |
# Darksair | |
# Usage: Strength = pwStrength(password). | |
import re | |
def findSeqChar(CharLocs, src): | |
"""Find all sequential chars in string `src'. Only chars in | |
`CharLocs' are considered. `CharLocs' is a list of numbers. For | |
example if `CharLocs' is [0,2,3], then only src[2:3] is a possible | |
substring with sequential chars. | |
""" | |
AllSeqChars = [] | |
i = 0 | |
SeqChars = [] | |
while i < len(CharLocs) - 1: | |
if CharLocs[i + 1] - CharLocs[i] == 1 and \ | |
ord(src[CharLocs[i+1]]) - ord(src[CharLocs[i]]) == 1: | |
# We find a pair of sequential chars! | |
if not SeqChars: | |
SeqChars = [src[CharLocs[i]], src[CharLocs[i+1]]] | |
else: | |
SeqChars.append(src[CharLocs[i+1]]) | |
else: | |
if SeqChars: | |
AllSeqChars.append(SeqChars) | |
SeqChars = [] | |
i += 1 | |
if SeqChars: | |
AllSeqChars.append(SeqChars) | |
return AllSeqChars | |
def pwStrength(pw): | |
"""Wolfram|Alpha algorithm without dictionary and “extra critira”. | |
""" | |
Score = 0 | |
Length = len(pw) | |
Score += Length * 4 | |
# print("Length score: {}".format(Score)) | |
NUpper = 0 | |
NLower = 0 | |
NNum = 0 | |
NSymbol = 0 | |
LocUpper = [] | |
LocLower = [] | |
LocNum = [] | |
LocSymbol = [] | |
CharDict = {} | |
for i in range(Length): | |
Ch = pw[i] | |
Code = ord(Ch) | |
if Code >= 48 and Code <= 57: | |
NNum += 1 | |
LocNum.append(i) | |
elif Code >= 65 and Code <= 90: | |
NUpper += 1 | |
LocUpper.append(i) | |
elif Code >= 97 and Code <= 122: | |
NLower += 1 | |
LocLower.append(i) | |
else: | |
NSymbol += 1 | |
LocSymbol.append(i) | |
if not Ch in CharDict: | |
CharDict[Ch] = 1 | |
else: | |
CharDict[Ch] += 1 | |
if NUpper != Length and NLower != Length: | |
if NUpper != 0: | |
Score += (Length - NUpper) * 2 | |
# print("Upper case score:", (Length - NUpper) * 2) | |
if NLower != 0: | |
Score += (Length - NLower) * 2 | |
# print("Lower case score:", (Length - NLower) * 2) | |
if NNum != Length: | |
Score += NNum * 4 | |
# print("Number score:", NNum * 4) | |
Score += NSymbol * 6 | |
# print("Symbol score:", NSymbol * 6) | |
# Middle number or symbol | |
Score += len([i for i in LocNum if i != 0 and i != Length - 1]) * 2 | |
# print("Middle number score:", len([i for i in LocNum if i != 0 and i != Length - 1]) * 2) | |
Score += len([i for i in LocSymbol if i != 0 and i != Length - 1]) * 2 | |
# print("Middle symbol score:", len([i for i in LocSymbol if i != 0 and i != Length - 1]) * 2) | |
# Letters only? | |
if NUpper + NLower == Length: | |
Score -= Length | |
# print("Letter only:", -Length) | |
if NNum == Length: | |
Score -= Length | |
# print("Number only:", -Length) | |
# Repeating chars | |
Repeats = 0 | |
for Ch in CharDict: | |
if CharDict[Ch] > 1: | |
Repeats += CharDict[Ch] - 1 | |
if Repeats > 0: | |
Score -= int(Repeats / (Length - Repeats)) + 1 | |
# print("Repeating chars:", -int(Repeats / (Length - Repeats)) - 1) | |
if Length > 2: | |
# Consequtive letters | |
for MultiLowers in re.findall(''.join(["[a-z]{2,", str(Length), '}']), pw): | |
Score -= (len(MultiLowers) - 1) * 2 | |
# print("Consequtive lowers:", -(len(MultiLowers) - 1) * 2) | |
for MultiUppers in re.findall(''.join(["[A-Z]{2,", str(Length), '}']), pw): | |
Score -= (len(MultiUppers) - 1) * 2 | |
# print("Consequtive uppers:", -(len(MultiUppers) - 1) * 2) | |
# Consequtive numbers | |
for MultiNums in re.findall(''.join(["[0-9]{2,", str(Length), '}']), pw): | |
Score -= (len(MultiNums) - 1) * 2 | |
# print("Consequtive numbers:", -(len(MultiNums) - 1) * 2) | |
# Sequential letters | |
LocLetters = (LocUpper + LocLower) | |
LocLetters.sort() | |
for Seq in findSeqChar(LocLetters, pw.lower()): | |
if len(Seq) > 2: | |
Score -= (len(Seq) - 2) * 2 | |
# print("Sequential letters:", -(len(Seq) - 2) * 2) | |
# Sequential numbers | |
for Seq in findSeqChar(LocNum, pw.lower()): | |
if len(Seq) > 2: | |
Score -= (len(Seq) - 2) * 2 | |
# print("Sequential numbers:", -(len(Seq) - 2) * 2) | |
return Score |
Consider it under WTFPL :-).
Perfect. :-) My PHP port is here: https://gist.github.com/2926619 (for anyone interested).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is their any license to it? I'd like to adapt it, but need to make sure it's compatible with the MIT license.