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]))
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
@Damon: sí, buen punto. – Heisenbug
Por favor, mira mi edición –