web-dev-qa-db-fra.com

Hachage MD5 dans Android

J'ai un simple Android qui doit "parler" à un simple écouteur HTTP C #. Je souhaite fournir un niveau d'authentification de base en passant un nom d'utilisateur/mot de passe dans POST demandes.

Le hachage MD5 est trivial en C # et fournit assez de sécurité pour mes besoins, mais je n'arrive pas à trouver comment faire cela à la fin Android).

EDIT: Juste pour répondre aux préoccupations exprimées au sujet de la faiblesse de MD5 - le serveur C # s’exécute sur les ordinateurs des utilisateurs de mon Android client. Dans de nombreux cas, ils accéderont au serveur à l’aide de Ils peuvent également accéder à Internet par leurs propres réseaux locaux, mais à leurs risques et périls. Le service sur le serveur doit également utiliser la transmission pour le MD5 à une application tierce sur laquelle je n’ai aucun contrôle.

86
Squonk

Ici est une implémentation que vous pouvez utiliser (mis à jour pour utiliser plus à jour Java conventions - for:each boucle, StringBuilder au lieu de StringBuffer):

public static final String md5(final String s) {
    final String MD5 = "MD5";
    try {
        // Create MD5 Hash
        MessageDigest digest = Java.security.MessageDigest
                .getInstance(MD5);
        digest.update(s.getBytes());
        byte messageDigest[] = digest.digest();

        // Create Hex String
        StringBuilder hexString = new StringBuilder();
        for (byte aMessageDigest : messageDigest) {
            String h = Integer.toHexString(0xFF & aMessageDigest);
            while (h.length() < 2)
                h = "0" + h;
            hexString.append(h);
        }
        return hexString.toString();

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return "";
}

Bien que cela ne soit pas recommandé pour les systèmes qui impliquent même le niveau de sécurité de base (MD5 considéré comme cassé et pouvant être facilement exploité ), il est parfois suffisant pour les tâches de base.

210
Den Delimarsky

La réponse acceptée ne fonctionnait pas pour moi dans Android 2.2. Je ne sais pas pourquoi, mais il "mangeait" certains de mes zéros (0). Apache commons ne fonctionnait pas non plus sur Android 2.2, car il utilise des méthodes prises en charge à partir de Android = 2.3.x. De plus, si vous voulez simplement MD5 une chaîne, Apache commons est trop complexe pour cela. Pourquoi garder une bibliothèque entière pour n’utiliser qu’une petite fonction de celle-ci ...

Enfin, j'ai trouvé l'extrait de code suivant ici qui a parfaitement fonctionné pour moi. J'espère que ça sera utile pour quelqu'un ...

public String MD5(String md5) {
   try {
        Java.security.MessageDigest md = Java.security.MessageDigest.getInstance("MD5");
        byte[] array = md.digest(md5.getBytes("UTF-8"));
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < array.length; ++i) {
          sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
       }
        return sb.toString();
    } catch (Java.security.NoSuchAlgorithmException e) {
    } catch(UnsupportedEncodingException ex){
    }
    return null;
}
46
Andranik

Le code androidsnippets.com ne fonctionne pas de manière fiable car les 0 semblent être coupés du hachage résultant.

Une meilleure implémentation est ici .

public static String MD5_Hash(String s) {
    MessageDigest m = null;

    try {
            m = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
    }

    m.update(s.getBytes(),0,s.length());
    String hash = new BigInteger(1, m.digest()).toString(16);
    return hash;
}
26
Christian

Si Apache Commons Codec est une option, son implémentation serait plus courte:

String md5Hex = new String(Hex.encodeHex(DigestUtils.md5(data)));

Ou SHA:

String shaHex= new String(Hex.encodeHex(DigestUtils.sha("textToHash")));

Source pour ci-dessus.

S'il vous plaît suivez le lien et upvote sa solution pour attribuer la bonne personne.


Lien de dépôt Maven: https://mvnrepository.com/artifact/commons-codec/commons-codec

