diff --git a/src/test_pass.py b/src/test_pass.py index 0c8ba26c56b1c193ec6863d3d569a0ee9cbcde24..2ffdcb995205d106b86b0785159e5ccbaece429b 100644 --- a/src/test_pass.py +++ b/src/test_pass.py @@ -21,12 +21,7 @@ from dateutil.parser import parse from itertools import combinations from zxcvbn import zxcvbn from zxcvbn.matching import add_frequency_lists - - -def tr(text): - # TODO translation - return text - +from translations import tr def add_dictionnaries(): dicts = {} @@ -43,19 +38,21 @@ def add_dictionnaries(): # Process user inputs: # Generate all possibile combinations of 2 parts of dates def process_input(inputs): - dates = [] - words = [] - for i in inputs: - try: - date = parse(i) - dates += date.strftime("%d-%m-%y-%B-%Y-%A").split('-') - except: - words.append(i) - for n in range(2, 4): - for subset in combinations(dates, n): - words.append("".join(subset)) - print(words) - return words + try : + dates = [] + words = [] + for i in inputs: + try: + date = parse(i) + dates += date.strftime("%d-%m-%y-%B-%Y-%A").split('-') + except: + words.append(i) + for n in range(2, 4): + for subset in combinations(dates, n): + words.append("".join(subset)) + return words + except: + return None def test_pass(password, inputs): @@ -68,31 +65,27 @@ def test_pass(password, inputs): lines.append("Résultats du test\n") lines.append("Nombre de tentatives : {}".format(results["guesses"])) - # TODO let tr handle things - times = results["crack_times_display"] lines.append("Temps requis pour craquer votre mot de passe") - lines.append("\t Dump bases de donnée mal protégée : \t**{}**".format( - tr(times["offline_fast_hashing_1e10_per_second"]))) - lines.append("\t Dump bases de donnée, bien protégée : \t**{}**".format( - tr(times["offline_slow_hashing_1e4_per_second"]))) - lines.append("\t En ligne, sans protection anti bruteforce : \t**{}**".format( - tr(times["online_no_throttling_10_per_second"]))) - lines.append("\t En ligne, avec protection anti bruteforce : \t**{}**".format( - tr(times["online_throttling_100_per_hour"]))) + for key, value in results["crack_times_display"].items(): + lines.append("\t "+tr(key).capitalize()+" :\t **"+tr(value)+"**") lines.append("\n") lines.append("Methode de hack utilisées") # Print hack methods - print(results["sequence"]) for seq in results["sequence"]: if seq["pattern"] == "bruteforce": lines.append("\tMot de passe trouvé par force brute") elif seq["pattern"] == "repeat": for match in seq["base_matches"]: - print("\tMot de passe trouvé par repetition depuis le dictionnaire {}". - format(tr(match["dictionary_name"]))) + line = "\tMot de passe trouvé par répétitions depuis" + try: + line += "le dictionnaire '{}'".format(tr(match["dictionary_name"])) + except: + line += "le motif '{}'".format(tr(match["token"])) + finally: + lines.append(line) elif seq["pattern"] == "date": - lines.append("\tMot de passe trouvé par dates") + lines.append("\tMot de passe trouvé par essai de dates") elif seq["pattern"] == "sequence": lines.append("\tMot proche trouvé dans la séquence : '{}'".format(tr(seq["sequence_name"]))) else: @@ -100,12 +93,9 @@ def test_pass(password, inputs): lines.append("\n") - valeur = ["Tres faible", "Faible", "Acceptable", "Correct", "Bon"] - lines.append("Score Global {}/4 : {}".format(results["score"], valeur[results["score"]])) - for key, values in results["feedback"].items(): if values != [] and values != "": - lines.append("{} :".format(tr(key))) + lines.append("{} :".format(tr(key).capitalize())) else: continue if not isinstance(values, list): @@ -113,4 +103,8 @@ def test_pass(password, inputs): values = [values] for val in values: lines.append("\t{}".format(tr(val))) + + valeur = ["Très faible", "Faible", "Tolérable", "Correct", "Bon"] + lines.append("Score Global {}/4 : {}".format(results["score"], valeur[results["score"]])) + return lines diff --git a/src/translations.py b/src/translations.py new file mode 100644 index 0000000000000000000000000000000000000000..1dac12b30b195228213bf280c0eb0ce0b50b25d3 --- /dev/null +++ b/src/translations.py @@ -0,0 +1,91 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -* +# Copyright (C) 2017 Tetras Libre <contact@Tetras-Libre.fr> +# Author: Beniamine, David <David.Beniamine@Tetras-Libre.fr> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Translation: technical english to NOT technical french + +import re + +translations = { + 'offline_fast_hashing_1e10_per_second': 'Essai sur base de donnée volée mal protégée', + 'offline_slow_hashing_1e4_per_second': 'Essai sur base de donnée volée bien protégée', + 'online_no_throttling_10_per_second': 'Essai en ligne sans protection anti brute force', + 'online_throttling_100_per_hour': 'Essai en ligne avec protection anti brute force', + 'passwords': 'mots de passes', + 'surnames': 'nom de famille', + 'user_input': "indices données par l'attaquant.e", + 'suggestions': 'conseils', + 'warning': 'problèmes', + 'less than a second': "moins d'une seconde", + 'less than a minute': "moins d'une minute", +} + +substitutions = { + 'less than': "moins de", + 'day': 'jour', + 'second(s*)': 'seconde\g<1>', + 'hour(s*)': 'heure\g<1>', + 'months*': 'mois', + 'year(s*)': 'an\g<1>', + 'centuries': 'des siècles', + 'centuries': 'des siècles', + "Predictable substitutions like (.*) instead of (.*) don't help very much": + "Les substitutions prévisibles tels que \g<1> au lieu de \g<2> n'aident pas beaucoup", + 'Uncommon words are better': 'Préférer des mots rares', + 'Add another word or two': 'Ajouter un mot ou deux', + 'This is similar to a commonly used password': 'Ce mot de passe ressemble à un mot de passe très utilisé', + 'lower': 'minuscules', + 'upper': 'majuscules', + 'digits': 'chiffres', + 'unicode': 'caractères unicodes', + 'Use a few words, avoid common phrases': 'Utiliser plusieurs mots, évitez les phrases classiques', + 'No need for symbols, digits, or uppercase letters': 'pas besoin de symboles, nombres ou majuscules', + 'are easy to guess': 'sont faciles à deviner', + 'Straight rows of keys': 'Les suites directes de lettres sur le clavier', + 'Short keyboard patterns': 'Des petits déplacement sur le clavier', + 'Use a longer keyboard pattern with more turn': 'Utiliser un plus long schéma sur le clavier avec plus de virages', + 'Repeats like': 'Les répétitions telles que', + 'are only slightly harder to guess than': 'sont a peine plus difficile à deviner que', + 'Sequences like': 'Les sequences telles que', + '<or>': 'ou', + 'Avoid repeated words and characters': 'Éviter les répétitions de mots ou caractères', + 'Avoid': 'Éviter', + 'recent years': 'les années récentes', + 'years that are associated with you': 'les années qui ont quelque chose à voir avec vous', + 'Dates are often easy to guess': 'Les dates sont souvent faciles à deviner', + 'dates': 'les dates', + 'This is a top-(.*) common password': 'Ce mot de passe est dans le top \g<1> des plus utilisés', + 'This is a very common passowrd': 'Ce mot de passe est très utilisé', + 'A word by itself is easy to guess': 'Un mot seul est facile à deviner', + 'Names and surnames by themselves': 'Les noms et noms de familles seuls', + 'Common names and surnames': 'Les noms et noms de familles courants', + "Capitalization doesn't help very much": "Mettre en majuscule n'aide pas tant que ça", + 'All-uppercase is almost as easy to guess as all-lowercase': + 'Les mots en majuscules sont aussi simple à deviner que ceux en minuscules', + "Reversed words aren't much harder to guess": 'Les mots inversés ne sont pas beaucoup plus dur à deviner', + +} + + +def tr(text): + try: + return translations[text] + except: + # Todo use regex + for pattern, sub in substitutions.items(): + text = re.sub(pattern, sub, text) + return text