web-dev-qa-db-fra.com

Comment inverser MD5 pour obtenir la chaîne d'origine?

Duplicata possible:
Est-il possible de décrypter les hachages md5?

Est-il possible d'obtenir une chaîne de MD5 en Java?

Tout d'abord, une chaîne est convertie en somme de contrôle MD5, est-il possible de récupérer cette somme de contrôle MD5 dans le texte d'origine?

Je suppose que vous utilisez MessageDigest, toute aide est grandement appréciée, même les autres bibliothèques Java.

Je veux juste aussi signaler s'il n'est pas possible comment cette application peut le faire: https://play.google.com/store/apps/details?id=com.fab.md5&hl=en =

J'ai même converti du texte en somme de contrôle MD5 en utilisant une autre application et j'ai utilisé cette somme de contrôle pour voir si l'application était capable de le reconvertir en texte et c'est ce qu'elle a fait.

24
orange

Non, ce n'est pas vraiment possible, car

  • il peut y avoir plus d'une chaîne donnant la même chose MD5
  • il a été conçu pour être difficile à "inverser"

L'objectif du MD5 et de sa famille de fonctions de hachage est

  • pour obtenir de courts "extraits" d'une longue chaîne
  • pour qu'il soit difficile de deviner d'où ils viennent
  • pour qu'il soit difficile de trouver des collisions, c'est-à-dire ayant le même hachage (ce qui est une exigence très similaire à la seconde)

Pensez que vous pouvez obtenir le MD5 de n'importe quelle chaîne, même très longue. Et le MD5 ne fait que 16 octets (32 si vous l'écrivez en hexa pour le stocker ou le distribuer plus facilement). Si vous pouviez les inverser, vous auriez un schéma de compactage magique.

Cela étant dit, comme il n'y a pas tant de chaînes courtes (mots de passe ...) utilisées dans le monde, vous pouvez les tester à partir d'un dictionnaire (appelé "attaque par force brute") ou même google pour votre MD5. Si la Parole est courante et n'a pas été salée, vous avez une chance raisonnable de réussir ...

38
Denys Séguret

Ce n'est pas possible, c'est tout l'intérêt du hachage. Vous pouvez cependant utiliser la force brute en passant par toutes les possibilités (en utilisant tous les caractères possibles dans chaque ordre) et en les hachant et en recherchant une collision.

pour plus d'informations sur le hachage et MD5, etc., voir: http://en.wikipedia.org/wiki/MD5 , http://en.wikipedia.org/wiki/Hash_function =, http://en.wikipedia.org/wiki/Cryptographic_hash_function et http://onin.com/hhh/hhhexpl.html

J'ai moi-même créé ma propre application pour ce faire, son open source, vous pouvez vérifier le lien: http://sourceforge.net/projects/jpassrecovery/ et bien sûr la source. Voici la source pour un accès facile il a une implémentation de base dans les commentaires:

Bruter.Java :

import Java.util.ArrayList;

public class Bruter {

    public ArrayList<String> characters = new ArrayList<>();
    public boolean found = false;
    public int maxLength;
    public int minLength;
    public int count;
    long starttime, endtime;
    public int minutes, seconds, hours, days;
    public char[] specialCharacters = {'~', '`', '!', '@', '#', '$', '%', '^',
        '&', '*', '(', ')', '_', '-', '+', '=', '{', '}', '[', ']', '|', '\\',
        ';', ':', '\'', '"', '<', '.', ',', '>', '/', '?', ' '};
    public boolean done = false;
    public boolean paused = false;

    public boolean isFound() {
        return found;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
    }

    public boolean isPaused() {
        return paused;
    }

    public void setFound(boolean found) {
        this.found = found;
    }

    public synchronized void setEndtime(long endtime) {
        this.endtime = endtime;
    }

    public int getCounter() {
        return count;
    }

    public long getRemainder() {
        return getNumberOfPossibilities() - count;
    }

    public long getNumberOfPossibilities() {
        long possibilities = 0;
        for (int i = minLength; i <= maxLength; i++) {
            possibilities += (long) Math.pow(characters.size(), i);
        }
        return possibilities;
    }

