Python: генератор списка паролей для перебора (brute-force).
При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы ;-) ) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая «примеряла» их к чему-надо. К чему — дело третье и сейчас нас (вернее Вас) не волнует. В результате получился скромный класс, который приведён ниже со столь же скромными моими комментариями к нему :-).
Сам класс для перебора паролей ко всему и вся таков:
# -*- coding: utf-8 -*-
EN = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
en = "abcdefghijklmnopqrstuvwxyz"
RU = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
ru = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
digits = "1234567890"
space = " "
p = ",.-!?;:'\"/()"
op = "+-*/:^()<>="
all_spec = "`~!@#$%^&*-_=+\\|/?.>,< '\";:[]{}"
class ABCIterator:
firstuse_flag = True
stop = None
def __init__(self, start="", stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec):
assert len(abc) > 0
if start_len is not None:
assert start_len > 0
#assert start == ""
self.current_str = list(abc[0]*start_len)
else:
self.current_str = list(filter(lambda x: x in abc, start))
if stop_len is not None:
assert (start_len is None) or (start_len <= stop_len)
assert stop_len > 0
self.stop = list(abc[0]*(stop_len+1)) # т.к. итератор работает с полуотрезками
else:
if stop is not None: self.stop = list(filter(lambda x: x in abc, stop))
self.abc = list(abc)
def __iter__(self):
return self
def next(self):
if (self.stop is not None) and (self.stop == self.current_str):
raise StopIteration
if self.current_str == []:
self.current_str.append(self.abc[0])
self.firstuse_flag = False
return self.abc[0]
elif self.firstuse_flag:
self.firstuse_flag = False
return "".join(self.current_str)
offset = 0
while offset < len(self.current_str):
if self.current_str[offset] != self.abc[-1]:
self.current_str[offset] = self.abc[self.abc.index(self.current_str[offset])+1]
# выпендрёшь для полуотрезка
if (self.stop is not None) and (self.current_str == self.stop):
raise StopIteration
return "".join(self.current_str)
self.current_str[offset] = self.abc[0]
offset += 1
self.current_str = [self.abc[0]] + self.current_str
# опять же оно же
if (self.stop is not None) and (self.current_str == self.stop):
raise StopIteration
return "".join(self.current_str)
А таковы мои пояснения к нему:
- firstuse_flag — свойство, которое указывает на то, что итератор используется впервые и не стоит производить итерацию, надо лишь вернуть текущее значени строки. Это нужно для того, чтобы в цикле не «съедалось» первое значение (напр., инициализировали итератор с начальной строкой «aaa», а при 1й же итерации он вернул бы, без этого чудесного свойства, «baa»)
- stop — указывает на значение, на котором пора бы уже остановиться и вызвать исключение StopIteration. Если не задано (имеет значение None), то не пора, итератор будет бесконечным
- __init__(start=», stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec, **kwargs) — в общем то сам конструктор. start — начальное значение, stop — конечное, если не задано или идёт до начального, то итерации происходят бесконечно. Можно так же задать начальную и конечную длину, место конкретных значений с помощью start_len и stop_len. Если задана длина и начальные значения, то приоритет будет иметь длина, что можно легко исправить, если для кого-то это критично. abc — алфавит, над которым будут производиться итерации.
- __iter__() — необходимо для того чтобы класс был полноценным итератором.
- next() — возвращает следующую строку, в общем-то этот метод так же необходим для того чтобы класс был итератором.
Пример использования:
>>> for i in ABCIterator(start_len=1, stop_len=3, abc="abc"): ... i ... 'a' 'b' [...] 'bcc' 'ccc' >>>
Ну, как-то так оно и работает. Если кому-то что-то непонятно, то могу объяснить подробнее. В общем как обычно, всё в комменты ;-). Неплохо было бы ещё реализовать преобразование чисел в строки и наоборот, но это позже… может быть.


А какую программу использовать куда чё ???
Это программа, а класс для программистов. Хотите его использовать — учитесь программировать, нужна программа — готов обсудить условия ;).
assert len(abc) > 0 не пойму как здесь должени реашировать py? объясни
@Роман
Если длина меньше или равна 0 — программа вызовет исключение (AssertionError) и завершит работу, если это исключение не ловится нигде выше.
а зачем велосипед, если есть itertools.product — http://docs.python.org/library/itertools.html#itertools.product
@laqie
Скорее от незнания. :) Писалось когда только начинал изучать питон, но есть вероятность что тогда и не было питона 2.6.
Спасибо за линк, может кому-то пригодится.