Hash MD5 en Android

Tengo un cliente de Android simple que necesita ‘hablar’ con un simple oyente HTTP C #. Deseo proporcionar un nivel básico de autenticación pasando el nombre de usuario / contraseña en las solicitudes POST.

El hash MD5 es trivial en C # y proporciona suficiente seguridad para mis necesidades, pero parece que no puedo encontrar cómo hacerlo en el extremo de Android.

EDITAR: solo para abordar las preocupaciones planteadas sobre la debilidad de MD5: el servidor C # se ejecuta en las PC de los usuarios de mi cliente de Android. En muchos casos, accederán al servidor usando wi-fi en sus propias LAN pero, bajo su propio riesgo, pueden optar por acceder a él desde Internet. Además, el servicio en el servidor necesita utilizar el traspaso para el MD5 a una aplicación de terceros sobre la que no tengo control.

Aquí hay una implementación que puede usar (actualizada para usar convenciones de Java más actualizadas for:each bucle, StringBuilder lugar 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 ""; } 

Aunque no se recomienda para sistemas que involucran incluso el nivel básico de seguridad (MD5 se considera dañado y puede explotarse fácilmente ), a veces es suficiente para tareas básicas.

La respuesta aceptada no funcionó para mí en Android 2.2. No sé por qué, pero estaba “comiendo” algunos de mis ceros (0). Apache commons tampoco funcionó en Android 2.2, ya que utiliza métodos que solo son compatibles a partir de Android 2.3.x. Además, si desea solo MD5 una cadena, Apache commons es demasiado complejo para eso. ¿Por qué uno debería mantener una biblioteca completa para usar solo una pequeña función de ella …?

Finalmente encontré el siguiente fragmento de código aquí que funcionó perfectamente para mí. Espero que sea útil para alguien …

 public String MD5(String md5) { try { java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); byte[] array = md.digest(md5.getBytes()); 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) { } return null; } 

El código de androidsnippets.com no funciona de manera confiable porque los 0 parecen cortados del hash resultante.

Una mejor implementación está aquí .

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

Si usar Apache Commons Codec es una opción, entonces esta sería una implementación más corta:

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

O SHA:

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

Fuente para arriba.

Siga el enlace y vote su solución para otorgarle la persona correcta.


Enlace de repository Maven: https://mvnrepository.com/artifact/commons-codec/commons-codec

Dependencia actual de Maven (desde el 6 de julio de 2016):

   commons-codec commons-codec 1.10  

Una solución anterior usando DigestUtils no funcionó para mí. En mi versión de Apache commons (la última para 2013) no existe tal clase.

Encontré otra solución aquí en un blog . Funciona perfecto y no necesita los recursos comunes de Apache. Se ve un poco más corto que el código en la respuesta aceptada anteriormente.

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

Necesitarás estas importaciones:

 import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; 

Esta es una pequeña variación de las respuestas de Andranik y Den Delimarsky, pero es un poco más conciso y no requiere ninguna lógica bit a bit. En su lugar, utiliza el método String.format para convertir los bytes en dos cadenas hexadecimales de caracteres (no elimina los 0). Normalmente solo comentaría sus respuestas, pero no tengo la reputación de hacerlo.

 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 desea devolver una cadena de minúsculas, simplemente cambie %02X a %02x .

Editar: Usando BigInteger como con la respuesta de wzbozon, puede hacer que la respuesta sea aún más concisa:

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

MD5 es un poco viejo, SHA-1 es un mejor algoritmo, aquí hay un ejemplo .

( Además, como señalan en esa publicación, Java maneja esto por sí mismo, sin código específico de Android ) .

En nuestra aplicación MVC generamos param largo

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

y lo mismo en la aplicación de Android (thenk ayuda a 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(); } 

He hecho una biblioteca simple en Kotlin.

Agregar a Root build.gradle

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

en la aplicación build.gradle

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

Uso

En Kotlin

 val ob = Hasher() 

Luego use el método hash ()

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

Devolverá MD5 y SHA-1 respectivamente.

Más sobre la biblioteca

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

He usado el método de abajo para darme md5 pasando la secuencia para la cual quieres obtener 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 ""; } 

Demasiado inútil para la conversión de Hex () prevalece en otras sugerencias, realmente.

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

Las soluciones proporcionadas para el lenguaje Scala (un poco más corto):

 def getMd5(content: Array[Byte]) = try { val md = MessageDigest.getInstance("MD5") val bytes = md.digest(content) bytes.map(b => Integer.toHexString((b + 0x100) % 0x100)).mkString } catch { case ex: Throwable => null }