    public void addExtendedSet() {
        for (char c = (char) 0; c <= (char) 31; c++) {
            characters.add(String.valueOf(c));
        }
    }

    public void addStandardCharacterSet() {
        for (char c = (char) 32; c <= (char) 127; c++) {
            characters.add(String.valueOf(c));
        }
    }

    public void addLowerCaseLetters() {
        for (char c = 'a'; c <= 'z'; c++) {
            characters.add(String.valueOf(c));
        }
    }

    public void addDigits() {
        for (int c = 0; c <= 9; c++) {
            characters.add(String.valueOf(c));
        }
    }

    public void addUpperCaseLetters() {
        for (char c = 'A'; c <= 'Z'; c++) {
            characters.add(String.valueOf(c));
        }
    }

    public void addSpecialCharacters() {
        for (char c : specialCharacters) {
            characters.add(String.valueOf(c));
        }
    }

    public void setMaxLength(int i) {
        maxLength = i;
    }

    public void setMinLength(int i) {
        minLength = i;
    }

    public int getPerSecond() {
        int i;
        try {
            i = (int) (getCounter() / calculateTimeDifference());
        } catch (Exception ex) {
            return 0;
        }
        return i;

    }

    public String calculateTimeElapsed() {
        long timeTaken = calculateTimeDifference();
        seconds = (int) timeTaken;
        if (seconds > 60) {
            minutes = (int) (seconds / 60);
            if (minutes * 60 > seconds) {
                minutes = minutes - 1;
            }

            if (minutes > 60) {
                hours = (int) minutes / 60;
                if (hours * 60 > minutes) {
                    hours = hours - 1;
                }
            }

            if (hours > 24) {
                days = (int) hours / 24;
                if (days * 24 > hours) {
                    days = days - 1;
                }
            }
            seconds -= (minutes * 60);
            minutes -= (hours * 60);
            hours -= (days * 24);
            days -= (hours * 24);
        }
        return "Time elapsed: " + days + "days " + hours + "h " + minutes + "min " + seconds + "s";
    }

    private long calculateTimeDifference() {
        long timeTaken = (long) ((endtime - starttime) * (1 * Math.pow(10, -9)));
        return timeTaken;
    }

    public boolean excludeChars(String s) {
        char[] arrayChars = s.toCharArray();
        for (int i = 0; i < arrayChars.length; i++) {
            characters.remove(arrayChars[i] + "");
        }
        if (characters.size() < maxLength) {
            return false;
        } else {
            return true;

        }
    }

    public int getMaxLength() {
        return maxLength;
    }

    public int getMinLength() {
        return minLength;
    }

    public void setIsDone(Boolean b) {
        done = b;
    }

    public boolean isDone() {
        return done;
    }
}

HashBruter.Java :

import Java.security.MessageDigest;
import Java.security.NoSuchAlgorithmException;
import Java.util.Zip.Adler32;
import Java.util.Zip.CRC32;
import Java.util.Zip.Checksum;
import javax.swing.JOptionPane;

public class HashBruter extends Bruter {
    /*
     * public static void main(String[] args) {
     *
     * final HashBruter hb = new HashBruter();
     *
     * hb.setMaxLength(5); hb.setMinLength(1);
     *
     * hb.addSpecialCharacters(); hb.addUpperCaseLetters();
     * hb.addLowerCaseLetters(); hb.addDigits();
     *
     * hb.setType("sha-512");
     *
     * hb.setHash("282154720ABD4FA76AD7CD5F8806AA8A19AEFB6D10042B0D57A311B86087DE4DE3186A92019D6EE51035106EE088DC6007BEB7BE46994D1463999968FBE9760E");
     *
     * Thread thread = new Thread(new Runnable() {
     *
     * @Override public void run() { hb.tryBruteForce(); } });
     *
     * thread.start();
     *
     * while (!hb.isFound()) { System.out.println("Hash: " +
     * hb.getGeneratedHash()); System.out.println("Number of Possibilities: " +
     * hb.getNumberOfPossibilities()); System.out.println("Checked hashes: " +
     * hb.getCounter()); System.out.println("Estimated hashes left: " +
     * hb.getRemainder()); }
     *
     * System.out.println("Found " + hb.getType() + " hash collision: " +
     * hb.getGeneratedHash() + " password is: " + hb.getPassword());
     *
     * }
     */

