是否存在迭代所有符合特定正则表达式的字符串的算法?

时间:2015-06-22 18:28:35

标签: c# regex algorithm

我正在创建一个脚本来尝试入侵一个帐户,其登录密码长度至少为8个字符,并且包含至少1个数字,1个特殊字符和1个大写字母。我会用蛮力。是否有一种紧凑,优雅和有效的方法来迭代匹配给定正则表达式的每个可能的字符串?有没有C#类已经这样做了,还是我必须发明轮子?

渴望:

CoolClass pswExpIter = CoolClass(pswExp);
for ( string thisExp = pswdExpIter.first(); thisExp != pswdExpIter.offend(); thisExp = pswdExpIter.next()) 
{
      if (login("John Doe", thisExp)
      {
           // do something
           break;
      }          
}

3 个答案:

答案 0 :(得分:3)

枚举字符串并不困难,如下所示:

  1. 使用任何常用算法构建DFA。

  2. DFA实际上是一张图表。对图表进行广度优先遍历,如果已经访问过目标,则不通常从工作队列中删除边缘。在标记为接受的每个节点上,打印通向节点的转换。

  3. 由于必须维护队列中每个节点的转换历史记录,因此该算法将快速耗尽内存。您想到的特定用例的替代方案是深度优先遍历,在达到所需的字符串长度时停止。这不会占用太多内存,但除非你有办法进一步限制可能性,否则它仍然需要花费大量时间。

答案 1 :(得分:1)

这是你要找的东西:

    char[] availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_=+*".ToArray();
    IEnumerable<string> CreatePassword(int size)
    {

        if (size == 1 )
        {
            foreach (var c in availableChars)
            {
                yield return c.ToString();
            }
            yield break;
        }

        foreach (var password in CreatePassword(size - 1))
        {
            foreach (var c in availableChars)
            {
                yield return password + c;
            }
        }
    }
祝你好运:)

答案 2 :(得分:0)

让我们说域名如下

String domain[] = { a, b, .., z, A, B, .. Z, 0, 1, 2, .. 9 };

我们说密码大小为8

ArrayList allCombinations = getAllPossibleStrings2(domain,8);

这将生成SIZE(domain) * LENGTH个组合,在此示例中为(26+26+10)^8 = 62^8 = 218,340,105,584,896个组合

然后你可以枚举所有可能的字符串\ at到特定大小,如

// get all possible combinations up to a given size
static ArrayList getAllPossibleStrings1(ArrayList domain, int maxSize)
{
    ArrayList list = new ArrayList();
    int i = 1;

    list.AddRange(domain);

    while(++i <= maxSize)
        for(String a in list)
            for(String b in domain)
                list.Add(String.Concat(a,b));

    return list;
}

// get all possible combinations at a given size
static ArrayList getAllPossibleStrings2(ArrayList domain, int size)
{
    ArrayList list = new ArrayList();
    ArrayList temp = new ArrayList();
    int i = 1;

    list.AddRange(domain);

    while(++i <= maxSize)
    {
        for(String a in list)
            for(String b in domain)
                temp.Add(String.Concat(a,b));

        list.Clear();
        list.AddRange(temp);
        temp.Clear();
    }

    return list;
}