Soy relativamente nuevo con Python y estoy haciendo un programa donde recibimos una cadena de 3 letras con una letra mayúscula, una letra minúscula y un número en cualquier orden. Se supone que el programa lo encontrará a través de un ataque de fuerza bruta.

He intentado hacer esto para bucles y definir las letras mayúsculas y minúsculas y las letras como cadenas y luego intentar iterar a través de ellas para bucles for y tratar de hacer coincidir las letras de la cadena que queríamos encontrar con las letras mayúsculas y minúsculas o números en consecuencia.

Lo que intenté hacer:

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))

Cuando ejecuto el código, funciona, pero solo cuando la cadena secret está en un orden diferente al de mayúsculas, minúsculas y números ("Je1" funciona, "eJ1" no). El programa realmente no hace su función correctamente sin reorganizar los bucles for en consecuencia.

¡Cualquier ayuda es muy apreciada!

0
Yago Tobio 6 oct. 2019 a las 09:40

4 respuestas

La mejor respuesta

Su código muy específicamente siempre genera mayúsculas, minúsculas y números exactamente en este orden, independientemente de la entrada.

Esto es posible de solucionar de varias maneras, cada una con algunas compensaciones.

Lo más simple es hacer fuerza bruta, es decir, examinar los tres conjuntos en cada posición.

Como optimización, puede eliminar la categoría en la que encontró una coincidencia de las iteraciones posteriores, reduciendo el espacio de búsqueda a medida que avanza. Es poco probable que esto sea escalable a problemas del mundo real, donde el espacio de búsqueda es más complejo (no sabe si habrá una o más apariciones de caracteres en cualquier categoría, excepto si una categoría aún no ha sido certificada por cerca de El final de la cadena).

Alternativamente, puede recordar en qué posición encontró un personaje en una categoría particular y volver a armar la contraseña en el orden correcto al final con esta información. En cierto sentido, esta es la solución más elegante, pero nuevamente, tiene el problema de que no será muy útil en un programa de descifrado de contraseñas del mundo real.

En otras palabras, la solución de "fuerza bruta completa" es la más escalable, ya que escalará a problemas del mundo real, a pesar de que es computacionalmente la menos escalable.

En el futuro, piense en cómo podría enumerar todas las contraseñas posibles en el espacio de búsqueda, para que cada candidato de contraseña obtenga un índice predecible, y simplemente repita esa enumeración.

2
tripleee 6 oct. 2019 a las 08:14

Una manera fácil de lograr esto en Python es usar itertools.permutations . Esto le brinda todas las combinaciones posibles de una determinada colección de artículos.

En su caso, la "colección de elementos" son todas las letras minúsculas, mayúsculas y números. Por lo tanto, para usar permutations, debes juntarlos en una sola colección. Para esto, solo puede concatenar las cadenas juntas:

chars = uppers + lowers + numbers

O simplemente definirlas como una cadena:

chars = "ABCDEFGHIJabcdefghij1234567890"

Luego puede ejecutar permutations(chars, 3) que le da elementos de 3 caracteres de longitud como una tupla. Un ejemplo sería ('a', 'C', '3'). Necesita comparar esto con la cadena de contraseña. Puede dividir la cadena de contraseña en una tupla (que debe hacerse una vez) o unir la tupla de permutación en una cadena (que debe hacerse para cada elemento). En su caso, supongo que desea usar la contraseña generada para algo, así que unamos la tupla en una cadena, que nos da el siguiente código:

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)
1
exhuma 6 oct. 2019 a las 07:56

El siguiente programa es ligeramente ineficiente pero funciona para su propósito.

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"

Que se puede modificar aún más utilizando positive lookaheads como se menciona en la respuesta aceptada de Match regex en cualquier pedido

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

Está haciendo un bucle en el orden superior, inferior, número, por lo que solo puede hacer coincidir las cadenas que están en ese orden específico. Necesita hacer un bucle en todas las permutaciones posibles de número superior, inferior. Es decir, debe repetir lo que hizo para estas permutaciones:

Superior, número, inferior
inferior, superior, número
inferior, número, superior
número, inferior, superior
número, superior, inferior

Puedes acortar tus tres bucles de esta manera:

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

Repita esto cinco veces más cambiando el orden del número superior, inferior,.

O bien, puede usar el paquete itertools para evitar tener que repetir tantas veces.

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)
0
ba_ul 6 oct. 2019 a las 07:29
58254855