4

好吧,我知道这听起来很糟糕,就像我要把它用于不道德的事情一样,但你有我的保证,我不是。

我正在为我的计算机和信息安全课程写一篇论文,我选择的主题是散列方法。我在论文中提到的一点是 MD5 只是单向的,破解 MD5 哈希的唯一方法是不断地制作字符串并使用 MD5 函数,然后将其与要破解的哈希进行比较。

我想构建一个非常简单的模型程序来展示我的论文(我们做了一个演示,这将是一件很棒的事情),所以我想制定一个算法,用每个可能的字符组合生成一个字符串最多 8 个字符。例如,输出将是:

a, b, c, ..., aa, ab, ac, ... ba, bb, bc 等等等等等等。

如果可能,它需要包含字母、数字和符号。

我部分地通过了这个算法,但不幸的是我的编程技能不能胜任这项任务。如果有人可以为此提供完整的算法,我将非常感激。

再说一次,如果你认为我是个骗子,我打算用它来进行黑客攻击,你不必留下答案。

谢谢你。:)

4

5 回答 5

6

在 Python 中,itertools.product几乎可以满足您的所有要求——尽管它只针对一个“重复次数”进行,因此您必须从 1 迭代到 8(不难;-)。在本质上:

import itertools
import string

# whatever you wish as alphabet (lower/upper, digits, punct, &c)
myalphabet = string.ascii_lowercase + string.ascii_digits

def prods(maxlen, alphabet=myalphabet):
  for i in range(1, maxlen+1):
    for s in itertools.product(alphabet, repeat=i):
      yield ''.join(s)

当然,对于长度为 N 和 K 重复的字母(在您的情况下为 8),这确实会产生 N + N^2 + ... + N^K 的可能性(N=36 和 K=8 的可能性为 2,901,713,047,668),但是,朋友之间有几万亿的产出!-)

于 2009-11-01T04:18:04.257 回答
3

为了实现这一点,我可能会将整数编码为以 36 为基数(如果您想要符号,则可以更多)。

1 = 1 2 = 2 ... a = 10 b = 12 ..

等等。

那么你会有一个数字,比如 38 并做一些除法,即:

38/36 = 1 remaider 2 = 12 in base 36

然后只需运行一个 for 循环到您要编码的最大数字,非常大的数字并输出您的编码数字。

只是为了好玩,我为你写了这个:http ://pastebin.antiyes.com/index.php?id=327

于 2009-11-01T04:01:39.673 回答
1

“破解 MD5 哈希的唯一方法”是生成每个可能的字符串并查找冲突,这不是真的。事实上,如果您有权访问原始文件,则可以对其进行修改,使其 MD5 与您可以创建的另一个文件的 MD5 匹配。这在 infosec.edu 的一篇论文中有所描述。

即使您无法修改原始文件,也存在 MD5 校验和的彩虹表,可用于生成冲突。

这些事实使 MD5 不适用于密码或密码学,事实上美国政府已禁止其继续用于安全应用程序。

于 2009-11-01T04:10:58.517 回答
0

用一个 Java 示例来完成这篇文章,该示例将仅使用 0-9 和 az 字符打印出所有可能的字符组合的 Base64 编码的 MD5:

MessageDigest digest = MessageDigest.getInstance("MD5");
int i = 0;
while (true)
{
    String raw = Integer.toString(i, Character.MAX_RADIX);
    byte[] md5 = digest.digest(raw.getBytes());
    String base64 = new BigInteger(1, md5).toString(16);
    System.out.println(raw + " = " + base64);
    i++;
}
于 2009-11-01T05:09:43.357 回答
0

如果您已经可以访问密码的散列版本,则MD5 以. 也就是说,当涉及到破坏散列值时,您最好使用Rainbow TablesDictionary AttacksSocial Engineering ,而不是蛮力方法。也就是说,由于您要求一种算法来生成所有值,因此以下内容可能会有所帮助(C#):

using System;
using System.Text;

namespace PossibiltyIterator
{
  class Program
  {
    static readonly char[] Symbols = {
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 
      'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
      'I', 'J', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
      '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '!', '@', '#', '$', '%', '^', '&', 
      '*', '(', ')', '-', '_', '+', '=', '/', '\\', '[', ']', '{', '}', ';', ':', '\'', '"', 
      ',', '.', '<', '>', '?', '`', '~'
    };

    const int MaxLength = 8;

    static void BuildWord(int currentLength, int desiredLength, char[] word)
    {
      if (currentLength == desiredLength)
      {
        Console.WriteLine(word);
      }
      else
      {
        for (int value = 0; value < Symbols.Length; ++value)
        {
          word[currentLength] = Symbols[value];
          BuildWord(currentLength + 1, desiredLength, word);
        }
      }
    }

    static void Main(String[] args)
    {
      double totalValues = (Math.Pow(Symbols.Length, MaxLength + 1) - Symbols.Length)/(Symbols.Length - 1);
      Console.WriteLine("Warning! You are about to print: {0} values", totalValues);
      Console.WriteLine("Press any key to continue...");
      Console.ReadKey(true /* intercept */);

      for (int desiredLength = 1; desiredLength <= MaxLength; ++desiredLength)
      {
        BuildWord(0 /* currentLength */, desiredLength, new char[MaxLength]);
      }
    }

  }
}

老实说,这可以进一步优化。因为它构建了所有长度为 1 的“单词”,然后第二次构建长度为 2 的单词。构建长度为 MaxLength 的单词会更聪明,然后截断一个字母以构建一个 MaxLength 的单词- 1.

这是优化版本...请注意,它不会按照最初请求的顺序返回单词。

using System;
using System.Text;

namespace PossibiltyIterator
{
  class Program
  {
    static readonly char[] Symbols = {
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 
      'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
      'I', 'J', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
      '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '!', '@', '#', '$', '%', '^', '&', 
      '*', '(', ')', '-', '_', '+', '=', '/', '\\', '[', ']', '{', '}', ';', ':', '\'', '"', 
      ',', '.', '<', '>', '?', '`', '~'
    };

    const int MaxLength = 8;

    static void BuildWord(int currentLength, int desiredLength, char[] word)
    {
      if (currentLength != desiredLength)
      {
        for (int value = 0; value < Symbols.Length; ++value)
        {
          word[currentLength] = Symbols[value];
          BuildWord(currentLength + 1, desiredLength, word);
        }
        word[currentLength] = '\0';
      }

      Console.WriteLine(word);
    }

    static void Main(String[] args)
    {
      double totalValues = (Math.Pow(Symbols.Length, MaxLength + 1) - Symbols.Length)/(Symbols.Length - 1);
      char[] word = new char[MaxLength];

      Console.WriteLine("Warning! You are about to print: {0} values", totalValues);
      Console.WriteLine("Press any key to continue...");
      Console.ReadKey(true /* intercept */);

      BuildWord(0 /* currentLength */, MaxLength, new char[MaxLength]);
    }

  }
}
于 2009-11-01T04:38:35.540 回答