2010-07-09 23 views
9

我不是超出了我讀過維基百科上的果然是高手語言的臀部。轉換萊特的口吻明文

我確實需要添加一個字典檢查到我們的密碼強度驗證工具,並且由於leet-speak只會在密碼破解過程中增加微不足道的開銷,所以我想在檢查之前檢查輸入它反對字典。

爲了澄清這背後的原因:當需要符號添加到他們的密碼很多用戶會簡單地做一個共同的詞了一些非常可預測萊特替換,以滿足數字和符號包含的要求。因爲它是如此可預測的,所以這增加了密碼的實際複雜度,而不是僅僅使用原始字典單詞。 \編輯

不知道所有的規則,尤其是多字符替換,如「//」爲「W」,並且是一定的,這是已經解決了許多倍的開源項目,當然包括了問題。

我正在尋找代碼示例,但目前還沒有找到任何代碼示例。如果它是C#代碼將是一個獎金!,但在任何共同語言的代碼將有所幫助。

另外,如果我有一個可擴展的方法,那就太好了,因爲我知道這個方言很快會演變。隨着這些進展的發展,能夠在一年內加入一些規則將會很好。

不,這不是我整個密碼強度檢查的基礎。這只是我在這篇文章中尋求幫助的部分。因此,我們不會被其他密碼和安全問題的因素分心,讓我描述一下密碼問題,這些問題不需要與leet-speak相關:

我們測量密碼中的熵位數NIST special publication 800-63,並要求一個策略可配置的等效措施(例如56位),以使密碼有效。這仍然留下了字典單詞的空間,這些單詞已經被簡單地用詞表示,並且從熵的角度來看並不是一個更好的普通字典單詞。

我只是想告訴用戶「P @ s5w0rd」太靠近一個字典中的單詞,他們可能會找到一個強密碼。

我知道還有很多安全考慮因素,比如人類可以記住的密碼和安全的密碼之間的平衡。這不是那個問題。

我所要求的就是轉換的l33t以明文這應該是幾乎一樣好玩有趣的話題作爲代碼高爾夫球。有沒有人看過任何代碼示例?

+1

我已經把一個稍微複雜的答案,即解決了XKCD 「Tr0ub4dor&3」 的密碼。 – 2015-06-25 15:14:23

回答

9

還提供了一些代碼:

String password = @"\/\/4573Fu|_"; 
Dictionary<string, string> leetRules = new Dictionary<string, string>(); 

leetRules.Add("4", "A"); 
leetRules.Add(@"/\", "A"); 
leetRules.Add("@", "A"); 
leetRules.Add("^", "A"); 

leetRules.Add("13", "B"); 
leetRules.Add("/3", "B"); 
leetRules.Add("|3", "B"); 
leetRules.Add("8", "B"); 

leetRules.Add("><", "X"); 

leetRules.Add("<", "C"); 
leetRules.Add("(", "C"); 

leetRules.Add("|)", "D"); 
leetRules.Add("|>", "D"); 

leetRules.Add("3", "E"); 

leetRules.Add("6", "G"); 

leetRules.Add("/-/", "H"); 
leetRules.Add("[-]", "H"); 
leetRules.Add("]-[", "H"); 

leetRules.Add("!", "I"); 

leetRules.Add("|_", "L"); 

leetRules.Add("_/", "J"); 
leetRules.Add("_|", "J"); 

leetRules.Add("1", "L"); 

leetRules.Add("0", "O"); 

leetRules.Add("5", "S"); 

leetRules.Add("7", "T"); 

leetRules.Add(@"\/\/", "W"); 
leetRules.Add(@"\/", "V"); 

leetRules.Add("2", "Z"); 

foreach (KeyValuePair<string,string> x in leetRules) 
{ 
    password = password.Replace(x.Key, x.Value); 
} 

MessageBox.Show(password.ToUpper()); 
+0

我認爲地圖leet => unleet會更好,因爲你不必爲每一對輸入leetRules.Add。 – tstenner 2010-07-09 19:52:06

+0

謝謝,這是完美的。可擴展,簡單。這些替換可以放在一個文件中,以使其更具可擴展性。像-xor和-zorz這樣的後綴可以被刪除。除了這個替換密碼,還有沒有更多的東西可用?浪費了?有趣的密碼選擇。 – DanO 2010-07-09 20:01:43

+0

我雖然可能會有更多的語法涉及leet而不僅僅是替代。處理語法是我不關心的CS的一部分。 – DanO 2010-07-09 20:03:22

14

我必須說,我認爲這是一個糟糕的主意......如果你希望他們要堅強,拿出更好的需求..必須至少8個字符,包含大寫和小寫字母,至少包含一個數字,並至少有一個特殊字符。在禁用帳戶之前實施最大授權失敗計數器。一旦完成,你擔心什麼?

+2

+1更好的方向,更相關的安全原則。 – andyortlieb 2010-07-09 17:54:54

+0

不得不說,我同意:)「De-1337-ifying」並不是微不足道的。一個簡單的例子是1337年的'4'=='a',所以,你是否想要禁止所有4個? – cwap 2010-07-09 17:55:14

