Cadena de Java para SHA1

Estoy intentando hacer un convertidor String a SHA1 simple en Java y esto es lo que tengo …

public static String toSHA1(byte[] convertme) { MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-1"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } return new String(md.digest(convertme)); } 

Cuando lo paso toSHA1("password".getBytes()) , obtengo “[ a ɹ ?? % l 3 ~ .” Sé que probablemente sea una solución de encoding simple como UTF-8, pero ¿alguien podría decirme qué debo hacer para obtener lo que quiero que sea “5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8”? ¿O estoy haciendo esto completamente mal?

¡Muchas gracias!

ACTUALIZAR
Puede usar Apache Commons Codec (versión 1.7+) para hacer este trabajo por usted.

  DigestUtils.sha1Hex (stringToConvertToSHexRepresentation) 

Gracias a @ Jon Onstott por esta sugerencia.


Vieja respuesta
Convierte tu matriz de bytes a Hex String. Real’s How te dice cómo .

 return byteArrayToHexString(md.digest(convertme)) 

y (copiado de Real’s How)

 public static String byteArrayToHexString(byte[] b) { String result = ""; for (int i=0; i < b.length; i++) { result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 ); } return result; } 

Por cierto, puede obtener una representación más compacta usando Base64. Apache Commons Codec API 1.4 , tiene esta buena utilidad para eliminar todo el dolor. refiérase aquí

Esta es mi solución para convertir cadenas a sha1. Funciona bien en mi aplicación de Android:

 private static String encryptPassword(String password) { String sha1 = ""; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); sha1 = byteToHex(crypt.digest()); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } catch(UnsupportedEncodingException e) { e.printStackTrace(); } return sha1; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } 

Usando la clase de Hash de Guava :

 Hashing.sha1().hashString( "password", Charsets.UTF_8 ).toString() 

SHA-1 (y todos los demás algoritmos hash) devuelven datos binarios. Eso significa que (en Java) producen un byte[] . Esa matriz de byte no representa ningún carácter específico, lo que significa que no puedes simplemente convertirla en una String como lo hiciste.

Si necesita un String , debe formatear ese byte[] de una manera que pueda representarse como String (de lo contrario, simplemente mantenga el byte[] alrededor).

Dos formas comunes de representar byte[] arbitrarios byte[] como caracteres imprimibles son BASE64 o simples cadenas hexagonales (es decir, representa cada byte por dos dígitos hexadecimales). Parece que estás intentando producir un hex-String.

También hay otro inconveniente: si desea obtener el SHA-1 de un Java String , entonces necesita convertir ese String en un byte[] primero (ya que la entrada de SHA-1 también es un byte[] ). Si simplemente usa myString.getBytes() como mostró, entonces usará la encoding predeterminada de la plataforma y, como tal, dependerá del entorno en el que lo ejecute (por ejemplo, podría devolver datos diferentes en función de la configuración de idioma / configuración regional de su sistema operativo).

Una mejor solución es especificar la encoding que se utilizará para la conversión String -to- byte[] como esta: myString.getBytes("UTF-8") . Elegir UTF-8 (u otra encoding que pueda representar cada carácter Unicode) es la opción más segura aquí.

Simplemente use la biblioteca de códec de Apache commons. Tienen una clase de utilidad llamada DigestUtils

No es necesario entrar en detalles.

Esta es una solución simple que se puede usar al convertir una cadena a un formato hexadecimal:

 private static String encryptPassword(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(password.getBytes("UTF-8")); return new BigInteger(1, crypt.digest()).toString(16); } 

Como se mencionó anteriormente, use el códec de Apache commons. También es recomendado por los chicos de Spring (ver DigestUtils en Spring doc). P.ej:

 DigestUtils.sha1Hex(b); 

Definitivamente no usaría la respuesta mejor calificada aquí.

No se está imprimiendo correctamente porque necesita usar encoding Base64. Con Java 8 puede codificar utilizando la clase de codificador Base64 .

 public static String toSHA1(byte[] convertme) { md = MessageDigest.getInstance("SHA-1"); return Base64.getEncoder().encodeToString((md.digest(convertme)); } 

Resultado

Esto le dará su salida esperada de 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8

La razón por la que esto no funciona es que cuando llamas a String(md.digest(convertme)) , le estás diciendo a Java que interprete una secuencia de bytes cifrados como una Cadena. Lo que quiere es convertir los bytes en caracteres hexadecimales.

Convierte la matriz de bytes a una cadena hexadecimal.

 public static String toSHA1(byte[] convertme) { final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); MessageDigest md = null; try { md = MessageDigest.getInstance("SHA-1"); } catch(NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] buf = md.digest(convertme); char[] chars = new char[2 * buf.length]; for (int i = 0; i < buf.length; ++i) { chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4]; chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F]; } return new String(chars); } 

Representación de base 64 de Hash SHA1 :

 String hashedVal = Base64.getEncoder().encodeToString(DigestUtils.sha1(stringValue.getBytes(Charset.forName("UTF-8"))));