2017-07-25 49 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