+0

我想操作系統想要防止像「l33t haxx0r」這樣的密碼,這是非常普通的,可能很常見。它有8個字符,至少一個數字和一個特殊字符,但不安全。 – 2010-07-09 17:58:36

2

你爲什麼不只是實現一個功能,只需創建"pronounceable" passwords並要求用戶使用他們?這似乎少得多的工作和更好的安全性。

+0

這是一個很好的建議和一個有趣的想法,因爲用戶生成的密碼在大多數情況下確實存在固有的問題。但在這種情況下,用戶需要能夠選擇他們自己的密碼,並且我們必須確保它足夠強大。如果他們需要幫助提供密碼,這是一個好主意。 – DanO 2010-07-09 22:40:59

2

我發現這個問題很有意思,所以這裏是一個額外的答案,作爲一個智力練習;由於leet speak不能映射到唯一的單詞,因此必須檢查一個leet speak鏈可以提供的可能的解碼值。這裏是一些示例代碼:

public class LeetSpeakDecoder 
{ 
    private Dictionary<string, IEnumerable<string>> Cache { get; set; } 
    private Dictionary<string, string> Rules { get; set; } 

    public LeetSpeakDecoder() 
    { 
     Cache = new Dictionary<string, IEnumerable<string>>(); 
     Rules = new Dictionary<string,string>(); 

     Rules.Add("4", "A"); 
     // add rules here... 
    } 

    public IEnumerable<string> Decode(string leet) 
    { 
     var list = new List<string>(); 
     if (Cache.ContainsKey(leet)) 
     { 
      return Cache[leet]; 
     } 

     DecodeOneCharacter(leet, list); 
     DecodeMoreThanOneCharacter(leet, list); 
     DecodeWholeWord(leet, list); 

     list = list.Distinct().ToList(); 

     Cache.Add(leet, list); 
     return list; 
    } 

    private void DecodeOneCharacter(string leet, List<string> list) 
    { 
     if (leet.Length == 1) 
     { 
      list.Add(leet); 
     } 
    } 

    private void DecodeMoreThanOneCharacter(string leet, List<string> list) 
    { 
     if (leet.Length > 1) 
     { // we split the word in two parts and check how many variations each part will decode to 
      for (var splitPoint = 1; splitPoint < leet.Length; splitPoint++) 
      { 
       foreach (var leftPartDecoded in Decode(leet.Substring(0, splitPoint))) 
       { 
        foreach (var rightPartDecoded in Decode(leet.Substring(splitPoint))) 
        { 
         list.Add(leftPartDecoded + rightPartDecoded); 
        } 
       } 
      } 
     } 
    } 

