MD5 puede ser inseguro como una característica de seguridad unidireccional, pero sigue siendo bueno para aplicaciones de suma de verificación genéricas.
Una cosa que no se menciona aquí, y me tomó por sorpresa. Las clases MessageDigest NO son seguras para subprocesos. Si van a ser utilizados por diferentes hilos, simplemente cree uno nuevo, en lugar de intentar reutilizarlos.
mjuarez
39
Utiliza múltiples métodos para mutar su estado interno. ¿Cómo puede ser sorprendente la falta de seguridad del hilo?
Bombe
90
@Bombe: ¿por qué deberíamos esperar a tener que saber sobre el estado interno de MessageDigest?
Dan Barowy
28
@DanBarowy bien, lo está mutando (es decir, llamando a métodos que no devuelven valores pero hacen que otros métodos devuelvan valores diferentes), por lo que hasta que se demuestre lo contrario, siempre debe suponer que no es seguro para subprocesos.
Bombe
3
@Traubenfuchs le MessageDigestpermite ingresar los datos en fragmentos. Eso no sería posible con un método estático. Aunque puede argumentar que deberían haber agregado uno de todos modos por conveniencia cuando puede pasar todos los datos a la vez.
user253751
690
La MessageDigestclase puede proporcionarle una instancia del resumen MD5.
Cuando trabaje con cadenas y las clases de cifrado, asegúrese de especificar siempre la codificación en la que desea la representación de bytes. Si solo la usa string.getBytes(), usará la plataforma predeterminada. (No todas las plataformas usan los mismos valores predeterminados)
Si tiene muchos datos, eche un vistazo al .update(byte[])método al que se puede llamar repetidamente. Luego llame .digest()para obtener el hash resultante.
"LATIN1"! = "ASCII" (o "US-ASCII"). ASCII es un conjunto de caracteres de 7 bits, Latin1 es un conjunto de caracteres de 8 bits. Ellos no son los mismos.
Este tema también es útil si necesita convertir los bytes resultantes a una cadena hexadecimal.
Weekens
1
Entonces, ¿cómo se convierte este resumen en una cadena para que podamos insertarlo en mysql?
Humphrey
2
Mejor aún, donde sea posible su uso yourString.getBytes(StandardCharsets.UTF_8). Esto evita el manejo de un UnsupportedEncodingException.
Hummeling Engineering BV
267
Si realmente desea que la respuesta se devuelva como una cadena en lugar de una matriz de bytes, siempre puede hacer algo como esto:
String plaintext ="your text here";MessageDigest m =MessageDigest.getInstance("MD5");
m.reset();
m.update(plaintext.getBytes());byte[] digest = m.digest();BigInteger bigInt =newBigInteger(1,digest);String hashtext = bigInt.toString(16);// Now we need to zero pad it if you actually want the full 32 chars.while(hashtext.length()<32){
hashtext ="0"+hashtext;}
@BalusC: No es cierto, el método BigInteger.toString devolverá el número completo en la base especificada. 0x0606 se imprimirá como 606, solo se omiten los ceros finales,
Spidey
11
Nitpick menor: m.reset () no es necesario justo después de llamar a getInstance. Más menor: 'su texto aquí' requiere comillas dobles.
David Leppik
A partir de Java 11, puede usar en hashtext = "0".repeat(32 - hashtext.length()) + hashtextlugar de while, por lo que los editores no le darán una advertencia de que está haciendo una concatenación de cadenas dentro de un bucle.
Tom
En lugar de m.update (plaintext.getBytes ()); Recomendaría especificar la codificación. como m.update (plaintext.getBytes ("UTF-8")); getBytes () no garantiza la codificación y puede variar de un sistema a otro, lo que puede dar como resultado diferentes resultados MD5 entre sistemas para la misma cadena.
user1819780
256
También es posible que desee ver la clase DigestUtils del proyecto de códec apache commons , que proporciona métodos muy convenientes para crear resúmenes MD5 o SHA.
En particular, los métodos que devuelven representaciones codificadas "seguras" de los datos de bytes en forma de cadena.
Rob
44
Sin embargo, no hay una manera fácil de obtener la clase DigestUtils en su proyecto sin agregar una tonelada de libs o portar la clase "por mano" que requiere al menos dos clases más.
iuiz
No puedo encontrarlo en repositorios de Maven tampoco. Grrrr.
sparkyspider
55
Debería estar en los repositorios centrales de Maven, a menos que me vuelva loco: groupId = commons-codec artifactId = commons-codec version = 1.5
Nick Spacek
160
Encontró esto:
publicString MD5(String md5){try{
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");byte[] array = md.digest(md5.getBytes());StringBuffer sb =newStringBuffer();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){}returnnull;}
en el sitio a continuación, no me lo atribuyo, ¡pero es una solución que funciona! Para mí, muchos otros códigos no funcionaron correctamente, terminé perdiendo ceros en el hash. Este parece ser el mismo que PHP tiene. fuente: http://m2tec.be/blog/2010/02/03/java-md5-hex-0093
Debe especificar la codificación que se utilizará getBytes(), de lo contrario su código obtendrá resultados diferentes en diferentes plataformas / configuraciones de usuario.
Paŭlo Ebermann
@ PaŭloEbermann hace MessageDigest.getInstance ("MD5"); ¿no es suficiente? Traté de agregar "MD5" en getBytes () pero me devolvió un error
Blaze Tama
2
@BlazeTama "MD5" no es una codificación, es un algoritmo de resumen de mensajes (y no uno que deba usarse en nuevas aplicaciones). Una codificación es un par de algoritmos que transforma bytes en cadenas y cadenas en bytes. Un ejemplo sería "UTF-8", "US-ASCII", "ISO-8859-1", "UTF-16BE" y similares. Use la misma codificación que cualquier otra parte que calcule un hash de esta cadena, de lo contrario obtendrá resultados diferentes.
Paŭlo Ebermann
66
Para un ejemplo del conjunto de caracteres ... (use UTF-8, que es el mejor y más compatible en mi opinión) ... byte[] array = md.digest(md5.getBytes(Charset.forName("UTF-8")));
Richard
Como no es mi solución, y no probé todos los escenarios yo mismo, lo dejaré sin cambios, aunque creo que especificar codificación, etc., probablemente sea una buena idea.
dac2009
88
Así es como lo uso:
finalMessageDigest messageDigest =MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(string.getBytes(Charset.forName("UTF8")));finalbyte[] resultByte = messageDigest.digest();finalString result =newString(Hex.encodeHex(resultByte));
Este es el método que proporciona el mismo valor de retorno que la función MySQL md5 (str). Muchas de las otras respuestas devolvieron otros valores.
rwitzel
1
Esto no funciona bien en Android porque Android agrupa commons-codec 1.2, para lo cual necesita esta solución alternativa: stackoverflow.com/a/9284092/2413303
EpicPandaForce
76
He descubierto que esta es la forma más clara y concisa de hacerlo:
Excelente. No cae en la trampa de cortar ceros a la izquierda.
Markus Pscheidt
2
Tenga en cuenta que esto no funcionará para Android si está utilizando el nivel de API <19, pero solo necesita cambiar la segunda línea con md5.update (string.getBytes ("UTF-8")); Sin embargo, esto agregará otra excepción marcada para manejar ...
Fran Marzoa
34
Encontré esta solución que es mucho más limpia en términos de recuperar una representación de cadena de un hash MD5.
import java.security.*;import java.math.*;publicclass MD5 {publicstaticvoid main(String args[])throwsException{String s="This is a test";MessageDigest m=MessageDigest.getInstance("MD5");
m.update(s.getBytes(),0,s.length());System.out.println("MD5: "+newBigInteger(1,m.digest()).toString(16));}}
¿Por qué tiene esta respuesta -1 mientras que la otra, más corta y menos descriptiva, tiene +146?
Nilzor
44
Agradable usar BigInteger para obtener un valor hexadecimal +1
Dave.B
55
Me acabo de
enterar de
3
@kovica esto se debe a que los ceros iniciales se truncan si no recuerdo mal. String.format("%032x", new BigInteger(1, hash)); Esto debería resolver esto. 'hash' es el byte [] del hash.
Heshan Perera
¡Esta respuesta tiene error con el tipo de juego de caracteres!
Solo he visto una frase que no usa una biblioteca externa.
holmis83
A menos que me equivoque, esto vuelve siempre en mayúscula, lo que no se alineará con md5 sin usar hexadecimal. Ni siquiera estoy seguro de que sea un verdadero md5
walshie4
2
@ walshie4 no hay MD5 sin hexadecimal (vea ietf.org/rfc/rfc1321.txt ), para obtenerlo en minúsculas simplemente agregue .toLower (). Compare los resultados con los ejemplos en, por ejemplo, en.wikipedia.org/wiki/MD5, entonces tendrá una mejor oportunidad de creer que el código de la biblioteca Javas es correcto.
apilador
28
Tengo una clase (Hash) para convertir texto sin formato en hash en formatos: md5 o sha1, similar a las funciones de php ( md5 , sha1 ):
publicclassHash{/**
*
* @param txt, text in plain format
* @param hashType MD5 OR SHA1
* @return hash in hashType
*/publicstaticString getHash(String txt,String hashType){try{
java.security.MessageDigest md = java.security.MessageDigest.getInstance(hashType);byte[] array = md.digest(txt.getBytes());StringBuffer sb =newStringBuffer();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){//error action}returnnull;}publicstaticString md5(String txt){returnHash.getHash(txt,"MD5");}publicstaticString sha1(String txt){returnHash.getHash(txt,"SHA1");}}
La respuesta de Bombe es correcta, sin embargo, tenga en cuenta que, a menos que deba usar MD5 (por ejemplo, forzado para la interoperabilidad), una mejor opción es SHA1 ya que MD5 tiene debilidades para el uso a largo plazo.
Debo agregar que SHA1 también tiene vulnerabilidades teóricas, pero no tan graves. El estado actual de la técnica en hashing es que hay varias funciones de hash de reemplazo de candidatos, pero ninguna ha surgido como la mejor práctica estándar para reemplazar SHA1. Por lo tanto, dependiendo de sus necesidades, le recomendamos que configure su algoritmo hash para que pueda ser reemplazado en el futuro.
¿Podría indicarme algunos recursos, donde puedo leer sobre los méritos y debilidades relativas de cada uno?
Akshay
Probablemente lo mejor que puede hacer en este momento es usar SHA1 y estar listo para reemplazarlo en el futuro. Podría usar funciones más nuevas, pero aún no han sido objeto de grandes investigaciones. Puede realizar un seguimiento de los recursos de seguridad en línea para saber cuándo cambia esto, por ejemplo, el blog de Bruce Schneier.
frankodwyer
77
SHA1 es excesivo a menos que desee un hash criptográficamente seguro, es decir, no quiere que el hash le ayude a reconstruir el mensaje original, ni desea que un atacante inteligente cree otro mensaje que coincida con el hash. Si el original no es un secreto y el hash no se usa para seguridad, MD5 es rápido y fácil. Por ejemplo, Google Web Toolkit utiliza hashes MD5 en URL de JavaScript (por ejemplo, foo.js? Hash = 12345).
Esta es una biblioteca sólida e independiente con dependencias mínimas. Buen material.
Ajax
Lo encontré muy útil. Tomó 15357 ms para un archivo de 4.57GB, mientras que la implementación incorporada de Java tomó 19094 ms.
bkrish
11
No sé si esto es relevante para alguien que lea esto, pero acabo de tener el problema que quería
descargar un archivo desde una URL dada y
compare su MD5 con un valor conocido.
Quería hacerlo solo con las clases JRE (no Apache Commons o similar). Una búsqueda rápida en la web no me mostró fragmentos de código de muestra haciendo ambas cosas al mismo tiempo, solo cada tarea por separado. Debido a que esto requiere leer el mismo archivo dos veces, pensé que valdría la pena escribir un código que unifique ambas tareas, calculando la suma de verificación sobre la marcha mientras descarga el archivo. Este es mi resultado (perdón si no es Java perfecto, pero supongo que de todos modos tienes la idea):
Ah, por cierto, antes de que nadie, excepto yo mismo, note cuán malo es realmente mi conocimiento de JRE: acabo de descubrir DigestInputStream y DigestOutputStream . Voy a editar mi solución original para reflejar lo que acabo de aprender.
kriegaex
6
Eche un vistazo al siguiente enlace, el ejemplo obtiene un hash MD5 de una imagen suministrada:
hash MD5 de una imagen
Por lo que vale, me topé con esto porque quiero sintetizar GUID a partir de una clave natural para un programa que instalará componentes COM; Quiero sintetizar para no administrar el ciclo de vida GUID. Usaré MD5 y luego usaré la clase UUID para obtener una cadena. (http://stackoverflow.com/questions/2190890/how-can-i-generate-guid-for-a-string-values/12867439 plantea este problema).
En cualquier caso, java.util.UUID puede obtener una buena cadena de los bytes MD5.
en realidad acepta no solo la matriz de bytes MD5 (tamaño == 16). Puede pasar una matriz de bytes de cualquier longitud. Se convertirá en una matriz de bytes MD5 por medio de MD5 MessageDigest(consulte el código fuente nameUUIDFromBytes () )
A diferencia de PHP, donde puede hacer un hash MD5 de su texto simplemente llamando a la función md5, es decir md5($text), en Java se hizo un poco complicado. Por lo general, lo implementé llamando a una función que devuelve el texto hash md5. Así es como lo implementé, primero cree una función nombrada md5hashingdentro de su clase principal como se muestra a continuación.
publicstaticString md5hashing(String text){String hashtext =null;try{String plaintext = text;MessageDigest m =MessageDigest.getInstance("MD5");
m.reset();
m.update(plaintext.getBytes());byte[] digest = m.digest();BigInteger bigInt =newBigInteger(1,digest);
hashtext = bigInt.toString(16);// Now we need to zero pad it if you actually want the full 32 chars.while(hashtext.length()<32){
hashtext ="0"+hashtext;}}catch(Exception e1){// TODO: handle exceptionJOptionPane.showMessageDialog(null,e1.getClass().getName()+": "+ e1.getMessage());}return hashtext;}
Ahora llame a la función siempre que lo necesite como se indica a continuación.
String text = textFieldName.getText();String pass = md5hashing(text);
Aquí puede ver que el hashtext se agrega con un cero para que coincida con el hash md5 en PHP.
MD5 está perfectamente bien si no necesita la mejor seguridad y si está haciendo algo como verificar la integridad del archivo, entonces la seguridad no es una consideración. En tal caso, es posible que desee considerar algo más simple y rápido, como Adler32, que también es compatible con las bibliotecas de Java.
¿Qué te hace pensar que la integridad del archivo no es un problema de seguridad?
Jeremy Huiskamp
5
este da el md5 exacto que obtienes de la función md5 de mysql o las funciones md5 de php, etc. Este es el que uso (puedes cambiar según tus necesidades)
Esta es probablemente la peor solución, ya que elimina los ceros iniciales.
Jannick
4
import java.security.MessageDigest
val digest =MessageDigest.getInstance("MD5")//Quick MD5 of text
val text ="MD5 this text!"
val md5hash1 = digest.digest(text.getBytes).map("%02x".format(_)).mkString
//MD5 of text with updates
digest.update("MD5 ".getBytes())
digest.update("this ".getBytes())
digest.update("text!".getBytes())
val md5hash2 = digest.digest().map(0xFF& _).map("%02x".format(_)).mkString
//Output
println(md5hash1 +" should be the same as "+ md5hash2)
Puede generar hash MD5 para un texto dado haciendo uso de los métodos de la MessageDigestclase en el java.securitypaquete. A continuación se muestra el fragmento de código completo,
La salida de la función MD5 es un hash de 128 bits representado por 32 números hexadecimales.
En el caso, si está utilizando una base de datos como MySQL, también puede hacerlo de una manera más simple. La consulta Select MD5(“text here”)devolverá el hash MD5 del texto en el paréntesis.
Respuestas:
Es necesario
java.security.MessageDigest
.Llame
MessageDigest.getInstance("MD5")
para obtener una instancia de MD5MessageDigest
que pueda usar.Calcule el hash haciendo uno de:
byte[]
y calcule el hash en una operación conmd.digest(bytes)
.MessageDigest
unbyte[]
trozo a la vez llamandomd.update(bytes)
. Cuando termine de agregar bytes de entrada, calcule el hash conmd.digest()
.El
byte[]
devuelto pormd.digest()
es el hash MD5.fuente
MessageDigest
permite ingresar los datos en fragmentos. Eso no sería posible con un método estático. Aunque puede argumentar que deberían haber agregado uno de todos modos por conveniencia cuando puede pasar todos los datos a la vez.La
MessageDigest
clase puede proporcionarle una instancia del resumen MD5.Cuando trabaje con cadenas y las clases de cifrado, asegúrese de especificar siempre la codificación en la que desea la representación de bytes. Si solo la usa
string.getBytes()
, usará la plataforma predeterminada. (No todas las plataformas usan los mismos valores predeterminados)Si tiene muchos datos, eche un vistazo al
.update(byte[])
método al que se puede llamar repetidamente. Luego llame.digest()
para obtener el hash resultante.fuente
yourString.getBytes(StandardCharsets.UTF_8)
. Esto evita el manejo de unUnsupportedEncodingException
.Si realmente desea que la respuesta se devuelva como una cadena en lugar de una matriz de bytes, siempre puede hacer algo como esto:
fuente
hashtext = "0".repeat(32 - hashtext.length()) + hashtext
lugar dewhile
, por lo que los editores no le darán una advertencia de que está haciendo una concatenación de cadenas dentro de un bucle.También es posible que desee ver la clase DigestUtils del proyecto de códec apache commons , que proporciona métodos muy convenientes para crear resúmenes MD5 o SHA.
fuente
Encontró esto:
en el sitio a continuación, no me lo atribuyo, ¡pero es una solución que funciona! Para mí, muchos otros códigos no funcionaron correctamente, terminé perdiendo ceros en el hash. Este parece ser el mismo que PHP tiene. fuente: http://m2tec.be/blog/2010/02/03/java-md5-hex-0093
fuente
getBytes()
, de lo contrario su código obtendrá resultados diferentes en diferentes plataformas / configuraciones de usuario.byte[] array = md.digest(md5.getBytes(Charset.forName("UTF-8")));
Así es como lo uso:
donde está Hex:
org.apache.commons.codec.binary.Hex
del proyecto Apache Commons .fuente
String result = Hex.encodeHexString(resultByte);
Acabo de descargar commons-codec.jar y obtuve php perfecto como md5. Aquí está el manual .
Solo impórtalo a tu proyecto y úsalo
Y ahí lo tienes.
fuente
He descubierto que esta es la forma más clara y concisa de hacerlo:
fuente
Encontré esta solución que es mucho más limpia en términos de recuperar una representación de cadena de un hash MD5.
El código fue extraído de aquí .
fuente
String.format("%032x", new BigInteger(1, hash));
Esto debería resolver esto. 'hash' es el byte [] del hash.Otra opción es utilizar los métodos Hashing de guayaba :
Práctico si ya está usando Guava (que si no lo está, probablemente debería estarlo).
fuente
Hashing.md5().hashString("my string").asBytes();
Otra implementación:
fuente
Tengo una clase (Hash) para convertir texto sin formato en hash en formatos: md5 o sha1, similar a las funciones de php ( md5 , sha1 ):
Pruebas con JUnit y PHP
Script PHP:
Script PHP de salida:
Usando ejemplos y pruebas con JUnit:
Código en GitHub
fuente
No hay necesidad de hacerlo demasiado complicado.
DigestUtils funciona bien y te hace sentir cómodo mientras trabajas con
md5
hashes.o
Puede utilizar cualquier otro método de cifrado como
sha
omd
.fuente
Mi respuesta no muy reveladora:
fuente
String.format("%1$032X", big)
tener un formato en mayúsculaTambién hay una
DigestUtils
clase en primavera :http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/util/DigestUtils.html
Esta clase contiene el método
md5DigestAsHex()
que hace el trabajo.fuente
Puedes intentar seguir. Vea los detalles y los códigos de descarga aquí: http://jkssweetlife.com/java-hashgenerator-md5-sha-1/
fuente
La respuesta de Bombe es correcta, sin embargo, tenga en cuenta que, a menos que deba usar MD5 (por ejemplo, forzado para la interoperabilidad), una mejor opción es SHA1 ya que MD5 tiene debilidades para el uso a largo plazo.
Debo agregar que SHA1 también tiene vulnerabilidades teóricas, pero no tan graves. El estado actual de la técnica en hashing es que hay varias funciones de hash de reemplazo de candidatos, pero ninguna ha surgido como la mejor práctica estándar para reemplazar SHA1. Por lo tanto, dependiendo de sus necesidades, le recomendamos que configure su algoritmo hash para que pueda ser reemplazado en el futuro.
fuente
Otra implementación: Implementación rápida de MD5 en Java
fuente
No sé si esto es relevante para alguien que lea esto, pero acabo de tener el problema que quería
Quería hacerlo solo con las clases JRE (no Apache Commons o similar). Una búsqueda rápida en la web no me mostró fragmentos de código de muestra haciendo ambas cosas al mismo tiempo, solo cada tarea por separado. Debido a que esto requiere leer el mismo archivo dos veces, pensé que valdría la pena escribir un código que unifique ambas tareas, calculando la suma de verificación sobre la marcha mientras descarga el archivo. Este es mi resultado (perdón si no es Java perfecto, pero supongo que de todos modos tienes la idea):
fuente
Eche un vistazo al siguiente enlace, el ejemplo obtiene un hash MD5 de una imagen suministrada: hash MD5 de una imagen
fuente
Por lo que vale, me topé con esto porque quiero sintetizar GUID a partir de una clave natural para un programa que instalará componentes COM; Quiero sintetizar para no administrar el ciclo de vida GUID. Usaré MD5 y luego usaré la clase UUID para obtener una cadena. (http://stackoverflow.com/questions/2190890/how-can-i-generate-guid-for-a-string-values/12867439 plantea este problema).
En cualquier caso, java.util.UUID puede obtener una buena cadena de los bytes MD5.
fuente
MessageDigest
(consulte el código fuente nameUUIDFromBytes () )fuente
A diferencia de PHP, donde puede hacer un hash MD5 de su texto simplemente llamando a la función md5, es decir
md5($text)
, en Java se hizo un poco complicado. Por lo general, lo implementé llamando a una función que devuelve el texto hash md5. Así es como lo implementé, primero cree una función nombradamd5hashing
dentro de su clase principal como se muestra a continuación.Ahora llame a la función siempre que lo necesite como se indica a continuación.
Aquí puede ver que el hashtext se agrega con un cero para que coincida con el hash md5 en PHP.
fuente
MD5 está perfectamente bien si no necesita la mejor seguridad y si está haciendo algo como verificar la integridad del archivo, entonces la seguridad no es una consideración. En tal caso, es posible que desee considerar algo más simple y rápido, como Adler32, que también es compatible con las bibliotecas de Java.
fuente
este da el md5 exacto que obtienes de la función md5 de mysql o las funciones md5 de php, etc. Este es el que uso (puedes cambiar según tus necesidades)
fuente
prueba esto:
fuente
fuente
Puede generar hash MD5 para un texto dado haciendo uso de los métodos de la
MessageDigest
clase en eljava.security
paquete. A continuación se muestra el fragmento de código completo,La salida de la función MD5 es un hash de 128 bits representado por 32 números hexadecimales.
En el caso, si está utilizando una base de datos como MySQL, también puede hacerlo de una manera más simple. La consulta
Select MD5(“text here”)
devolverá el hash MD5 del texto en el paréntesis.fuente
Esto es para lo que vine aquí: una práctica función de escala que devuelve una cadena de hash MD5:
fuente
Hay un artículo en Codingkit sobre eso. Echa un vistazo: http://codingkit.com/a/JAVA/2013/1020/2216.html
fuente