84 |
84 |
85 # how much redundancy is permitted, if the password is |
85 # how much redundancy is permitted, if the password is |
86 # long enough. we will skip the redudancy penalty if this |
86 # long enough. we will skip the redudancy penalty if this |
87 # number is not exceeded (meaning redundancy < this number) |
87 # number is not exceeded (meaning redundancy < this number) |
88 self.redundancy = { |
88 self.redundancy = { |
89 "value": 1, # 1 means, not double characters, default to start |
89 "value": 1, # 1 means, not double characters, |
90 "permitted": 2.0, # 2 means, in average every character can occur twice |
90 # default to start |
|
91 "permitted": 2.0, # 2 means, in average every character |
|
92 # can occur twice |
91 "status": self.Status_Failed, |
93 "status": self.Status_Failed, |
92 "rating": 0, |
94 "rating": 0, |
93 } |
95 } |
94 |
96 |
95 # number of uppercase letters, such as A-Z |
97 # number of uppercase letters, such as A-Z |
316 uniqueCharacters.append(password[index1]) |
318 uniqueCharacters.append(password[index1]) |
317 |
319 |
318 # calculate a redundancy number |
320 # calculate a redundancy number |
319 self.redundancy["value"] = len(password) / len(uniqueCharacters) |
321 self.redundancy["value"] = len(password) / len(uniqueCharacters) |
320 |
322 |
321 # Check for sequential alpha string patterns (forward and reverse) but only, |
323 # Check for sequential alpha string patterns (forward and reverse) |
322 # if the string has already a length to check for, does not make sense to check |
324 # but only, if the string has already a length to check for, does |
323 # the password "ab" for the sequential data "abc" |
325 # not make sense to check the password "ab" for the sequential data |
|
326 # "abc" |
324 lowercasedPassword = password.lower() |
327 lowercasedPassword = password.lower() |
325 |
328 |
326 if self.passwordLength["count"] >= self.sequentialLetters["length"]: |
329 if self.passwordLength["count"] >= self.sequentialLetters["length"]: |
327 for index in range(len(self.sequentialLetters["data"]) - \ |
330 for index in range(len(self.sequentialLetters["data"]) - \ |
328 self.sequentialLetters["length"] + 1): |
331 self.sequentialLetters["length"] + 1): |
348 |
351 |
349 # Check common keyboard patterns |
352 # Check common keyboard patterns |
350 patternsMatched = [] |
353 patternsMatched = [] |
351 if self.passwordLength["count"] >= self.keyboardPatterns["length"]: |
354 if self.passwordLength["count"] >= self.keyboardPatterns["length"]: |
352 for pattern in self.keyboardPatterns["data"]: |
355 for pattern in self.keyboardPatterns["data"]: |
353 for index in range(len(pattern) - self.keyboardPatterns["length"] + 1): |
356 for index in range( |
354 fwd = pattern[index:index + self.keyboardPatterns["length"]] |
357 len(pattern) - self.keyboardPatterns["length"] + 1): |
|
358 fwd = pattern[index:index + |
|
359 self.keyboardPatterns["length"]] |
355 rev = self.__strReverse(fwd) |
360 rev = self.__strReverse(fwd) |
356 if lowercasedPassword.find(fwd) != -1: |
361 if lowercasedPassword.find(fwd) != -1: |
357 if fwd not in patternsMatched: |
362 if fwd not in patternsMatched: |
358 self.keyboardPatterns["count"] += 1 |
363 self.keyboardPatterns["count"] += 1 |
359 patternsMatched.append(fwd) |
364 patternsMatched.append(fwd) |
364 |
369 |
365 # Try to find repeated sequences of characters. |
370 # Try to find repeated sequences of characters. |
366 if self.passwordLength["count"] >= self.repeatedSequences["length"]: |
371 if self.passwordLength["count"] >= self.repeatedSequences["length"]: |
367 for index in range(len(lowercasedPassword) - \ |
372 for index in range(len(lowercasedPassword) - \ |
368 self.repeatedSequences["length"] + 1): |
373 self.repeatedSequences["length"] + 1): |
369 fwd = lowercasedPassword[index:index + self.repeatedSequences["length"]] |
374 fwd = lowercasedPassword[ |
|
375 index:index + self.repeatedSequences["length"]] |
370 if lowercasedPassword.find( |
376 if lowercasedPassword.find( |
371 fwd, index + self.repeatedSequences["length"]) != -1: |
377 fwd, index + self.repeatedSequences["length"]) != -1: |
372 self.repeatedSequences["count"] += 1 |
378 self.repeatedSequences["count"] += 1 |
373 |
379 |
374 # Try to find mirrored sequences of characters. |
380 # Try to find mirrored sequences of characters. |
375 if self.passwordLength["count"] >= self.mirroredSequences["length"]: |
381 if self.passwordLength["count"] >= self.mirroredSequences["length"]: |
376 for index in range(len(lowercasedPassword) - \ |
382 for index in range(len(lowercasedPassword) - \ |
377 self.mirroredSequences["length"] + 1): |
383 self.mirroredSequences["length"] + 1): |
378 fwd = lowercasedPassword[index:index + self.mirroredSequences["length"]] |
384 fwd = lowercasedPassword[ |
|
385 index:index + self.mirroredSequences["length"]] |
379 rev = self.__strReverse(fwd) |
386 rev = self.__strReverse(fwd) |
380 if lowercasedPassword.find( |
387 if lowercasedPassword.find( |
381 fwd, index + self.mirroredSequences["length"]) != -1: |
388 fwd, index + self.mirroredSequences["length"]) != -1: |
382 self.mirroredSequences["count"] += 1 |
389 self.mirroredSequences["count"] += 1 |
383 |
390 |
384 # Initial score based on length |
391 # Initial score based on length |
385 self.score["count"] = self.passwordLength["count"] * self.passwordLength["factor"] |
392 self.score["count"] = self.passwordLength["count"] * \ |
|
393 self.passwordLength["factor"] |
386 |
394 |
387 # passwordLength |
395 # passwordLength |
388 # credit additional length or punish "under" length |
396 # credit additional length or punish "under" length |
389 if self.passwordLength["count"] >= self.passwordLength["minimum"]: |
397 if self.passwordLength["count"] >= self.passwordLength["minimum"]: |
390 # credit additional characters over minimum |
398 # credit additional characters over minimum |
391 self.passwordLength["rating"] = self.passwordLength["bonus"] + \ |
399 self.passwordLength["rating"] = self.passwordLength["bonus"] + \ |
392 (self.passwordLength["count"] - self.passwordLength["minimum"]) * \ |
400 (self.passwordLength["count"] - |
|
401 self.passwordLength["minimum"]) * \ |
393 self.passwordLength["factor"] |
402 self.passwordLength["factor"] |
394 else: |
403 else: |
395 self.passwordLength["rating"] = self.passwordLength["penalty"] |
404 self.passwordLength["rating"] = self.passwordLength["penalty"] |
396 self.score["count"] += self.passwordLength["rating"] |
405 self.score["count"] += self.passwordLength["rating"] |
397 |
406 |
398 # recommendedPasswordLength |
407 # recommendedPasswordLength |
399 # Credit reaching the recommended password length or put a |
408 # Credit reaching the recommended password length or put a |
400 # penalty on it |
409 # penalty on it |
401 if self.passwordLength["count"] >= self.recommendedPasswordLength["minimum"]: |
410 if self.passwordLength["count"] >= \ |
|
411 self.recommendedPasswordLength["minimum"]: |
402 self.recommendedPasswordLength["rating"] = \ |
412 self.recommendedPasswordLength["rating"] = \ |
403 self.recommendedPasswordLength["bonus"] + \ |
413 self.recommendedPasswordLength["bonus"] + \ |
404 (self.passwordLength["count"] - \ |
414 (self.passwordLength["count"] - \ |
405 self.recommendedPasswordLength["minimum"]) * \ |
415 self.recommendedPasswordLength["minimum"]) * \ |
406 self.recommendedPasswordLength["factor"] |
416 self.recommendedPasswordLength["factor"] |
410 self.score["count"] += self.recommendedPasswordLength["rating"] |
420 self.score["count"] += self.recommendedPasswordLength["rating"] |
411 |
421 |
412 # lowercaseLetters |
422 # lowercaseLetters |
413 # Honor or punish the lowercase letter use |
423 # Honor or punish the lowercase letter use |
414 if self.lowercaseLetters["count"] > 0: |
424 if self.lowercaseLetters["count"] > 0: |
415 self.lowercaseLetters["rating"] = self.lowercaseLetters["bonus"] + \ |
425 self.lowercaseLetters["rating"] = \ |
416 self.lowercaseLetters["count"] * self.lowercaseLetters["factor"] |
426 self.lowercaseLetters["bonus"] + \ |
|
427 self.lowercaseLetters["count"] * \ |
|
428 self.lowercaseLetters["factor"] |
417 else: |
429 else: |
418 self.lowercaseLetters["rating"] = self.lowercaseLetters["penalty"] |
430 self.lowercaseLetters["rating"] = self.lowercaseLetters["penalty"] |
419 self.score["count"] += self.lowercaseLetters["rating"] |
431 self.score["count"] += self.lowercaseLetters["rating"] |
420 |
432 |
421 # uppercaseLetters |
433 # uppercaseLetters |
422 # Honor or punish the lowercase letter use |
434 # Honor or punish the lowercase letter use |
423 if self.uppercaseLetters["count"] > 0: |
435 if self.uppercaseLetters["count"] > 0: |
424 self.uppercaseLetters["rating"] = self.uppercaseLetters["bonus"] + \ |
436 self.uppercaseLetters["rating"] = \ |
425 self.uppercaseLetters["count"] * self.uppercaseLetters["factor"] |
437 self.uppercaseLetters["bonus"] + \ |
|
438 self.uppercaseLetters["count"] * \ |
|
439 self.uppercaseLetters["factor"] |
426 else: |
440 else: |
427 self.uppercaseLetters["rating"] = self.uppercaseLetters["penalty"] |
441 self.uppercaseLetters["rating"] = self.uppercaseLetters["penalty"] |
428 self.score["count"] += self.uppercaseLetters["rating"] |
442 self.score["count"] += self.uppercaseLetters["rating"] |
429 |
443 |
430 # numerics |
444 # numerics |
464 self.score["count"] += self.middleNumerics["rating"] |
478 self.score["count"] += self.middleNumerics["rating"] |
465 |
479 |
466 # sequentialLetters |
480 # sequentialLetters |
467 # Honor or punish the sequential letter use |
481 # Honor or punish the sequential letter use |
468 if self.sequentialLetters["count"] == 0: |
482 if self.sequentialLetters["count"] == 0: |
469 self.sequentialLetters["rating"] = self.sequentialLetters["bonus"] + \ |
483 self.sequentialLetters["rating"] = \ |
470 self.sequentialLetters["count"] * self.sequentialLetters["factor"] |
484 self.sequentialLetters["bonus"] + \ |
471 else: |
485 self.sequentialLetters["count"] * \ |
472 self.sequentialLetters["rating"] = self.sequentialLetters["penalty"] |
486 self.sequentialLetters["factor"] |
|
487 else: |
|
488 self.sequentialLetters["rating"] = \ |
|
489 self.sequentialLetters["penalty"] |
473 self.score["count"] += self.sequentialLetters["rating"] |
490 self.score["count"] += self.sequentialLetters["rating"] |
474 |
491 |
475 # sequentialNumerics |
492 # sequentialNumerics |
476 # Honor or punish the sequential numerics use |
493 # Honor or punish the sequential numerics use |
477 if self.sequentialNumerics["count"] == 0: |
494 if self.sequentialNumerics["count"] == 0: |
478 self.sequentialNumerics["rating"] = self.sequentialNumerics["bonus"] + \ |
495 self.sequentialNumerics["rating"] = \ |
479 self.sequentialNumerics["count"] * self.sequentialNumerics["factor"] |
496 self.sequentialNumerics["bonus"] + \ |
480 else: |
497 self.sequentialNumerics["count"] * \ |
481 self.sequentialNumerics["rating"] = self.sequentialNumerics["penalty"] |
498 self.sequentialNumerics["factor"] |
|
499 else: |
|
500 self.sequentialNumerics["rating"] = \ |
|
501 self.sequentialNumerics["penalty"] |
482 self.score["count"] += self.sequentialNumerics["rating"] |
502 self.score["count"] += self.sequentialNumerics["rating"] |
483 |
503 |
484 # keyboardPatterns |
504 # keyboardPatterns |
485 # Honor or punish the keyboard patterns use |
505 # Honor or punish the keyboard patterns use |
486 if self.keyboardPatterns["count"] == 0: |
506 if self.keyboardPatterns["count"] == 0: |
487 self.keyboardPatterns["rating"] = self.keyboardPatterns["bonus"] + \ |
507 self.keyboardPatterns["rating"] = \ |
488 self.keyboardPatterns["count"] * self.keyboardPatterns["factor"] |
508 self.keyboardPatterns["bonus"] + \ |
|
509 self.keyboardPatterns["count"] * \ |
|
510 self.keyboardPatterns["factor"] |
489 else: |
511 else: |
490 self.keyboardPatterns["rating"] = self.keyboardPatterns["penalty"] |
512 self.keyboardPatterns["rating"] = self.keyboardPatterns["penalty"] |
491 self.score["count"] += self.keyboardPatterns["rating"] |
513 self.score["count"] += self.keyboardPatterns["rating"] |
492 |
514 |
493 # Count our basicRequirements and set the status |
515 # Count our basicRequirements and set the status |
528 # requirement met |
550 # requirement met |
529 self.basicRequirements["count"] += 1 |
551 self.basicRequirements["count"] += 1 |
530 |
552 |
531 # judge the requirement status |
553 # judge the requirement status |
532 self.basicRequirements["status"] = self.__determineStatus( |
554 self.basicRequirements["status"] = self.__determineStatus( |
533 self.basicRequirements["count"] - self.basicRequirements["minimum"]) |
555 self.basicRequirements["count"] - |
|
556 self.basicRequirements["minimum"]) |
534 if self.basicRequirements["status"] != self.Status_Failed: |
557 if self.basicRequirements["status"] != self.Status_Failed: |
535 self.basicRequirements["rating"] = \ |
558 self.basicRequirements["rating"] = \ |
536 self.basicRequirements["bonus"] + \ |
559 self.basicRequirements["bonus"] + \ |
537 self.basicRequirements["factor"] * self.basicRequirements["count"] |
560 self.basicRequirements["factor"] * \ |
538 else: |
561 self.basicRequirements["count"] |
539 self.basicRequirements["rating"] = self.basicRequirements["penalty"] |
562 else: |
|
563 self.basicRequirements["rating"] = \ |
|
564 self.basicRequirements["penalty"] |
540 self.score["count"] += self.basicRequirements["rating"] |
565 self.score["count"] += self.basicRequirements["rating"] |
541 |
566 |
542 # beyond basic requirements |
567 # beyond basic requirements |
543 self.recommendedPasswordLength["status"] = self.__determineStatus( |
568 self.recommendedPasswordLength["status"] = self.__determineStatus( |
544 self.recommendedPasswordLength["count"] - \ |
569 self.recommendedPasswordLength["count"] - \ |
563 # we apply them only, if the length is not awesome |
588 # we apply them only, if the length is not awesome |
564 if self.recommendedPasswordLength["status"] != self.Status_Exceeded: |
589 if self.recommendedPasswordLength["status"] != self.Status_Exceeded: |
565 # repeatedSequences |
590 # repeatedSequences |
566 # Honor or punish the use of repeated sequences |
591 # Honor or punish the use of repeated sequences |
567 if self.repeatedSequences["count"] == 0: |
592 if self.repeatedSequences["count"] == 0: |
568 self.repeatedSequences["rating"] = self.repeatedSequences["bonus"] |
593 self.repeatedSequences["rating"] = \ |
|
594 self.repeatedSequences["bonus"] |
569 else: |
595 else: |
570 self.repeatedSequences["rating"] = self.repeatedSequences["penalty"] + \ |
596 self.repeatedSequences["rating"] = \ |
|
597 self.repeatedSequences["penalty"] + \ |
571 self.repeatedSequences["count"] * \ |
598 self.repeatedSequences["count"] * \ |
572 self.repeatedSequences["factor"] |
599 self.repeatedSequences["factor"] |
573 |
600 |
574 # mirroredSequences |
601 # mirroredSequences |
575 # Honor or punish the use of mirrored sequences |
602 # Honor or punish the use of mirrored sequences |
576 if self.mirroredSequences["count"] == 0: |
603 if self.mirroredSequences["count"] == 0: |
577 self.mirroredSequences["rating"] = self.mirroredSequences["bonus"] |
604 self.mirroredSequences["rating"] = \ |
|
605 self.mirroredSequences["bonus"] |
578 else: |
606 else: |
579 self.mirroredSequences["rating"] = self.mirroredSequences["penalty"] + \ |
607 self.mirroredSequences["rating"] = \ |
|
608 self.mirroredSequences["penalty"] + \ |
580 self.mirroredSequences["count"] * \ |
609 self.mirroredSequences["count"] * \ |
581 self.mirroredSequences["factor"] |
610 self.mirroredSequences["factor"] |
582 |
611 |
583 # save value before redundancy |
612 # save value before redundancy |
584 self.score["beforeRedundancy"] = self.score["count"] |
613 self.score["beforeRedundancy"] = self.score["count"] |
585 |
614 |
586 # apply the redundancy |
615 # apply the redundancy |
587 # is the password length requirement fulfilled? |
616 # is the password length requirement fulfilled? |
588 if self.recommendedPasswordLength["status"] != self.Status_Exceeded: |
617 if self.recommendedPasswordLength["status"] != self.Status_Exceeded: |
589 # full penalty, because password is not long enough, only for a positive score |
618 # full penalty, because password is not long enough, only for |
|
619 # a positive score |
590 if self.score["count"] > 0: |
620 if self.score["count"] > 0: |
591 self.score["count"] *= 1.0 / self.redundancy["value"] |
621 self.score["count"] *= 1.0 / self.redundancy["value"] |
592 |
622 |
593 # level it out |
623 # level it out |
594 if self.score["count"] > 100: |
624 if self.score["count"] > 100: |