    private void DecodeWholeWord(string leet, List<string> list) 
    { 
     if (Rules.ContainsKey(leet)) 
     { 
      list.Add(Rules[leet]); 
     } 
    } 
} 

代碼認爲

  • 一個字符可以被保持爲是(DecodeOneCharacter
  • 一個字必須由解碼值的組合對所有的被解碼(DecodeMoreThanOneCharacter
  • 一個單詞必須直接按規則解碼(DecodeWholeWord

緩存是非常有用的,因爲代碼在跟蹤什麼樣的排列無用時非常低效:將「浪費」分成「w」和「無聊」或「wa」和「steful」將導致解碼的一些重複在右邊,然後在左邊。我沒有太多的數據,但是它經常被超過90%的解碼所擊中;對於一個小小的添加來說不算太破舊。

由於它返回了所有可能的解碼字符串的組合,所以您可能需要查看它的解決方案:例如Fosco的代碼將「137M3P455」解碼爲「BTMEPASS」,但您可能想知道它也轉化爲「LETMEPASS」 - 這會讓你更畏縮。

+0

查看我的增強版本,根據你的開始。 – 2015-06-25 15:13:37

2

根據samy上面的回答,這是一個更進一步的增強版本。它允許每個輸入字符有多個輸出規則,並且特別爲所有非字母數字字符設置規則,以便將其從字符串中刪除。其結果是,你可以發送經典的XKCD漫畫密碼Tr0ub4dor & 3,然後離開Troubador。

我使用它的目的與OP相同,以確認提供給包含高度安全數據的系統的密碼不基於字典單詞。

我正在解碼函數的輸出,並通過字典運行它。

public class LeetSpeakDecoder 
    { 
     private Dictionary<string, IEnumerable<string>> Cache { get; set; } 
     private Dictionary<string, List<string>> Rules = new Dictionary<string, List<string>>(); 

     public void AddRule(string key, string value) 
     { 
      List<string> keyRules = null; 
      if (Rules.ContainsKey(key)) 
      { 
       keyRules = Rules[key]; 
      } 
      else 
      { 
       keyRules = new List<string>(); 
       Rules[key] = keyRules; 
      } 
      keyRules.Add(value); 
     } 

     public LeetSpeakDecoder() 
     { 
      Cache = new Dictionary<string, IEnumerable<string>>(); 


      AddRule("4", "A"); 
      AddRule("4", "a"); 
      AddRule(@"/\", "A"); 
      AddRule("@", "A"); 
      AddRule("^", "A"); 
      AddRule("13", "B"); 
      AddRule("/3", "B"); 
      AddRule("|3", "B"); 
      AddRule("8", "B"); 
      AddRule("><", "X"); 
      AddRule("<", "C"); 
      AddRule("(", "C"); 
      AddRule("|)", "D"); 
      AddRule("|>", "D"); 
      AddRule("3", "E"); 
      AddRule("6", "G"); 
      AddRule("/-/", "H"); 
      AddRule("[-]", "H"); 
      AddRule("]-[", "H"); 
      AddRule("!", "I"); 
      AddRule("|_", "L"); 
      AddRule("_/", "J"); 
      AddRule("_|", "J"); 
      AddRule("1", "L"); 
      AddRule("0", "O"); 
      AddRule("0", "o"); 
      AddRule("5", "S"); 
      AddRule("7", "T"); 
      AddRule(@"\/\/", "W"); 
      AddRule(@"\/", "V"); 
      AddRule("2", "Z"); 

      const string nonAlpha = @"[email protected]#$%^&*()-_=+[]{}\|;:'<,>./?"""; 
      foreach (var currentChar in nonAlpha) 
      { 
       AddRule(currentChar.ToString(), ""); 
      } 
     } 

     public IEnumerable<string> Decode(string leet) 
     { 
      var list = new List<string>(); 
      if (Cache.ContainsKey(leet)) 
      { 
       return Cache[leet]; 
      } 

      DecodeOneCharacter(leet, list); 
      DecodeMoreThanOneCharacter(leet, list); 
      DecodeWholeWord(leet, list); 

      list = list.Distinct().ToList(); 

      Cache.Add(leet, list); 
      return list; 
     } 

     private void DecodeOneCharacter(string leet, List<string> list) 
     { 
      if (leet.Length == 1) 
      { 
       list.Add(leet); 
      } 
     } 

     private void DecodeMoreThanOneCharacter(string leet, List<string> list) 
     { 
      if (leet.Length > 1) 
      { // we split the word in two parts and check how many variations each part will decode to 
       for (var splitPoint = 1; splitPoint < leet.Length; splitPoint++) 
       { 
        foreach (var leftPartDecoded in Decode(leet.Substring(0, splitPoint))) 
        { 
         foreach (var rightPartDecoded in Decode(leet.Substring(splitPoint))) 
         { 
          list.Add(leftPartDecoded + rightPartDecoded); 
         } 
        } 
       } 
      } 
     } 

     private void DecodeWholeWord(string leet, List<string> list) 
     { 
      if (Rules.ContainsKey(leet)) 
      { 
       foreach (var ruleValue in Rules[leet]) 
       { 
        list.Add(ruleValue); 
       } 

      } 
     } 
    } 

這裏是我的輸出

Tr0ub4dor&3 
Tr0ub4dor&E 
Tr0ub4dor& 
Tr0ub4dor3 
Tr0ub4dorE 
Tr0ub4dor 
Tr0ubAdor&3 
Tr0ubAdor&E 
Tr0ubAdor& 
Tr0ubAdor3 
Tr0ubAdorE 
Tr0ubAdor 
Tr0ubador&3 
Tr0ubador&E 
Tr0ubador& 
Tr0ubador3 
Tr0ubadorE 
Tr0ubador 
Tr0ubdor&3 
Tr0ubdor&E 
Tr0ubdor& 
Tr0ubdor3 
Tr0ubdorE 
Tr0ubdor 
TrOub4dor&3 
TrOub4dor&E 
TrOub4dor& 
TrOub4dor3 
TrOub4dorE 
TrOub4dor 
TrOubAdor&3 
TrOubAdor&E 
TrOubAdor& 
TrOubAdor3 
TrOubAdorE 
TrOubAdor 
TrOubador&3 
TrOubador&E 
TrOubador& 
TrOubador3 
TrOubadorE 
TrOubador 
TrOubdor&3 
TrOubdor&E 
TrOubdor& 
TrOubdor3 
TrOubdorE 
TrOubdor 
Troub4dor&3 
Troub4dor&E 
Troub4dor& 
Troub4dor3 
Troub4dorE 
Troub4dor 
TroubAdor&3 
TroubAdor&E 
TroubAdor& 
TroubAdor3 
TroubAdorE 
TroubAdor 
Troubador&3 
Troubador&E 
Troubador& 
Troubador3 
TroubadorE 
Troubador 
Troubdor&3 
Troubdor&E 
Troubdor& 
Troubdor3 
TroubdorE 
Troubdor 
Trub4dor&3 
Trub4dor&E 
Trub4dor& 
Trub4dor3 
Trub4dorE 
Trub4dor 
TrubAdor&3 
TrubAdor&E 
TrubAdor& 
TrubAdor3 
TrubAdorE 
TrubAdor 
Trubador&3 
Trubador&E 
Trubador& 
Trubador3 
TrubadorE 
Trubador 
Trubdor&3 
Trubdor&E 
Trubdor& 
Trubdor3 
TrubdorE 
Trubdor 
+1

Troubador實際上拼寫爲Troubadour,因此上面的測試在與普通字典匹配時不起作用。我在轉換中增加了一些額外的規則,以處理英國主義,更多規則和常見錯字。每個新規則都會顯着增加組合的數量,但由於密碼更改相對較少,因此對每個排列進行排列和字典查找的負載不是問題 – 2015-06-25 18:30:28