Угадайте трехбуквенную строку, которая содержит прописные, строчные и цифры (в любом порядке) - PullRequest
0 голосов
/ 06 октября 2019

Я относительно новичок в Python и создаю программу, в которой мы получаем трехбуквенную строку с одной заглавной буквой, одной строчной буквой и числом в любом заданном порядке. Затем программа должна найти его с помощью атаки методом грубой силы.

Я попытался сделать это для циклов и определения прописных, строчных букв и букв в виде строк, а затем попытаться выполнить их с помощью forциклы и попробуйте сопоставить буквы из строки, которую мы хотели найти, с прописными, строчными или цифрами соответственно.

Что я пытался сделать:

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

Когда я запускаюкод, это работает, но только когда строка secret имеет другой порядок, чем прописные, строчные и цифры («Je1» работает, «eJ1» - нет). Программа на самом деле не выполняет свою функцию должным образом без соответствующей перестановки циклов for.

Любая помощь высоко ценится!

Ответы [ 4 ]

2 голосов
/ 06 октября 2019

Ваш код очень точно всегда выводит прописные, строчные буквы и числа именно в этом порядке, независимо от того, какой ввод был.

Это можно исправить несколькими способами, каждый с некоторыми компромиссами.

Самое простое - это действительно применить грубую силу, то есть изучить все три набора в каждой позиции.

В качестве оптимизации вы можете исключить категорию, в которой вы нашли совпадение, из последующих итераций, уменьшив пространство поиска какВаш ход. Это вряд ли будет масштабируемым для реальных проблем, где пространство поиска является более сложным (вы не знаете, будет ли одно или несколько вхождений символов в какой-либо одной категории, за исключением того, что одна категория еще не засвидетельствована для ближайшегоконец строки).

Кроме того, вы можете вспомнить, в какой позиции вы нашли символ в определенной категории, и заново собрать пароль в правильном порядке в конце с этой информацией. В некотором смысле это самое элегантное исправление, но, опять же, оно страдает от проблемы, заключающейся в том, что оно не будет очень полезным в реальной программе взлома паролей.

Другими словами, «полныйРешение "грубой силы" является наиболее масштабируемым, поскольку оно будет масштабироваться до реальных проблем, даже если оно вычислительно наименее масштабируемое.

В дальнейшем подумайте, как можно перечислить все возможные пароли в поиске. пробел, чтобы каждый кандидат на пароль получил предсказуемый индекс и просто перебрал это перечисление.

1 голос
/ 06 октября 2019

Простой способ сделать это в Python - использовать itertools.permutations . Это дает вам все возможные комбинации из данной коллекции предметов.

В вашем случае «коллекция предметов» - это все строчные буквы, прописные буквы и цифры. Поэтому, чтобы использовать permutations, вам нужно собрать их в одну коллекцию. Для этого вы можете просто объединить строки:

chars = uppers + lowers + numbers

Или просто определить их как одну строку:

chars = "ABCDEFGHIJabcdefghij1234567890"

Затем вы можете запустить permutations(chars, 3), который даст вам элементы из 3 символовв длину как кортеж. Одним из примеров будет ('a', 'C', '3'). Вам нужно сравнить это со строкой пароля. Вы можете либо разбить строку пароля на кортеж (что необходимо сделать один раз), либо соединить кортеж перестановки в строку (что необходимо сделать для каждого элемента). В вашем случае я предполагаю, что вы хотите использовать сгенерированный пароль для чего-то, поэтому давайте объединим кортеж в строку, что даст нам следующий код:

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)
0 голосов
/ 06 октября 2019

Вы выполняете цикл в верхнем, нижнем порядке, поэтому вы можете сопоставлять только те строки, которые находятся в определенном порядке. Вы должны зациклить все возможные перестановки верхнего, нижнего числа. То есть вам нужно повторить то, что вы сделали для этих перестановок:

верхний, число, нижнее
нижнее, верхнее, число
нижнее, число, верхнее
число, нижнее, верхнее
число, верхнее, нижнее

Вы можете сократить три цикла следующим образом:

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

Повторите это еще пять раз, изменив порядок верхнего, нижнего числа.

Или вы можете использовать пакет itertools, чтобы избежать многократного зацикливания.

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 голосов
/ 06 октября 2019

Следующая программа немного неэффективна, но работает для вашей цели.

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"

Который может быть дополнительно изменен с использованием positive lookaheads, как указано в принятом ответе Соответствует регулярному выражению в любом порядке

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