    public String hash, generatedHash, password;
    public String type;

    public String getType() {
        return type;
    }

    public String getPassword() {
        return password;
    }

    public void setHash(String p) {
        hash = p;
    }

    public void setType(String digestType) {
        type = digestType;
    }

    public String getGeneratedHash() {
        return generatedHash;
    }

    public void tryBruteForce() {
        starttime = System.nanoTime();
        for (int size = minLength; size <= maxLength; size++) {
            if (found == true || done == true) {
                break;
            } else {
                while (paused) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                generateAllPossibleCombinations("", size);
            }
        }
        done = true;
    }

    private void generateAllPossibleCombinations(String baseString, int length) {
        while (paused) {
            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
        if (found == false || done == false) {
            if (baseString.length() == length) {
                if(type.equalsIgnoreCase("crc32")) {
                generatedHash = generateCRC32(baseString);
                } else if(type.equalsIgnoreCase("adler32")) {
                generatedHash = generateAdler32(baseString);
                } else if(type.equalsIgnoreCase("crc16")) {
                    generatedHash=generateCRC16(baseString);
                } else if(type.equalsIgnoreCase("crc64")) {
                    generatedHash=generateCRC64(baseString.getBytes());
                }
                else {
                generatedHash = generateHash(baseString.toCharArray());
                }
                    password = baseString;
                if (hash.equals(generatedHash)) {
                    password = baseString;
                    found = true;
                    done = true;
                }
                count++;
            } else if (baseString.length() < length) {
                for (int n = 0; n < characters.size(); n++) {
                    generateAllPossibleCombinations(baseString + characters.get(n), length);
                }
            }
        }
    }

    private String generateHash(char[] passwordChar) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance(type);
        } catch (NoSuchAlgorithmException e1) {
            JOptionPane.showMessageDialog(null, "No such algorithm for hashes exists", "Error", JOptionPane.ERROR_MESSAGE);
        }
        String passwordString = new String(passwordChar);
        byte[] passwordByte = passwordString.getBytes();
        md.update(passwordByte, 0, passwordByte.length);
        byte[] encodedPassword = md.digest();
        String encodedPasswordInString = toHexString(encodedPassword);
        return encodedPasswordInString;
    }

    private void byte2hex(byte b, StringBuffer buf) {
        char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
            '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        int high = ((b & 0xf0) >> 4);
        int low = (b & 0x0f);
        buf.append(hexChars[high]);
        buf.append(hexChars[low]);
    }

    private String toHexString(byte[] block) {
        StringBuffer buf = new StringBuffer();
        int len = block.length;
        for (int i = 0; i < len; i++) {
            byte2hex(block[i], buf);
        }
        return buf.toString();
    }

    private String generateCRC32(String baseString) {

                //Convert string to bytes
                byte bytes[] = baseString.getBytes();

                Checksum checksum = new CRC32();

                /*
                 * To compute the CRC32 checksum for byte array, use
                 *
                 * void update(bytes[] b, int start, int length)
                 * method of CRC32 class.
                 */

                checksum.update(bytes,0,bytes.length);

                /*
                 * Get the generated checksum using
                 * getValue method of CRC32 class.
                 */
                return String.valueOf(checksum.getValue());
    }   
    private String generateAdler32(String baseString) {

                //Convert string to bytes
                byte bytes[] = baseString.getBytes();

                Checksum checksum = new Adler32();

                /*
                 * To compute the CRC32 checksum for byte array, use
                 *
                 * void update(bytes[] b, int start, int length)
                 * method of CRC32 class.
                 */

                checksum.update(bytes,0,bytes.length);

                /*
                 * Get the generated checksum using
                 * getValue method of CRC32 class.
                 */
                return String.valueOf(checksum.getValue());
    }
