Пароль крекинг, комментируя в Python


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

import time 
import string

#Variables
max_attempts = 999999999 #the number of attempts the system makes for a brute-force attack
start       = time.time() #monitors the time length
chars       = list(string.printable) #all the possible ascii characters which the system uses to determine the password
base        = len(chars) #the base for conversion
n           = 0 #number of attempts
solved      = False
password    = input("Enter your password:") #the feature which allows the user to enter in their chosen password

print(chars) #record of previous password attempts

# converts number N base 10 to a list of digits base b
def numberToBase(n, b):
    digits = []
    while n: # takes n and the finds the modulus, the remainder of n % b
        digits.append(int(n % b)) # then it will append that to a list
        n //= b # following on it will then divide n into b
    return digits[::-1] #returns those digits into reverse order from -1, the end to the beginning


# checks if the user has inputted empty text/numbers/symbols
if password == '':

    print('Your password is empty')
    solved = True

elif password == chars[n]:
    print('Your password is ' + chars[n])
    solved = True

else:
    n = 1

#Begins systematically checking the password
if not solved:
    while n < max_attempts:
        list = numberToBase(n, base)
        print(list)
        word = ''
        for c in list: #loop through each of the characters in the list
            word += str(chars[c]) #adds the characters from the list to a word
        print(word)
        if password == word: #checks if the password equals to the word the system has generated
            solved = True # if the generation is correct the password will then commence to print statements
            print('***Results***')
            print('Password: ' + word)
            print('Attempts: ' + str(n))
            print('Time: ' + str((time.time() - start)) + ' sec') 
            break #stops the loop
        else:
            n += 1 #however if the password generation isn't correct, we increment with n

# the password is beyond max_attempts
if not solved:
    print('Unsolved after ' + str(n) + ' attempts!')


430
0
задан 31 января 2018 в 10:01 Источник Поделиться
Комментарии
2 ответа

1. Цель комментариях

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

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


  1. У функции есть документация, объясняя свои доводы и результаты? (В Python, есть ли у них комментарии?)

  2. Есть ли тестовые случаи (или примеры документации), демонстрирующих правильное поведение кода?

  3. Сделать имена функций четко описать, что они делают? И сделать имена переменных, явно указывают на смысл их значения?

  4. Это код, написанный в простой, ясный способ?

Только если ответы все "да", а код до сих пор не понятно, как вы считаете стоит писать комментарий.

2. Пример

Давайте возьмем numberToBase функции и задать эти вопросы:

# converts number N base 10 to a list of digits base b
def numberToBase(n, b):
digits = []
while n: # takes n and the finds the modulus, the remainder of n % b
digits.append(int(n % b)) # then it will append that to a list
n //= b # following on it will then divide n into b
return digits[::-1] #returns those digits into reverse order from -1, the end to the beginning


  1. Нет никакой документации. Давайте откроем первый комментарий в строкой документации:

    def numberToBase(n, b):
    """Convert the number n to base b and return a list of digits."""
    digits = []
    while n:
    digits.append(int(n % b))
    n //= b
    return digits[::-1]

  2. Нет примеров. Давайте добавим:

    def numberToBase(n, b):
    """Convert the number n to base b and return a list of digits.

    >>> numberToBase(1234, 10)
    [1, 2, 3, 4]
    >>> numberToBase(1023, 2)
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

    """
    digits = []
    while n:
    digits.append(int(n % b))
    n //= b
    return digits[::-1]

    Это в виде doctests , так что они могут быть автоматически проверены с помощью doctest модуль.


  3. Есть куча улучшений, мы можем сделать с именами. (я) что-то вроде number_to_digits будет понятнее, чем numberToBase поскольку результатом является список цифр. (II) в base будет понятнее, чем b. (III) это встроенная функция divmod хотел дать понять, что мы вычисления деление и модуль. (IV) имя digit для модуля сделает ее более понятной. (V) использование встроенных функций list и reversed хотел дать понять, что мы вычисляем список в обратном порядке.

    def number_to_digits(n, base):
    """Convert the number n to a list of digits in the given base.

    >>> number_to_digits(1234, 10)
    [1, 2, 3, 4]
    >>> number_to_digits(1023, 2)
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

    """
    digits = []
    while n:
    n, digit = divmod(n, base)
    digits.append(digit)
    return list(reversed(digits))


  4. Код, кажется, теперь ясный и простой: нет необходимости добавлять какие-либо комментарии.

3. Других точек обзора


  1. Когда n это 0результатом является пустой список. Может быть, лучше вернуться в список [0].

  2. Когда b это 1функция переходит в бесконечный цикл. Это может быть лучше, чтобы поднять исключение в этом случае.

5
ответ дан 31 января 2018 в 10:01 Источник Поделиться

О комментировании и читабельность

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

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

