Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在给定用于修改字符串的方法的情况下,如何将修改后的字符串反转回MD5哈希?_Java_Hash_Cryptography_Md5_Cryptographic Hash Function - Fatal编程技术网

Java 在给定用于修改字符串的方法的情况下,如何将修改后的字符串反转回MD5哈希?

Java 在给定用于修改字符串的方法的情况下,如何将修改后的字符串反转回MD5哈希?,java,hash,cryptography,md5,cryptographic-hash-function,Java,Hash,Cryptography,Md5,Cryptographic Hash Function,我正在使用下面所示的方法处理一些MD5哈希,这些哈希已转换为数字序列。给定下面的代码和示例哈希,我如何“反转”getString()方法的效果,并将数字序列转换回MD5哈希 例如,encrypt(“umadbro”)返回“1518918615824625494170109603025017352201241”,因为MD5哈希通过getString()方法传递。“umadbro”的MD5哈希是9759BA9EF6FE5EAA6D3C1EFAAD3C9F1。我需要一个方法,该方法接受由getStri

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

例如,
encrypt(“umadbro”)返回“1518918615824625494170109603025017352201241”,因为MD5哈希通过
getString()
方法传递。“umadbro”的MD5哈希是9759BA9EF6FE5EAA6D3C1EFAAD3C9F1。我需要一个方法,该方法接受由
getString()
方法修改的数字字符串,并将其转换为MD5哈希。例如:
reverseMethod(“1518918615824625494170109603025017352201241”)应输出“9759BA9EF6FE5EAA6D3C1EFAAD3C9F1”(输入参数为修改后的数字字符串,输出为原始字符串的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();
}
公共字符串加密(字符串源)
{
尝试
{
MessageDigest md=MessageDigest.getInstance(“MD5”);
byte[]bytes=md.digest(source.getBytes());
返回getString(字节);
}
捕获(例外e)
{
e、 printStackTrace();
}
返回null;
}
private String getString(byte[]bytes)//这将获取md5哈希并将其转换为数字字符串。
//我怎样才能扭转这种方法的效果?
{
StringBuffer sb=新的StringBuffer();
for(int i=0;i
如果不尝试所有组合并进行比较,这是不可能的。问题是,
getString
没有返回一个对于给定哈希值唯一的字节数

例如,如果字节的值为
0216
hex,则
02
将以十进制字符串编码方式变为
“2”
,而
16
将变为
“22”
。因此,您的方法将返回
“222”
,作为两者的串联。现在,如果我们对
1602
执行相同的操作,那么它将导致
“22”
“2”
,而串联仍然会导致
“222”
。这可能发生在字节数组中的每个字节组合上


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

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

例如,如果字节的值为
0216
hex,则
02
将以十进制字符串编码方式变为
“2”
,而
16
将变为
“22”
。因此,您的方法将返回
“222”
,作为两者的串联。现在,如果我们对
1602
执行相同的操作,那么它将导致
“22”
“2”
,而串联仍然会导致
“222”
。这可能发生在字节数组中的每个字节组合上


因此,尽管结果可能仍然是相对安全的散列,但找到冲突的可能性要高得多。您可以做的是返回一个大的哈希集,其中1将导致匹配,但这将需要大量计算;如果你想比较,最好先通过
getString
来比较结果,然后比较那些不太安全的散列(甚至比MD5还不安全)。

我试着写了一些代码,找到了所有可能的组合,结果发现比我预期的要少得多。在这种情况下只有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个。而且只需要很少的时间就能找到它们

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));
    }
  }
}

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

不确定这是否可行,因为不同的哈希将具有相同的表示形式。例如,“97”、“0133”、“0F01”和“010501”都将作为getString的结果使用“151”。如果数字之间有分隔符,则不存在可能重复的问题,也不确定是否可能重复,因为不同的哈希将具有相同的表示形式。例如,“97”、“0133”、“0F01”和“010501”都将作为getString的结果使用“151”。如果在数字之间有一个分隔符,那么就没有问题了。我可以用彩虹表破解器破解散列。您的解决方案将非常有用,唯一的问题是我不知道如何在Java中实现它。如何为一个从修改后的字符串生成所有可能散列的方法编写代码?请注意,如果尝试将其反转,则有一个优势:值都在0到255之间。这意味着第一个数字很有可能是
'1'
'2'
。因此,您可以使用该信息更好地猜测字节值之间的边界。@JavaWeenis您如何验证结果?我可以用rainbow表破解程序破解散列并将其插入程序,查看它是否输出相同的nu字符串