/*************************************************************************
 *  Compilation:  javac CRC16.Java
 *  Execution:    Java CRC16 s
 *  
 *  Reads in a string s as a command-line argument, and prints out
 *  its 16-bit Cyclic Redundancy Check (CRC16). Uses a lookup table.
 *
 *  Reference:  http://www.gelato.unsw.edu.au/lxr/source/lib/crc16.c
 *
 *  % Java CRC16 123456789
 *  CRC16 = bb3d
 *
 * Uses irreducible polynomial:  1 + x^2 + x^15 + x^16
 *
 *
 *************************************************************************/
    private String generateCRC16(String baseString) {
                int[] table = {
            0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
            0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
            0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
            0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
            0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
            0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
            0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
            0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
            0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
            0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
            0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
            0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
            0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
            0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
            0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
            0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
            0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
            0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
            0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
            0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
            0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
            0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
            0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
            0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
            0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
            0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
            0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
            0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
            0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
            0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
            0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
            0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
        };


        byte[] bytes = baseString.getBytes();
        int crc = 0x0000;
        for (byte b : bytes) {
            crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
        }

        return Integer.toHexString(crc);
    }
    /*******************************************************************************
 * Copyright (c) 2009, 2012 Mountainminds GmbH & Co. KG and Contributors
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.Eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Marc R. Hoffmann - initial API and implementation
 *    
 *******************************************************************************/

/**
 * CRC64 checksum calculator based on the polynom specified in ISO 3309. The
 * implementation is based on the following publications:
 * 
 * <ul>
 * <li>http://en.wikipedia.org/wiki/Cyclic_redundancy_check</li>
 * <li>http://www.geocities.com/SiliconValley/Pines/8659/crc.htm</li>
 * </ul>
 */
    private static final long POLY64REV = 0xd800000000000000L;

    private static final long[] LOOKUPTABLE;

    static {
        LOOKUPTABLE = new long[0x100];
        for (int i = 0; i < 0x100; i++) {
            long v = i;
            for (int j = 0; j < 8; j++) {
                if ((v & 1) == 1) {
                    v = (v >>> 1) ^ POLY64REV;
                } else {
                    v = (v >>> 1);
                }
            }
            LOOKUPTABLE[i] = v;
        }
    }

    /**
     * Calculates the CRC64 checksum for the given data array.
     * 
     * @param data
     *            data to calculate checksum for
     * @return checksum value
     */
    public static String generateCRC64(final byte[] data) {
        long sum = 0;
        for (int i = 0; i < data.length; i++) {
            final int lookupidx = ((int) sum ^ data[i]) & 0xff;
            sum = (sum >>> 8) ^ LOOKUPTABLE[lookupidx];
        }
        return String.valueOf(sum);
    }
}

vous l'utiliseriez comme:

      final HashBruter hb = new HashBruter();

      hb.setMaxLength(5); hb.setMinLength(1);

     hb.addSpecialCharacters(); hb.addUpperCaseLetters();
     hb.addLowerCaseLetters(); hb.addDigits();

      hb.setType("sha-512");

                   hb.setHash("282154720ABD4FA76AD7CD5F8806AA8A19AEFB6D10042B0D57A311B86087DE4DE3186A92019D6EE51035106EE088DC6007BEB7BE46994D1463999968FBE9760E");

      Thread thread = new Thread(new Runnable() {

      @Override public void run() { hb.tryBruteForce(); } });

      thread.start();

      while (!hb.isFound()) { System.out.println("Hash: " +
      hb.getGeneratedHash()); System.out.println("Number of Possibilities: " +
      hb.getNumberOfPossibilities()); System.out.println("Checked hashes: " +
     hb.getCounter()); System.out.println("Estimated hashes left: " +
     hb.getRemainder()); }

     System.out.println("Found " + hb.getType() + " hash collision: " +
     hb.getGeneratedHash() + " password is: " + hb.getPassword());
15
David Kroukamp