【问题标题】:How to reverse modified string back into MD5 hash given the method used to modify the string?给定用于修改字符串的方法,如何将修改后的字符串反转回 MD5 哈希?
【发布时间】:2017-11-04 23:39:19
【问题描述】:

我正在处理一些 MD5 散列,这些散列已使用下面显示的方法转换为数字序列。鉴于下面的代码和示例哈希,我如何“反转”getString() 方法的效果并将数字序列转换回 MD5 哈希?

例如,encrypt("umadbro"); 返回“1518918615824625494170109603025017352201241”,因为 MD5 哈希是通过 getString() 方法传递的。 “umadbro”的 MD5 哈希是 9759ba9ef6fe5eaa6d3c1efaad34c9f1。我需要一个方法,它接受由getString() 方法修改的一串数字并将其转换为它的 MD5 哈希值。例如:reverseMethod("1518918615824625494170109603025017352201241"); 应该输出“9759ba9ef6fe5eaa6d3c1efaad34c9f1”(输入参数是修改后的数字字符串,输出是原始字符串的 MD5 哈希)。 注意:我不是在寻找破解 MD5 哈希的方法。我只需要一个反转下面所示getString() 方法效果的方法。

    public String encrypt(String source)
        {
            try
            {
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] bytes = md.digest(source.getBytes());
                return getString(bytes);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
        }

    private String getString(byte[] bytes) //this takes an md5 hash and turns it into a string of numbers.
    // How can I reverse the effect of this method?
    {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++)
        {
            byte b = bytes[i];
            sb.append(0xFF & b);
        }
        return sb.toString();
}

【问题讨论】:

标签: java hash cryptography md5 cryptographic-hash-function


【解决方案1】:

我尝试编写一些代码来查找所有可能的组合,结果发现比我预期的要少得多。在这种情况下只有 2 个。并且只需很短的时间即可找到它们。

import java.util.ArrayList;
import java.util.Arrays;

public class Comb {
  static long combinations(String str, int startIdx, int numBytes, ArrayList<byte[]> combinations, byte[] combination) {
    if(startIdx >= str.length()) {
       if(numBytes == 16) {
         combinations.add(combination.clone());
         return 1;
       } else return 0;
    }
    if(numBytes > 15) return 0;
    combination[numBytes] = (byte)(str.charAt(startIdx) - '0');
    long result = combinations(str, startIdx + 1, numBytes + 1, combinations, combination);
    if(startIdx < str.length() - 1 && str.charAt(startIdx) != '0') {
      combination[numBytes] = (byte)((str.charAt(startIdx) - '0') * 10 + (str.charAt(startIdx + 1) - '0'));
      result += combinations(str, startIdx + 2, numBytes + 1, combinations, combination);
    }
    if(startIdx < str.length() - 2) {
      combination[numBytes] = (byte)((str.charAt(startIdx) - '0') * 100 + (str.charAt(startIdx + 1) - '0') * 10 + (str.charAt(startIdx + 2) - '0'));
      if(str.charAt(startIdx) == '1') result += combinations(str, startIdx + 3, numBytes + 1, combinations, combination);
      if(str.charAt(startIdx) == '2' &&
        (str.charAt(startIdx + 1) < '5' || str.charAt(startIdx + 1) == '5' && str.charAt(startIdx + 2) < '6')) {
          result += combinations(str, startIdx + 3, numBytes + 1, combinations, combination);
      }
    }
    return result;
  }

  public static void main(String[] args) {
    ArrayList<byte[]> combinations = new ArrayList<>();
    System.out.println(combinations("1518918615824625494170109603025017352201241", 0, 0, combinations, new byte[16]));
    for(byte[] c: combinations) {
      System.out.println(Arrays.toString(c));
    }
  }
}

这个的输出是:

2
[15, -67, -70, -98, -10, -2, 94, -86, 109, 60, 30, -6, -83, 52, -55, -15]
[-105, 89, -70, -98, -10, -2, 94, -86, 109, 60, 30, -6, -83, 52, -55, -15]

它找到的第二个解决方案确实是正确的。

【讨论】:

    【解决方案2】:

    如果不尝试所有组合并进行比较,这是不可能的。问题是getString 没有返回一个对于给定哈希值唯一的数字作为字节。

    例如,如果字节的值是 0216 十六进制,那么 02 在十进制字符串编码中变为 "2"16 变为 "22"。因此,您的方法将返回 "222" 作为两者的串联。现在,如果我们对1602 做同样的事情,那么它将产生"22""2",而连接仍然会产生"222"。这可能发生在字节数组中的每个字节组合上。

    因此,尽管结果可能仍然是相对安全的哈希,但发现冲突的机会要高得多。您可以做的是返回一大组散列,其中 1 将导致匹配,但这需要大量计算;如果您想比较,最好将结果通过getString 并比较安全性低得多的散列(甚至比 MD5 更不安全)。

    【讨论】:

    • 我可以用彩虹表破解器破解哈希。您的解决方案将非常有帮助,唯一的问题是我不知道如何在 Java 中做到这一点。如何为一种从修改后的字符串生成所有可能的哈希值的方法编写代码?
    • 请注意,如果您尝试反转它,您有一个优势:值都在 0 到 255 的范围内。这意味着第一个数字很有可能是 '1' 或 @ 987654334@。因此,您可以使用该信息更好地猜测字节值之间的边界在哪里。
    • @JavaWeenis 你将如何验证结果?
    • 我可以用彩虹表破解器破解哈希并将其重新插入程序,看看它是否输出相同的数字字符串。
    • @JavaWeenis 只是修改破解器中的代码以在它执行 md5 之后应用 getString。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 1970-01-01
    • 2014-05-30
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多