2010-06-11 13 views
23

Cuando calculo en Java un SHA-256 de una cadena con el siguiente método¿Qué SHA-256 es correcto? El Java SHA-256 digestión o la línea de comandos de Linux herramienta

public static void main(String[] args) throws NoSuchAlgorithmException { 

    MessageDigest md = MessageDigest.getInstance("SHA-256"); 

    byte[] hash = md.digest("password".getBytes()); 

    StringBuffer sb = new StringBuffer(); 
    for(byte b : hash) { 
     sb.append(Integer.toHexString(b & 0xff)); 
    } 

    System.out.println(sb.toString()); 
} 

me sale:

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8 

en la línea de comandos I hacer lo siguiente (necesito el -n para no añadir un salto de línea):

echo -n "password" | sha256sum 

y obtener

5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 

si comparamos estos más de cerca Encuentro 2 sutiles diferencias

5e884898da2847151d0e56f8dc6292773603dd6aabbdd62a11ef721d1542d8 
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8 

o:

5e884898da28 47151d0e56f8dc6292773603d d6aabbdd62a11ef721d1542d8 
5e884898da28 0 47151d0e56f8dc6292773603d 0 d6aabbdd62a11ef721d1542d8 

¿Cuál de los 2 es correcto en este caso?

Resultado: Ambos son, pero estaba mal ...

fija mediante el uso de:

StringBuffer sb = new StringBuffer(); 
    for(byte b : hash) { 
     sb.append(String.format("%02x", b)); 
    } 

Gracias!

Respuesta

26

Haré una conjetura razonable: ambos están produciendo el mismo resumen, pero en su código Java que emite el resultado byte[] como una cadena hexadecimal, se obtienen valores de bytes pequeños (menos de 16) sin una 0. un byte con el valor "0x0d" se escribe como "d" no como "0d".

+0

Sí, acabo de ver su actualización con código - este es el problema. 'Integer.toHexString()' no escribirá el 0 principal. Podría ser más fácil solo para los valores de casos especiales menores que 16 y escribir un '0' al frente. –

+0

¡Tonto! ¡Gracias por la rápida respuesta! Acabo de tener suerte con mi implementación de MD5. Great save ... –

9

El culpable es el toHexString. Parece que está produciendo 6 para el valor 6, mientras que sha256sum está produciendo 06. La documentación de Java para Integer.toHexString() Estado:

Este valor se convierte en una cadena de dígitos ASCII en hexadecimal (base 16) sin 0s principales adicionales.

Los otros ceros en la cadena no se ven afectados ya que son la segunda mitad de los bytes (por ejemplo, 30).

Una forma de solucionarlo sería cambiar:

for(byte b : hash) { 
    sb.append(Integer.toHexString(b & 0xff)); 
} 

a:

for(byte b : hash) { 
    if (b < 16) sb.append("0"); 
    sb.append(Integer.toHexString(b & 0xff)); 
} 
1

la generada por sha256sum parece correcta. Su implementación parece dejar esos dos ceros.

6

Ambos tienen razón; es su código Java el que tiene la culpa, porque no está imprimiendo el 0 inicial para un valor hexadecimal menor que 0x10.

3

Todavía es necesario "echo -n" para evitar el arrastre \ n

1

Usando @paxdiablo idea tenía un problema con el número grande de lo que aparece como negativo, de modo

En lugar de:

for(byte b : hash) { 
    sb.append(Integer.toHexString(b & 0xff)); 
} 

que podría hacer:

for(byte b : hash) { 
    if (b > 0 && b < 16) { 
     sb.append("0"); 
    } 
    sb.append(Integer.toHexString(b & 0xff)); 
} 

Y leer @Sean Owen respuesta.

0

También puede obtener el resultado correcto uso de este:

MessageDigest md = MessageDigest.getInstance("SHA-256"); 

byte[] hash = md.digest("password".getBytes()); 

BigInteger bI = new BigInteger(1, hash); 

System.out.println(bI.toString(16)); 
+1

No, este código sigue siendo incorrecto. BigInteger.toString (16) no contendrá ceros a la izquierda. – Nayuki

Cuestiones relacionadas