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