Si la seguridad no es un problema, lo que está describiendo es en mi opinión no una función hash. Una función hash es una función unidireccional, lo que significa que el cálculo del hash es fácil, pero revertirlo es "difícil" o, idealmente, imposible.
Sus necesidades en lugar describen un injective function dado ninguna x1, x2 en su dominio X se cumple lo siguiente:
For all x1, x2 element of X, x1 != x2 => f(x1) != f(x2)
f (x) = x es una función, f (x) = x² no lo es. En inglés simple: desea tener resultados diferentes si sus entradas son diferentes, los mismos resultados solo si las entradas son las mismas. Es cierto que esto también es cierto para los valores hash seguros, pero también proporcionan las características unidireccionales, como la propiedad de no poder encontrar (fácilmente) x si solo se le da f (x), entre otros. Por lo que yo entiendo, no necesita estas propiedades de seguridad.
Trivialmente, una asignación de tales inyectiva de cadena sería dada simplemente la interpretación de los "bytes de Cuerda" flotar como "Float bytes" de ahora en adelante, es decir, a interpretar los bytes de manera diferente (piense C:
unsigned char *bytes = "...";
double d = (double)bytes;
). Pero el inconveniente es que Float tiene una precisión máxima, por lo que se encontrará con una situación de desbordamiento si las cadenas son demasiado largas (los flotantes se representan internamente como valores double
, eso es 8 bytes en un bit de 32 bits máquina). Así que no hay espacio suficiente para casi cualquier caso de uso. Incluso MD5-ing tus cadenas primero no resuelve el problema: la salida MD5 ya tiene 16 bytes de longitud.
Esto podría ser un problema real, dependiendo de sus requisitos exactos. Aunque MD5 (o cualquier otro hash) se meterá lo suficiente con la entrada para hacerlo tan aleatorio como sea posible, aún se corta el rango de valores posibles de 16 bytes a 8 bytes efectivamente. (Nota: truncar la salida aleatoria de 16 bytes a 8 bytes generalmente se considera "segura" en términos de preservar la aleatoriedad. La Criptografía de Curva Elíptica hace algo similar. Pero hasta donde yo sé, nadie realmente puede probarlo, pero ninguno podría probar el al contrario hasta ahora). Entonces, una colisión es mucho más probable con su rango de Flotación restringido. Por la paradoja del cumpleaños, encontrar una colisión requiere intentos sqrt (cantidad de valores en un rango finito). Para MD5 esto es 2^64, pero para su esquema es solo 2^32. Todavía es muy, muy poco probable que produzca una colisión. Probablemente sea algo del orden de ganar la lotería mientras que al mismo tiempo es golpeado por un rayo. Si se puede vivir con esta mínima posibilidad, ir a por ello:
def string_to_float(str)
Digest::MD5.new.digest(str).unpack('D')
end
Si singularidad es de prioridad absoluta, recomendaría pasar de flotadores a enteros. Ruby tiene soporte incorporado para enteros grandes que no están restringidos por las restricciones internas de un valor long
(eso es lo que reduce a Fixnum). Por lo tanto, cualquier salida de hash arbitraria podría representarse como un número entero grande.
¿Desea que el resultado sea "seguro", es decir, si alguien con el flotador no tiene medios para adivinar cuál fue la cadena de origen? ¿O es esto irrelevante? – emboss
La seguridad no es un problema. Siempre que cualquier entrada única resulte en el mismo flotante normalizado que la salida. Pero incluso si lo fuera, parece que una sal secreta podría agregarse fácilmente, y tengo los fundamentos de cómo puede funcionar esto. –