2011-06-07 33 views
5

Tengo que generar hash Sha256 de datos que están en forma de little endian. Me gustaría saber si primero tengo que convertirlo a big endian, antes de usar el algoritmo sha 256. O si, el algoritmo es "endian-agnóstico".Little endian data y sha 256

EDIT: Perdón, creo que no estaba claro. Lo que me gustaría saber es lo siguiente: El algoritmo sha256 requiere rellenar el final de un mensaje con ciertos bits. El primer paso es agregar un 1 al final del mensaje. Luego, rellenarlo con cero hasta el final. Al final, debe agregar la longitud del mensaje en bits. Lo que me gustaría saber es si este relleno se puede realizar en little endian. Por ejemplo, para un mensaje de 640 bits, podría escribir la última palabra como 0x280 (en big endian) o 0x8002000 (en little endian). ¿Este relleno se puede hacer en little endian?

+1

Esto es complicado ... aunque en general, SHA no se preocupa por orden de bits. Para el hash, cualquier entrada es un múltiplo de bloques de 512 bits de "blob" binario (si es necesario, agregará relleno). Hasta el momento, la endianidad es insignificante. Por otro lado, si tienes por ejemplo una 'struct' una vez en poco y una vez en big endian, y las hash, por supuesto producirán hash diferentes. Pero eso se debe a que son datos binarios diferentes, no porque le importe el hash. – Damon

+0

@Damon: sí, buen punto. – Heisenbug

+0

Por favor, mira mi edición –

Respuesta

2

La implementación de SHA-256 debe ocuparse del relleno, no debería tener que lidiar con eso a menos que esté implementando su propio código SHA-256 especializado. Si es así, tenga en cuenta que las reglas de relleno especificadas en el "paso de preprocesamiento" dicen que la longitud es un entero de 64 bits de big-endian. Ver SHA-2 - Wikipedia

Es difícil siquiera imaginar qué significaría "agnóstico endian", pero el orden de todos los bits, bytes y palabras para un algoritmo hash es muy importante, así que estoy seguro de que no usaría ese término .

5

SHA256 es endian-agnostic si todo lo que quiere es un buen hash. Pero si está escribiendo SHA256 y quiere los mismos resultados con una implementación correcta, entonces debe jugar juegos en hardware little endian. SHA256 combina la suma aritmética (mod 2 * 32) y la operación booleana no es endian-agnóstica internamente.

1

Déjenme responder con respecto a sha 256 así como a sha 512. en resumen: El algoritmo en sí es independiente de Endian. Las partes sensibles endian son cuando los datos se importan desde un búfer de bytes a las variables de trabajo del algoritmo y cuando se exportan al resultado del resumen, también un búfer de bytes. Si la importación/exportación incluye fundición, entonces endian importa.

Donde podría ocurrir el fundido: En sha 512 hay un buffer de trabajo de 128 bytes. En mi código de su definen así:

union 
    { 
     U64 w [80]; (see U64 example below) 
     byte buffer [128]; 
    }; 

Los datos de entrada se copia en el búfer de bytes y luego el trabajo se realiza en W. Esto significa que los datos se coló a algún tipo de 64 bits. Esta información deberá ser intercambiada. en mi caso es intercambiado por pequeñas máquinas endian.

Un mejor método sería preparar una macro get que tome cada byte y colocarlo en su lugar correcto en el tipo u64.

Cuando se realiza el algoritmo, el resultado del resumen se envía desde las variables de trabajo a un búfer de bytes, si esto se hace mediante memcpy, también deberá intercambiarse.

Se puede producir otro lanzamiento al implementar sha 512, que está diseñado para máquinas de 64 bits, en máquinas de 32 bits.En mi caso tengo un tipo de 64 bits que se define:

typedef struct { 
     uint high; 
     uint low; 
    } U64; 

asume que defino por poco endian, así, de la siguiente manera:

typedef struct { 
     uint low; 
     uint high; 
    } U64; 

Y entonces el init k algoritmo se hace de la siguiente :

static const SHA_U64 k[80] = 
    { 
     {0xD728AE22, 0x428A2F98}, {0x23EF65CD, 0x71374491}, ... 
     ... 
     ... 
    } 

Pero necesito que el valor lógico de k [0] .high sea el mismo en cualquier máquina. Por lo tanto, en este ejemplo necesitaré otra matriz K con valores altos y bajos intercambiados.

Después de almacenar los datos en los parámetros de trabajo, cualquier manipulación bit a bit tendría el mismo resultado en ambas máquinas endian grandes/pequeñas.

Un buen método sería evitar cualquier conversión: Importar bytes desde el búfer de entrada a sus parámetros de trabajo usando macro. Trabaja con valores lógicos sin pensar en la asignación de memoria. Exportar salida para digerir el resultado con una macro.

Macro para tomar 32 bits desde una memoria intermedia de bytes a int32 (BE = big endian):

#define GET_BE_BYTES_FROM32(a) 
    ((((NQ_UINT32) (a)[0]) << 24) | 
    (((NQ_UINT32) (a)[1]) << 16) | 
    (((NQ_UINT32) (a)[2]) << 8) | 
    ((NQ_UINT32) (a)[3])) 

    #define GET_LE_BYTES_FROM32(a) 
    ((((NQ_UINT32) (a)[3]) << 24) | 
    (((NQ_UINT32) (a)[2]) << 16) | 
    (((NQ_UINT32) (a)[1]) << 8) | 
    ((NQ_UINT32) (a)[0])) 
Cuestiones relacionadas