Рейтинг@Mail.ru

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

Ну, как-то так оно и работает. Если кому-то что-то непонятно, то могу объяснить подробнее. В общем как обычно, всё в комменты ;-). Неплохо было бы ещё реализовать преобразование чисел в строки и наоборот, но это позже… может быть.

прикладное, Программирование ,

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1 звезда2 звезды3 звезды4 звезды5 звёзд (7 голосов, средний: 5,00 из 5)
Loading ... Loading ...

  1. Лёха
    27 Февраль 2010 в 16:06 | #1

    А какую программу использовать куда чё ???

  2. 2 Март 2010 в 11:18 | #2

    Это программа, а класс для программистов. Хотите его использовать — учитесь программировать, нужна программа — готов обсудить условия ;).

  3. Роман
    5 Март 2011 в 12:45 | #3

    assert len(abc) > 0 не пойму как здесь должени реашировать py? объясни

  4. 14 Март 2011 в 21:14 | #4

    @Роман
    Если длина меньше или равна 0 — программа вызовет исключение (AssertionError) и завершит работу, если это исключение не ловится нигде выше.

  5. laqie
    22 Апрель 2011 в 21:05 | #5

    а зачем велосипед, если есть itertools.product — http://docs.python.org/library/itertools.html#itertools.product

  6. 18 Май 2011 в 17:52 | #6

    @laqie
    Скорее от незнания. :) Писалось когда только начинал изучать питон, но есть вероятность что тогда и не было питона 2.6.

    Спасибо за линк, может кому-то пригодится.

  1. Пока что нет уведомлений.
*