# -*- coding: utf-8 -*- import string def __character_groups(basestring_sequence): """ Returns a (character groups used, min. amount of characters for each of those groups)-tuple """ counters = {string.ascii_lowercase: 0, string.ascii_uppercase: 0, string.digits: 0, string.punctuation: 0} for character in basestring_sequence: for group in counters.keys(): if character in group: counters[group] += 1 different_groups = [value for value in counters.values() if value > 0] return (len(different_groups), min(different_groups)) def calculate_entropy(password): """ NIST 800-63 Returns the entropy score (int) """ if not isinstance(password, basestring): raise Exception('Password should be a basestring') plength = len(password) entropy_value = 0 # "The entropy of the first character is four bits" entropy_value += len(password[0:1]) * 4 # "The entropy of the next seven characters are two bits per character" entropy_value += len(password[1:8]) * 2 # "The ninth through the twentieth character has 1.5 bits of entropy # per character" entropy_value += int(len(password[8:20]) * 1.5) # use only the int part # "Characters 21 and above have one bit of entropy per character." if plength > 20: entropy_value += (plength - 20) different_groups, chars_per_group = __character_groups(password) if different_groups >= 3: if chars_per_group >= 2: # 2 or more characters for each group entropy_value += 8 else: entropy_value += 6 return entropy_value