Dépendance actuelle de Maven (à compter du 6 juillet 2016):

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.10</version>
</dependency>
18
tbraun

Une solution ci-dessus utilisant DigestUtils n'a pas fonctionné pour moi. Dans ma version de Apache commons (la dernière en date de 2013), cette classe n'existe pas.

J'ai trouvé une autre solution ici dans un blog . Cela fonctionne parfaitement et n'a pas besoin de commons Apache. Il semble un peu plus court que le code dans la réponse acceptée ci-dessus.

public static String getMd5Hash(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] messageDigest = md.digest(input.getBytes());
        BigInteger number = new BigInteger(1, messageDigest);
        String md5 = number.toString(16);

        while (md5.length() < 32)
            md5 = "0" + md5;

        return md5;
    } catch (NoSuchAlgorithmException e) {
        Log.e("MD5", e.getLocalizedMessage());
        return null;
    }
}

Vous aurez besoin de ces importations:

import Java.math.BigInteger;
import Java.security.MessageDigest;
import Java.security.NoSuchAlgorithmException;
11
wzbozon

Ceci est une légère variation des réponses d’Andranik et Den Delimarsky ci-dessus, mais c’est un peu plus concis et ne nécessite aucune logique au niveau des bits. Au lieu de cela, il utilise le String.format méthode pour convertir les octets en chaînes hexadécimales de deux caractères (ne supprime pas les 0). Normalement, je voudrais juste commenter leurs réponses, mais je n’ai pas la réputation de le faire.

public static String md5(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");

        StringBuilder hexString = new StringBuilder();
        for (byte digestByte : md.digest(input.getBytes()))
            hexString.append(String.format("%02X", digestByte));

        return hexString.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}

Si vous souhaitez plutôt renvoyer une chaîne en minuscule, changez simplement %02X à %02x.

Edit: En utilisant BigInteger comme avec la réponse de wzbozon, vous pouvez rendre la réponse encore plus concise:

public static String md5(String input) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");
        BigInteger md5Data = new BigInteger(1, md.digest(input.getBytes()));
        return String.Format("%032X", md5Data);
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
        return null;
    }
}
9
rsimp

J'ai créé une simple bibliothèque à Kotlin.

Ajouter à la racine build.gradle

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

sur App build.gradle

implementation 'com.github.1AboveAll:Hasher:-SNAPSHOT'

Usage

À Kotlin

val ob = Hasher()

Ensuite, utilisez la méthode hash ()

ob.hash("String_You_Want_To_Encode",Hasher.MD5)

ob.hash("String_You_Want_To_Encode",Hasher.SHA_1)

Il retournera MD5 et SHA-1 respectivement.

En savoir plus sur la bibliothèque

https://github.com/1AboveAll/Hasher

3
Himanshu Rawat

Dans notre application MVC, nous générons pour de longs paramètres

using System.Security.Cryptography;
using System.Text;
    ...
    public static string getMD5(long id)
    {
        // convert
        string result = (id ^ long.MaxValue).ToString("X") + "-ANY-TEXT";
        using (MD5 md5Hash = MD5.Create())
        {
            // Convert the input string to a byte array and compute the hash. 
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(result));

            // Create a new Stringbuilder to collect the bytes and create a string.
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
                sBuilder.Append(data[i].ToString("x2"));

            // Return the hexadecimal string. 
            result = sBuilder.ToString().ToUpper();
        }

        return result;
    }

et même dans Android (thenk aide Andranik)

import Java.security.MessageDigest;
import Java.security.NoSuchAlgorithmException;
...
public String getIdHash(long id){
    String hash = null;
    long intId = id ^ Long.MAX_VALUE;
    String md5 = String.format("%X-ANY-TEXT", intId);
    try {
        MessageDigest md = Java.security.MessageDigest.getInstance("MD5");
        byte[] arr = md.digest(md5.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < arr.length; ++i)
            sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1,3));

        hash = sb.toString();
    } catch (NoSuchAlgorithmException e) {
        Log.e("MD5", e.getMessage());
    }

    return hash.toUpperCase();
}
1
Oleg Grabets

