2017-07-25 65 views
0

我已经成功完成并通过了一个项目,我正在创建所有可能的4字母密码组合来破解DES散列。当我找到一场比赛时,它应该立即返回,但我知道我的功能设计不佳。我了解基本的递归,但我一直无法理解它的任何有用的目的。在这种情况下,我发现唯一可以使方法返回的方法是通过检查封装函数中初始化的密码变量以及nonlocal属性。在递归调用中返回故障

在我来到我的最终解决方案之前,我曾经在没有非本地的情况下工作,但它会持续一段时间,即使在找到时正确输出密码也不会返回任何内容。

如何正确使用递归通过正确传播值来返回正确的密码?感谢您提供任何帮助或提示!

def brute_force_crack(hashed_pass): 
    char_list = create_possible_chars() 

    # Store all string combinations 
    password = "" 

    # Build the combos adding each letter to each prefix and then to combos. 
    def build_combos(curr_str): 

     nonlocal password 

     # Check password to return early 
     if password != "": 
      return 
     if len(curr_str) == 4: 
      return 

     for letter in char_list: 
      # Add letter to curr_str to build up the combo 
      curr_str += letter 

      if is_password(curr_str, hashed_pass): 
       password = curr_str 
       break 

      build_combos(curr_str) 
      # Reset curr_str to be used again in this iteration without the added letter 
      curr_str = curr_str[:-1] 

    build_combos("") 
    return password 
+0

“我有这个工作,而不外地之前,我来到了我的最终解决方案” 愿我们看到以前的版本吗?非本地使用可能是朝着错误方向迈出的一步。 – Floegipoky

+0

感谢您的评论。唯一的区别是原来没有最初检查密码,并且在循环内我试图返回curr_str而不是循环。不幸的是,我只能从那里打印,因为return语句无处可传。 – razzdango

回答

1

你的目标应该让递归函数回报正确的密码的时候发现,而不是设置一个非本地变量。

其次,在递归函数开始时执行密码检查,同时检查失败。这可能似乎第一次矫枉过正(因为空字符串不匹配),但它是更干净的代码。

这里是如何可能看起来:

def brute_force_crack(hashed_pass): 
    char_list = create_possible_chars() 

    # Build the combos adding each letter to each prefix and then to combos. 
    def build_combos(curr_str): 
     # Check for success 
     if is_password(curr_str, hashed_pass): 
      # Return the match 
      return curr_str 
     # Check for failure 
     if len(curr_str) >= 4: 
      return 

     for letter in char_list: 
      # Add letter via argument to build up the combo 
      password = build_combos(curr_str + letter) 
      # If a result is returned, we can quit 
      if password: 
       return password 

    # Return whatever is returned recursively 
    return build_combos("") 
+0

这对我来说更有意义。我完全可以看到如何将返回值传播到原始呼叫。我也看到我的字符串切片是多么不必要。感谢您的帮助 - 非常感谢! – razzdango

1

只要确保找到正确的答案,就可以返回。通过你的函数的每一条路径都应该返回一些东西,无论是正确的密码还是一个指示失败的标记值(例如None)。看看下面的对你有意义:

import string 

def create_possible_chars(): 
    return string.ascii_lowercase 

# Dummy implementation, check for the password reversed 
def is_password(curr_str, hashed_pass): 
    return ''.join(reversed(curr_str)) == hashed_pass 

def brute_force_crack(hashed_pass): 
    char_list = create_possible_chars() 

    def build_combos(curr_str=""): 
     # Base case: already at four characters, give up 
     if len(curr_str) == 4: 
      return None 

     for letter in char_list: 
      # Try adding this letter 
      guess = curr_str + letter 

      if is_password(guess, hashed_pass): 
       # If this is the password, return it 
       return guess 
      else: 
       # Recurse 
       result = build_combos(guess) 

       # If we found the password, return it 
       if result is not None: 
        return result 

     # We failed to find the psasword 
     return None 

    return build_combos() 

print(brute_force_crack("beef")) # feeb 
+0

感谢您的帮助@smarx! – razzdango