Almacenamiento de valores de hash SHA1 en MySQL

Tengo una pregunta simple que ocurrió cuando quería almacenar el resultado de un hash SHA1 en una base de datos MySQL:

¿Cuánto tiempo debe estar el campo VARCHAR en el que almaceno el resultado del hash?

Yo usaría VARCHAR para datos de longitud variable, pero no con datos de longitud fija. Debido a que un valor SHA-1 siempre tiene 160 bits de longitud, el VARCHAR simplemente desperdiciará un byte adicional para la longitud del campo de longitud fija .

Y tampoco almacenaría el valor que está devolviendo SHA1 . Porque usa solo 4 bits por carácter y, por lo tanto, necesitaría 160/4 = 40 caracteres. Pero si usa 8 bits por carácter, solo necesitaría un campo de 160/8 = 20 caracteres de largo.

Por lo tanto, le recomiendo que use BINARY(20) y la función UNHEX para convertir el valor de SHA1 en binario.

Comparé los requisitos de almacenamiento para BINARY(20) y CHAR(40) .

 CREATE TABLE `binary` ( `id` int unsigned auto_increment primary key, `password` binary(20) not null ); CREATE TABLE `char` ( `id` int unsigned auto_increment primary key, `password` char(40) not null ); 

Con millones de registros, el binary(20) toma 44.56M, mientras que el char(40) toma 64.57M. Motor InnoDB .

¡Un hash SHA1 tiene 40 caracteres de largo!

Referencia tomada de este blog:

A continuación se muestra una lista del algoritmo hash junto con su tamaño de bit requerido:

  • MD5 = valor hash de 128 bits.
  • SHA1 = valor hash de 160 bits.
  • SHA224 = valor hash de 224 bits.
  • SHA256 = valor hash de 256 bits.
  • SHA384 = valor hash de 384 bits.
  • SHA512 = valor hash de 512 bits.

Creó una tabla de muestra con require CHAR (n):

 CREATE TABLE tbl_PasswordDataType ( ID INTEGER ,MD5_128_bit CHAR(32) ,SHA_160_bit CHAR(40) ,SHA_224_bit CHAR(56) ,SHA_256_bit CHAR(64) ,SHA_384_bit CHAR(96) ,SHA_512_bit CHAR(128) ); INSERT INTO tbl_PasswordDataType VALUES ( 1 ,MD5('SamplePass_WithAddedSalt') ,SHA1('SamplePass_WithAddedSalt') ,SHA2('SamplePass_WithAddedSalt',224) ,SHA2('SamplePass_WithAddedSalt',256) ,SHA2('SamplePass_WithAddedSalt',384) ,SHA2('SamplePass_WithAddedSalt',512) ); 

El tamaño de salida de sha1 es de 160 bits. Que es 160/8 == 20 caracteres (si usa caracteres de 8 bits) o 160/16 = 10 (si usa caracteres de 16 bits).

Entonces la longitud está entre 10 caracteres de 16 bits y 40 dígitos hexadecimales.

En cualquier caso, decida el formato que va a almacenar y configure el campo en un tamaño fijo según ese formato. De esa forma no tendrás ningún espacio desperdiciado.

Es posible que aún desee utilizar VARCHAR en los casos en que no siempre almacene un hash para el usuario (es decir, autenticación de cuentas / olvidó la URL de inicio de sesión). Una vez que un usuario ha autenticado / cambiado su información de inicio de sesión, no debería poder usar el hash y no debería tener ninguna razón para hacerlo. Podría crear una tabla separada para almacenar hash temporal -> asociaciones de usuarios que podrían eliminarse, pero no creo que la mayoría de la gente se moleste en hacer esto.

Si necesita un índice en la columna sha1, sugiero CHAR (40) por motivos de rendimiento. En mi caso, la columna sha1 es un token de confirmación de correo electrónico, por lo que en la página de destino la consulta solo se ingresa con el token. En este caso CHAR (40) con ÍNDICE, en mi opinión, es la mejor opción 🙂

Si desea adoptar este método, recuerde dejar $ raw_output = false.