生成每个字符组合,直到某个字长

我将在几周后为我的计算机和信息安全课程做一个安全演示,在这个演讲中,我将展示不同攻击(字典,彩虹和暴力)的利弊。 我做的字典和彩虹攻击很好,但我需要在飞行中产生暴力攻击。 我需要找到一种算法,让我循环通过字母,符号和数字的每个组合,直到某个字符长度。

举个例子,对于12的字符长度,第一代和最后几代将是:

a ab abc abcd ... ... zzzzzzzzzzzx zzzzzzzzzzzy zzzzzzzzzzzz 

但它也会使用数字和符号,所以我很难解释……但我认为你明白了。 只使用ASCII表中的符号就可以了。

我可以用一个ASCII函数用计数器做这个图片,但我无法解决这个问题。 如果有人可以提供一些源代码(我可能会使用C#)甚至一些伪代码,我可以编写一个函数,这将是伟大的。

先感谢您。 🙂

递归函数将允许您运行ValidChars的所有组合:

  int maxlength = 12; string ValidChars; private void Dive(string prefix, int level) { level += 1; foreach (char c in ValidChars) { Console.WriteLine(prefix + c); if (level < maxlength) { Dive(prefix + c, level); } } } 

将有效字符集分配给ValidChars,即想要maxlength的字符串的最大长度,然后调用Dive("", 0); 然后你走吧

您需要从一组有效字符生成所有字符组合; 让我们称之为集合validChars 。 基本上,长度为N的每组组合都是validChars与其自身的笛卡尔积,N次。 使用Linq很容易做到:

 char[] validChars = ...; var combinationsOfLength1 = from c1 in validChars select new[] { c1 }; var combinationsOfLength2 = from c1 in validChars from c2 in validChars select new[] { c1, c2 }; ... var combinationsOfLength12 = from c1 in validChars from c2 in validChars ... from c12 in validChars select new[] { c1, c2 ... c12 }; var allCombinations = combinationsOfLength1 .Concat(combinationsOfLength2) ... .Concat(combinationsOfLength12); 

显然,你不想手动编写每个长度的代码,特别是如果你事先不知道最大长度……

Eric Lippert有一篇关于生成任意数量序列的笛卡尔积的文章 。 使用本文提供的CartesianProduct扩展方法,您可以生成长度为N的所有组合,如下所示:

 var combinationsOfLengthN = Enumerable.Repeat(validChars, N).CartesianProduct(); 

由于您需要从长度1到MAX的所有组合,您可以执行以下操作:

 var allCombinations = Enumerable .Range(1, MAX) .SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct()); 

allCombinations是一个IEnumerable> ,如果你想把结果作为一个字符串序列,你只需要添加一个投影:

 var allCombinations = Enumerable .Range(1, MAX) .SelectMany(N => Enumerable.Repeat(validChars, N).CartesianProduct()) .Select(combination => new string(combination.ToArray())); 

请注意,它肯定不是最有效的解决方案,但至少它简短易读……

您可以尝试使用递归将所有可能的字符串0打印到stringsLenght chars lenght的代码,该字符串由firstRangeChar和lastRangeChar的所有字符组合组成。

 class BruteWriter { static void Main(string[] args) { var bw = new BruteWriter(); bw.WriteBruteStrings(""); } private void WriteBruteStrings(string prefix) { Console.WriteLine(prefix); if (prefix.Length == stringsLenght) return; for (char c = firstRangeChar; c <= lastRangeChar; c++) WriteBruteStrings(prefix + c); } char firstRangeChar='A'; char lastRangeChar='z'; int stringsLenght=10; } 

这看起来比@ dthorpe的解决方案更快。我已经使用这段代码比较了algorthms:

 class BruteWriter { static void Main(string[] args) { var st = new Stopwatch(); var bw = new BruteWriter(); st.Start(); bw.WriteBruteStrings(""); Console.WriteLine("First method: " + st.ElapsedMilliseconds); for (char c = bw.firstRangeChar; c <= bw.lastRangeChar; c++) bw.ValidChars += c; st.Start(); bw.Dive("", 0); Console.WriteLine("Second method: " + st.ElapsedMilliseconds); Console.ReadLine(); } private void WriteBruteStrings(string prefix) { if (prefix.Length == stringsLenght) return; for (char c = firstRangeChar; c <= lastRangeChar; c++) WriteBruteStrings(prefix + c); } char firstRangeChar='A'; char lastRangeChar='R'; int stringsLenght=5; int maxlength = 5; string ValidChars; private void Dive(string prefix, int level) { level += 1; foreach (char c in ValidChars) { if (level <= maxlength) { Dive(prefix + c, level); } } } } 

而且,在我的电脑上,我得到了这些结果:

 First method: 247 Second method: 910 
 public void BruteStrings(int maxlength) { for(var i=1;i() .Aggregate(new StringBuilder(), (sb,c) => sb.Append(c)) .ToString()); if(bytes.All(b=>b.MaxValue)) return; bytes.Increment(); BruteStrings(bytes); } public static void Increment(this byte[] bytes) { bytes.Last() += 1; if(bytes.Last == byte.MinValue) { var lastByte = bytes.Last() bytes = bytes.Take(bytes.Count() - 1).ToArray().Increment(); bytes = bytes.Concat(new[]{lastByte}); } } 

我做的另一种选择,返回一个字符串。

我不关心事物的表现,因为它不是真实世界的场景。

 private void BruteForcePass(int maxLength) { var tempPass = ""; while (tempPass.Length <= maxLength) { tempPass = GetNextString(tempPass);//Use char from 32 to 256 //Do what you want } } private string GetNextString(string initialString, int minChar= 32, int maxChar = 256) { char nextChar; if (initialString.Length == 0) { nextChar = (char)minChar;//the initialString Length will increase } else if (initialString.Last() == (char)maxChar) { nextChar = (char)minChar; var tempString = initialString.Substring(0, initialString.Length -1);//we need to increment the char just before the last one initialString = GetNextString(tempString, minChar, maxChar); } else { nextChar = (char)(initialString.Last() + 1);//Get the lash Char and increment it; initialString= initialString.Remove(initialString.Length - 1);//Remove the last char. } return initialString + nextChar; }