Posted By

hlongmore on 08/17/11


Tagged

password python strength


Versions (?)

Password Strength Checker


 / Published in: Python
 

URL: http://snipplr.com/view/8755/password-strength-meter/

This is based on the JavaScript snippet at the snipplr URL listed. It in turn referenced a page that is no longer available. So I have decided to make my pythonification of the JavaScript available for others instead of hoarding it.

  1. """
  2. Class for checking the strength of a password.
  3. Copyright (C) 2011 Henry Longmore. This version
  4. of this file may be copied for personal, educational,
  5. or commercial purposes. Use at your own risk.
  6. """
  7.  
  8. import os
  9. from os import path
  10. import math
  11.  
  12. # Nota Bene: the configuration module is non-standard. You will
  13. # need to format and read your dictionary file yourself.
  14. from djangoapps import configuration
  15.  
  16. password_dict = path.join(os.sep, 'path', 'to', 'your', 'password.dictionary')
  17.  
  18. # Based on Password Strength Meter posted at Snipplr
  19. # http://snipplr.com/view/8755/password-strength-meter/
  20.  
  21. class PasswordStrengthChecker(object):
  22. def __init__(self, strength='medium', pwd_dict=''):
  23. self.punctuation = list("!@#$%^&* ()_+-='\";:[{]}\|.>,</?`~")
  24. self.similarity_map = {
  25. '3': 'e', 'x': 'k', '5': 's', '$': 's', '6': 'g', '7': 't',
  26. '8': 'b', '|': 'l', '9': 'g', '+': 't', '@': 'a', '0': 'o',
  27. '1': 'l', '2': 'z', '!': 'i', '1': 'i'}
  28. password_dictionary = configuration.Configuration(configpath=pwd_dict)
  29. self.word_list = dict()
  30. for i in xrange(3, 17):
  31. self.word_list[i] = password_dictionary.get_option('%s' % i, [])
  32.  
  33. self.strengths = ['medium', 'strong', 'best']
  34. self.thresholds = {'medium': 0.8, 'strong': 0.6, 'best': 0.6}
  35. self.min_length = {'medium': 8, 'strong': 8, 'best': 14}
  36. self.min_charsets = {'medium': 2, 'strong': 3, 'best': 3}
  37. self.similarity = {'medium': False, 'strong': True, 'best': True}
  38.  
  39. if strength not in self.strengths:
  40. strength = self.strengths[0]
  41. self.strength = strength
  42.  
  43. def is_charset_type(self, c, c_class):
  44. if c_class == 'capital':
  45. return c.isalpha() and c == c.upper()
  46. if c_class == 'lower':
  47. return c.isalpha() and c == c.lower()
  48. if c_class == 'digit':
  49. return c.isdigit()
  50. if c_class == 'punctuation':
  51. return c in self.punctuation
  52. return False
  53.  
  54. def canonicalize_word(self, word, letters_only=False):
  55. canonicalized = ''
  56. for c in list(word.lower()):
  57. if letters_only and not self.is_charset_type(c, 'lower'):
  58. canonicalized += c
  59. else:
  60. canonicalized += self.similarity_map.get(c, c)
  61. return canonicalized
  62.  
  63. def charset_span(self, word):
  64. checks = {'capital': 0, 'lower': 0, 'digit': 0, 'punctuation': 0}
  65. for c in list(word):
  66. for key in checks:
  67. if not checks[key] and self.is_charset_type(c, key):
  68. checks[key] = 1
  69. break
  70. return sum(checks.values())
  71.  
  72. def in_dictionary(self, word):
  73. similarity_check = self.similarity[self.strength]
  74. canonicalized = self.canonicalize_word(word, letters_only=similarity_check)
  75. word_length = len(canonicalized)
  76. if canonicalized in self.word_list[word_length]:
  77. return True
  78. if similarity_check:
  79. minimum_meaningful_match = int(math.floor((self.thresholds[self.strength]) * word_length))
  80. for length in xrange(minimum_meaningful_match, word_length):
  81. for start in xrange(0, word_length - minimum_meaningful_match):
  82. subword = canonicalized[start:start + length]
  83. if subword in self.word_list[len(subword)]:
  84. return True
  85. return False
  86.  
  87. def strong_enough(self, password):
  88. if not password:
  89. return False
  90. if len(password) < self.min_length[self.strength]:
  91. return False
  92. if self.charset_span(password) < self.min_charsets[self.strength]:
  93. return False
  94. if self.in_dictionary(password):
  95. return False
  96. return True
  97.  
  98. global password_checker
  99. password_checker = PasswordStrengthChecker(strength='medium', pwd_dict=password_dict)

Report this snippet  

You need to login to post a comment.