j'ai utilisé la méthode ci-dessous pour me donner md5 en passant la chaîne pour laquelle vous voulez obtenir md5

public static String getMd5Key(String password) {

//        String password = "12131123984335";

        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(password.getBytes());

            byte byteData[] = md.digest();

            //convert the byte to hex format method 1
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
            }

            System.out.println("Digest(in hex format):: " + sb.toString());

            //convert the byte to hex format method 2
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < byteData.length; i++) {
                String hex = Integer.toHexString(0xff & byteData[i]);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            System.out.println("Digest(in hex format):: " + hexString.toString());

            return hexString.toString();

        } catch (Exception e) {
            // TODO: handle exception
        }

        return "";
}
1
Ghanshyam Patidar

La conversion toHex () est bien trop inutile et prévaut dans d'autres suggestions.

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();

public static String md5string(String s) {
    return toHex(md5plain(s));
}

public static byte[] md5plain(String s) {
    final String MD5 = "MD5";
    try {
        // Create MD5 Hash
        MessageDigest digest = Java.security.MessageDigest.getInstance(MD5);
        digest.update(s.getBytes());
        return digest.digest();
    } catch (NoSuchAlgorithmException e) {
        // never happens
        e.printStackTrace();
        return null;
    }
}

public static String toHex(byte[] buf) {
    char[] hexChars = new char[buf.length * 2];
    int v;
    for (int i = 0; i < buf.length; i++) {
        v = buf[i] & 0xFF;
        hexChars[i * 2] = HEX_ARRAY[v >>> 4];
        hexChars[i * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}
0
Gena Batsyan

Veuillez utiliser SHA-512, MD5 n'est pas sécurisé

public static String getSHA512SecurePassword(String passwordToHash) {
    String generatedPassword = null;
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-512");
        md.update("everybreathyoutake".getBytes());
        byte[] bytes = md.digest(passwordToHash.getBytes());
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        generatedPassword = sb.toString();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return generatedPassword;
}

Voici la version Kotlin de @Andranik answer. Nous devons changer getBytes en toByteArray (il n'est pas nécessaire d'ajouter le jeu de caractères UTF-8 car le jeu de caractères par défaut de toByteArray est UTF-8) et le tableau cast [i]. en entier

fun String.md5(): String? {
    try {
        val md = MessageDigest.getInstance("MD5")
        val array = md.digest(this.toByteArray())
        val sb = StringBuffer()
        for (i in array.indices) {
            sb.append(Integer.toHexString(array[i].toInt() and 0xFF or 0x100).substring(1, 3))
        }
        return sb.toString()
    } catch (e: Java.security.NoSuchAlgorithmException) {
    } catch (ex: UnsupportedEncodingException) {
    }
    return null
}

J'espère que ça aide

0
Phan Van Linh

MD5 est un peu vieux, SHA-1 est un meilleur algorithme, il y a un exemple ici .

( Aussi, comme ils le notent dans ce message, Java gère cela seul, pas de code spécifique Android...) - )

0
Adam

cela fonctionne parfaitement pour moi, je l'ai utilisé pour obtenir MD5 sur un tableau LIST (puis le convertir en objet JSON), mais si vous devez seulement l'appliquer sur vos données. tapez format, remplacez JsonObject par le vôtre.

Surtout si vous avez un décalage avec python MD5, utilisez ceci!

private static String md5(List<AccelerationSensor> sensor) {

    Gson gson= new Gson();
    byte[] JsonObject = new byte[0];
    try {
        JsonObject = gson.toJson(sensor).getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    MessageDigest m = null;

    try {
        m = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    byte[] thedigest = m.digest(JsonObject);
    String hash = String.format("%032x", new BigInteger(1, thedigest));
    return hash;


}
0
mehran