Skip to content

Instantly share code, notes, and snippets.

@MetroWind
Created December 23, 2011 18:25
Show Gist options
  • Select an option

  • Save MetroWind/1514997 to your computer and use it in GitHub Desktop.

Select an option

Save MetroWind/1514997 to your computer and use it in GitHub Desktop.
Calculate password strength.
# -*- 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
@xrstf
Copy link
Copy Markdown

xrstf commented Jun 13, 2012

Is their any license to it? I'd like to adapt it, but need to make sure it's compatible with the MIT license.

@MetroWind
Copy link
Copy Markdown
Author

Consider it under WTFPL :-).

@xrstf
Copy link
Copy Markdown

xrstf commented Jun 13, 2012

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