UC-IIC3253 / 2021

Repositorio del curso Criptografı́a y Seguridad Computacional - IIC3253
21 stars 3 forks source link

[Tarea 1] duda parte final del padding para MD5 #9

Open johntrombon opened 3 years ago

johntrombon commented 3 years ago

Hola, respecto al padding de md5, entiendo que hay que concatenar el mensaje con un bit "1" y luego suficientes bits cosa que quede de largo 448 (mod 512). Finalmente, hay que terminar concatenándole 64 bits que representan el largo original del mensaje (mod 2**64). Mi duda es: ¿de que forma representamos dicho largo para que quede en 64 bits? Por ejemplo, supongamos que el largo del mensaje original 0xABCD en hexadecimal: los 64 bits añadidos son 0x000000000000ABCD ? 0xABCD000000000000 ? 0x0000ABCD00000000 ? (dos words de 32 bits) Estoy asumiendo que se usa big-endian, creo :sweat_smile: Gracias de antemano.

mugartec commented 3 years ago

EDIT: Importante, todos los valores de MD5 son little-endian incluyendo los 64 bits del largo del mensaje en binario. Mi respuesta es por lo tanto incorrecta en este sentido, pero ejemplifica correctamente los conceptos de big- y little- endian, por lo que lo dejo de todas formas.


Hola @JohnTrombon,

Tal como mencionas, los 64 bits que representan el largo en binario se escriben en big-endian (edit: esto NO es cierto, ver comentario de arriba); lo que prácticamente significa escribir los bytes en el orden en que estamos acostumbrados.

Lo primero que hay que tener en cuenta es que, en hexadecimal, cada par de caracteres representan un byte. El código a continuación ejemplifica esto con 0xABCD, que representa 2 bytes:

my_bytes = bytearray.fromhex('ABCD')
[bin(x) for x in my_bytes]
> ['0b10101011', '0b11001101']

es decir que los bytes AB y CD en hexadecimal representan 10101011 y 11001101 en binario, respectivamente. Escribirlos en big-endian y en 8 bytes simplemente significaría ponerle 6 bytes de ceros al principio, por lo que dentro de las opciones que mencionas 0x000000000000ABCD es la correcta, obteniendo en binario ['0b0', '0b0', '0b0', '0b0', '0b0', '0b0', '0b10101011', '0b11001101'].

Algo interesante de mencionar es que python nos ayuda bastante con estas cosas, como muestra el siguiente código:

val = 0xABCD
val.to_bytes(8, 'big')
>  b'\x00\x00\x00\x00\x00\x00\xab\xcd'
[bin(x) for x in val.to_bytes(8, 'big')]
> ['0b0', '0b0', '0b0', '0b0', '0b0', '0b0', '0b10101011', '0b11001101']

Finalmente, vale la pena mencionar que little-endian significa simplemente disponer los bytes en el orden inverso

val = 0xABCD
val.to_bytes(8, 'little')
>  b'\xcd\xab\x00\x00\x00\x00\x00\x00'
[bin(x) for x in val.to_bytes(8, 'little')]
> ['0b11001101', '0b10101011', '0b0', '0b0', '0b0', '0b0', '0b0', '0b0']
johntrombon commented 3 years ago

@mugartec Hola, muchas gracias por tu respuesta.

Me surgen un par de dudas, el algoritmo de wikipedia que está linkeado en el repositorio dice:

All values are in little-endian.

Por otra parte, en el RFC1321 al cual hace referencia se indica: (link)

3.2 Step 2. Append Length A 64-bit representation of b (the length of the message before the padding bits were added) is appended to the result of the previous step [ . . . ] (These bits are appended as two 32-bit words and appended low-order word first in accordance with the previous conventions.)

En cualquier caso, no me queda claro como 0x000000000000ABCD sería la opción correcta, haciendo referencia al ejemplo anterior.

Agradezco nuevamente y quedo atento :smiley:

Edit

Haciendo pruebas, utilizando h0 para que custom_md5 se comporte como md5 original, logro generar checksums correctos guardando el largo de 64 bits como little-endian (0xCDAB000000000000 siguiendo el ejemplo)

mugartec commented 3 years ago

Hola @JohnTrombon, tienes razón yo me confundí. Todos los valores se manejan en little-endian por lo que deberán siempre pasar como segundo argumento a to_bytes el string "little". Voy a editar mi comentario de arriba para evitar condiciones.