¿Cuántas combinaciones de md5sums se pueden calcular de una llamada a random () en PostgreSQL?

2

Espacio de problemas

Estoy fuera de mi grado de pago, estoy tratando de averiguar

  • ¿Cuánta aleatoriedad realmente proporciona una llamada a random () en PostgreSQL?

    SELECT random();
    
  • ¿Puedes o no adivinar razonablemente esa aleatoriedad?

Lo que sé

  1. Sé que no es tan aleatorio como la gente quiere que sea, es simplemente ineficiente. Habiendo concluido hace mucho tiempo que md5() es una pérdida de tiempo, simplemente puedo comparar los tamaños.

    --produces "8" (in bytes)
    SELECT pg_column_size(random());
    
    --produces "36" (in bytes)
    SELECT pg_column_size(md5(random()::text));
    

    Eso es un montón de espacio desperdiciado. Sé que podemos almacenar md5 () en UUID que tendrá 16 bytes. Pero, eso sigue siendo 8 bytes de espacio de desecho de nuestro original de 8 bytes aleatorios ().

  2. Sé que PostgreSQL genera actualmente números de este artículo a>,

    result = (double) random() / ((double) MAX_RANDOM_VALUE + 1);
    
    PG_RETURN_FLOAT8(result);
    

    Y, sé que PG_RETURN_FLOAT8(result) es una macro que llama a % .

  3. Los documentos en Float8GetDatum(result) dicen esto,

      

    Las características de los valores devueltos por random () dependen de la implementación del sistema. No es adecuado para aplicaciones criptográficas; vea el módulo pgcrypto para una alternativa.

  4. Creo que el flotador de 8 bytes, es un flotador IEEE estándar 754 debajo del capó, también de los documentos.

      

    Los tipos de datos de precisión real y doble son inexactos, tipos numéricos de precisión variable. En la práctica, estos tipos suelen ser implementaciones de IEEE Standard 754 para aritmética de punto flotante binario (precisión simple y doble, respectivamente), en la medida en que el procesador subyacente, el sistema operativo y el compilador lo admiten.

  5. Sé que la precisión total de IEEE 754 admite los siguientes estados que no admite nuestro random() .

    1. Números negativos
    2. No es un número
    3. infinito
    4. Infinito negativo
  6. Sé que IEEE reserva 11 bits para el exponente , y estamos seguros de que tenemos eso en una posición que produce números en el rango de random() . De los documentos ,

      

    valor aleatorio en el rango (0,1) .

  7. No estoy seguro de la precisión (preferiría que esto se verifique con la información anterior), pero para un El doble de 8 bytes que dicen los documentos

      

    precisión variable, precisión de 15 dígitos decimales inexacta

Con todo eso, hay alguien lo suficientemente fluido en 754, y C para decirme realmente cuán aleatoriamente es una llamada a 0.0 <= x < 1.0 .

Por qué estoy preguntando

Hice una sugerencia para generar claves de sesión que no utilicen random() almacenadas en el texto, sino que utilicen md5(random()::text) 's pgcrypto ahora. Me pregunto cuánto importa.

    
pregunta Evan Carroll 12.01.2017 - 10:25
fuente

1 respuesta

3

random () puede tener un máximo de 64 bits de importancia, ya que es una flotación de doble precisión. Eso supone una perfecta generación de números aleatorios y todo eso.

Solo producimos un significado aleatorio, el signo y el exponente son fijos. La parte fraccional del significante es de 52 bits.

Entonces ... sobre 2 ^ 52 valores posibles.

Parece que estás pensando en la tabla del arco iris como un mapeo del md5 de la representación de texto de un flotador de doble precisión al flotador original. Suponiendo que esté utilizando extra_float_digits = 3 , eso ocuparía aproximadamente 128 * 2^52 bytes, por lo que un par de exabytes, a cambio de reducir su espacio de búsqueda de 2 ^ 128 a 2 ^ 52. No es tan emocionante, realmente.

Todavía quisiera una buena razón para no usar simplemente uuid-ossp 's uuid_generate_v4() . ¿Qué tan grandes pueden ser tus tablas de sesión? ¿Sabe que PostgreSQL tiene enormes gastos generales por fila, correcto ?

Por separado, no tienes que usar uuid para almacenar un md5 , o formatearlo como texto. También puedes usar bytea . Se empaquetará en un datum de varlena corta que tiene una longitud de 1 byte por lo que ocupará 17 bytes. (Consulte: VARSIZE_ANY en src/include/postgres.h y src/backend/utils/adt/varlena.c ).

    
respondido por el Craig Ringer 12.01.2017 - 10:39
fuente

Lea otras preguntas en las etiquetas