Вы определили numberToBase() функция, которая является хорошей. Но она утопает в море свободно плавающий код, а это плохо.

Вы начали с определения 7 переменных, которые потенциально могут быть использованы и изменены в любом месте в вашей программе. Что делает ваш код трудно понять. nв частности, им будет лучше attemptsкак для того, чтобы устранить необходимость в комментариях и чтобы избежать путаницы с n в numberToBase(n, b).

Бенчмаркинг

Что именно ты измеряешь? Если пользователь занимает много времени, чтобы ответить на запрос, вы действительно хотите, чтобы быть включенными в прошедшее время?

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

Вот один такой комментарий, который бы на самом деле полезным для будущих сопровождающих ваш код:

# Disabled printing, because the cracking would go much slower!
# print(word)

Предлагаемое решение

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

"""
Brute-force password-cracking demonstration.
"""

import string
from time import time

def nth_possible_word(n, chars=string.printable):
"""
Generate the nth possible string composed of the given characters,
in order of increasing length. (By default, use the printable ASCII
characters.)

>>> nth_possible_word(0, chars='abc')
''
>>> nth_possible_word(1, chars='abc')
'a'
>>> [nth_possible_word(n, chars='ab') for n in range(10)]
['', 'a', 'b', 'aa', 'ab', 'ba', 'bb', 'aaa', 'aab', 'aba']
"""
word = ''
while n:
n -= 1
word += chars[n % len(chars)]
n //= len(chars)
return word[::-1]

def crack(password, max_attempts=10**9):
"""
Try all possible strings of increasing length until one of them matches
the given password, or max_attempts strings have been tried. Return a
tuple (word, n), where word is the password that was found (or None if
the password was not found), and n is the number of attempts made.

>>> crack('a')
('a', 12)
>>> crack('xyz')
('xyz', 343537)
>>> crack('xyz', 343537)
('xyz', 343537)
>>> crack('xyz', 343536)
(None, 343536)
"""
for attempt in range(max_attempts):
word = nth_possible_word(attempt)
# Disabled printing, because the cracking would go much slower!
# print(word)
if password == word:
return word, attempt + 1
return None, attempt + 1

def main():
password = input("Enter your password: ")
# print(string.printable)

start_time = time()
word, attempts = crack(password)
elapsed_secs = time() - start_time

if word is None:
print('Unsolved after {0} attempts!'.format(attempts))
elif word == '':
print('Your password is empty')
else:
print("""***Results***
Password: {0}
Attempts: {1}
Time: {2} sec""".format(word, attempts, elapsed_secs))

if __name__ == '__main__':
main()

Замечания:


  • В main() функция является относительно коротким. Вы можете получить ощущение того, что эта программа делает, глядя на него, не теряясь в деталях. В частности, все ввода/вывода происходит в main(); все "расчеты" происходит внутри других функций.

  • Код в nth_possible_word() и crack() функций может быть трудно для новичка, чтобы понять, но комментарии уточнить, как ведут себя функции. Вы только посмотрите на реализацию, когда вам нужно.

  • Пустой входной сигнал рассматривается как особый случай только для отчетности (чтобы повторить свой выходной). Для целей взлома, пароль нулевой длины не все, что особенное.

    Кстати, Ваш elif password == chars[n]: особый случай был довольно бессмысленным. Она будет только активизироваться, если пароль '0'.


Альтернативное решение

В некотором смысле, ваш numberToBase() метод-это способ перебора всех возможных паролей, чтобы попробовать. С помощью какой-либо Python-функции, такие как itertools и yield), вы можете перебрать все возможные строки более выразительно. Если вы замените nth_possible_word() и crack() функции в программе выше с двух функций, указанных ниже, то программа будет вести себя так же.

from itertools import count, islice, product

def passwords_to_try(chars=string.printable):
"""
Generate an infinite sequence of all possible strings composed of the
given characters, in order of increasing length. (By default, the
strings consist of printable ASCII characters.)

>>> p = passwords_to_try()
>>> next(p)
''
>>> next(p)
'0'
>>> next(p)
'1'
"""
for length in count():
for characters in product(chars, repeat=length):
yield ''.join(characters)

def crack(password, max_attempts=10**9):
"""
Try all possible strings of increasing length until one of them matches
the given password, or max_attempts strings have been tried. Return a
tuple (word, n), where word is the password that was found (or None if
the password was not found), and n is the number of attempts made.

>>> crack('a')
('a', 12)
>>> crack('xyz')
('xyz', 343537)
>>> crack('xyz', 343537)
('xyz', 343537)
>>> crack('xyz', 343536)
(None, 343536)
"""
for n, word in enumerate(islice(passwords_to_try(), max_attempts), 1):
# Disabled printing, because the cracking would go much slower!
# print(word)
if password == word:
return word, n
return None, n

4
ответ дан 1 февраля 2018 в 12:02 Источник Поделиться