0
votes

Devinez une chaîne de 3 lettres contenant une majuscule, une minuscule et un nombre (dans n'importe quel ordre)

Je suis relativement nouveau avec Python et je crée un programme où nous recevons une chaîne de 3 lettres avec une lettre majuscule, une lettre minuscule et un nombre dans un ordre donné. Le programme est alors censé le trouver grâce à une attaque par force brute.

J'ai essayé de faire cela à travers des boucles for et de définir les lettres majuscules, minuscules et les lettres comme des chaînes, puis d'essayer de les parcourir avec des boucles for et d'essayer pour faire correspondre les lettres de la chaîne que nous voulions trouver à celles entre les majuscules, les minuscules ou les nombres en conséquence.

Ce que j'ai essayé de faire:

uppers="ABCDEFGHIJ"
lowers="abcdefghij"
numbers="1234567890"
secret="Je1" #The string the computer is supposed to find through a brute-force attack 

password = ""
counter = 0

for upper in uppers:
    if upper in secret:
        password += upper
        break
    else:
        counter += 1

for lower in lowers:
    if lower in secret:
        password += lower
        break
    else:
        counter += 1

for number in numbers:
    if number in secret:
        password += number
        break
    else:
        counter += 1

print(password)
print("Counter: {0}".format(counter))

Lorsque j'exécute le code, cela fonctionne, mais uniquement lorsque la chaîne secret est dans un ordre différent de celui des majuscules, des minuscules et des nombres ("Je1" fonctionne, "eJ1" ne le fait pas). Le programme ne fait pas vraiment sa fonction correctement sans réorganiser les boucles for en conséquence.

Toute aide est très appréciée!


2 commentaires

Copie possible de stackoverflow.com/questions/18944909/match- regex-in-any-orde‌ r


Votre approche repose simplement sur le fait que les chiffres sont dans cet ordre, comme vous l'avez découvert vous-même. Vous devrez ajuster cela en conséquence. Comme suggestion et pour ne pas gâcher vos devoirs, essayez de décrire d'abord l'algorithme à un humain et voyez si cela donne les bons résultats. Aussi, très utile, parcourez le code dans un débogueur afin de trouver l'endroit où le programme ne se comporte pas comme prévu.


4 Réponses :


0
votes

Le programme suivant est légèrement inefficace mais fonctionne pour votre objectif.

if re.search(r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{3}$", secret):
    print "Yes"
else:
    print "No"

Qui peut être modifié ultérieurement en utilisant des anticipations positives comme mentionné dans la réponse acceptée de Faites correspondre les expressions régulières dans n'importe quel ordre

import re
def m(secret):
    import re
    if len(secret)==3 and re.search(r'[A-Z]', secret) and re.search(r'[a-z]', secret) and re.search(r'[0-9]', secret):
        print "Yes"
    else:
        print "No"

p >


1 commentaires

Cela n'effectue pas d'attaque de devinette par force brute, cela vérifie simplement que la chaîne répond aux critères. (Pour être honnête, je pensais que c'était aussi la question au début; j'espère que c'est plus clair maintenant.)



0
votes

Vous bouclez dans l'ordre supérieur, inférieur, nombre, vous ne pouvez donc faire correspondre que les chaînes qui sont dans cet ordre spécifique. Vous devez boucler toutes les permutations possibles de nombre supérieur, inférieur. Autrement dit, vous devez répéter ce que vous avez fait pour ces permutations:

supérieur, nombre, inférieur
inférieur, supérieur, nombre
inférieur, nombre, supérieur
nombre, inférieur, supérieur
nombre, supérieur, inférieur

Vous pouvez raccourcir vos trois boucles de cette façon:

from itertools import permutations

for upper in uppers:
    for lower in lowers:
        for number in numbers:
            perms = list(permutations([upper, lower, number]))
            if tuple(secret) in perms:
                print('Matched. Secret is', secret)

Répétez cette opération cinq fois de plus en changeant l'ordre supérieur, inférieur, nombre.

Ou, vous pouvez utiliser le package itertools pour éviter d'avoir à boucler autant de fois.

for upper in uppers:
    for lower in lowers:
        for number in numbers:
            password = upper + lower + number
            if password == secret:
                print('Matched. Secret is', secret)


0 commentaires

2
votes

Votre code génère très spécifiquement toujours la majuscule, les minuscules et le nombre dans cette commande, quelle que soit la saisie de l'entrée.

Ceci est possible de résoudre de plusieurs manières, chacun avec des compromis.

Le plus simple est de vraiment faire une force brute, c'est-à-dire examiner les trois ensembles à chaque position.

En optimisation, vous pouvez déposer la catégorie que vous avez trouvée une correspondance dans les itérations suivantes, ce qui réduit l'espace de recherche à votre guise. Il est peu probable qu'il soit peu susceptible d'être évolutif pour les problèmes du monde réel, où l'espace de recherche est plus complexe (vous ne savez pas s'il y aura une ou plusieurs occurrences de caractères dans une catégorie d'une seule catégorie, sauf si une catégorie n'est pas encore attestée pour près de la fin de la chaîne).

Alternativement, vous pouvez vous souvenir de quelle position vous avez trouvée un caractère dans une catégorie particulière et remonte au mot de passe dans le bon ordre à la fin avec ces informations. En quelque sorte, c'est la solution la plus élégante, mais encore une fois, elle souffre du problème que cela ne sera pas très utile dans un programme de craquage du mot de passe réel.

Ainsi, en d'autres termes, la solution "pleine force brute" est la plus évolutive, car elle augmentera les problèmes du monde réel, même s'il est calculé le moins évolutif.

À l'avenir, réfléchissez à la manière dont vous pourriez énumérer tous les mots de passe possibles dans l'espace de recherche, de sorte que chaque candidat de mot de passe obtient un indice prévisible, et simplement une boucle sur cette énumération.


0 commentaires

1
votes

Un moyen simple d'y parvenir en Python consiste à utiliser itertools.permutations . Cela vous donne toutes les combinaisons possibles à partir d'une collection d'éléments donnée.

Dans votre cas, la "collection d'éléments" comprend toutes les lettres minuscules, les lettres majuscules et les chiffres. Donc, pour utiliser les permutations , vous devez les rassembler en une seule collection. Pour cela, vous pouvez simplement concaténer les chaînes ensemble:

from itertools import permutations

uppers="ABCDEFGHIJ"
lowers="abcdefghij"
numbers="1234567890"

secret="Je1"

for candidate in permutations(uppers + lowers + numbers, 3):
    if ''.join(candidate) == secret:
        print(candidate)

Ou simplement les définir comme une chaîne:

chars = "ABCDEFGHIJabcdefghij1234567890"

Vous pouvez puis exécutez permutations (chars, 3) qui vous donne des éléments de 3 caractères de longueur sous forme de tuple. Un exemple serait ('a', 'C', '3') . Vous devez comparer cela avec la chaîne de mot de passe. Vous pouvez soit diviser la chaîne de mot de passe en un tuple (ce qui doit être fait une fois), soit joindre le tuple de permutation en une chaîne (ce qui doit être fait pour chaque élément). Dans votre cas, je suppose que vous souhaitez utiliser le mot de passe généré pour quelque chose, alors joignons le tuple dans une chaîne, ce qui nous donne le code suivant:

chars = uppers + lowers + numbers


0 commentaires