javahashcryptographymd5cryptographic-hash-function

How to reverse modified string back into MD5 hash given the method used to modify the string?


I am working with some MD5 hashes that have been turned into number sequences using the methods shown below. Given the code and example hash below, how can I "reverse" the effect of the getString() method and turn a numerical sequence back into an MD5 hash?

For example, encrypt("umadbro"); returns "1518918615824625494170109603025017352201241" because the MD5 hash is passed through the getString() method. The MD5 hash for "umadbro" is 9759ba9ef6fe5eaa6d3c1efaad34c9f1. I need a method that takes a string of numbers modified by the getString() method and converts it into its MD5 hash. For example: reverseMethod("1518918615824625494170109603025017352201241"); should output "9759ba9ef6fe5eaa6d3c1efaad34c9f1" (The input parameter is the modified string of numbers and the output is the MD5 hash of the original string). NOTE: I am not looking for a method to crack the MD5 hash. I only need a method that reverses the effect of the getString() method shown below.

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

Solution

  • I tried to write some code that finds all possible combinations and it turned out there are a lot less then I anticipated. Only 2 in this case. And it takes very little time to find them.

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

    The output of this is:

    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]
    

    And the second solution it found is indeed the correct one.