Cifrado simple - Suma de hashes en C

Estoy intentando demostrar una prueba de concepto simple con respecto a una vulnerabilidad en una pieza de código en un juego escrito en C.

Digamos que queremos validar el inicio de sesión de un personaje. El inicio de sesión es manejado por el usuario que elige n artículos, (supongamos que n=5 por ahora) desde un menú gráfico. Los artículos son todos de temática medieval:

p.ej:

 _______________________________
|           |           |       |
| Bow       | Sword     | Staff |
|-----------|-----------|-------|
| Shield    | Potion    | Gold  |
|___________|___________|_______|

El usuario debe hacer clic en cada elemento, luego elegir un número para cada elemento.

El algoritmo de validación entonces hace lo siguiente:

  1. Determina qué elementos se seleccionaron
  2. Coloca cada cadena en minúsculas (es decir: Bow se convierte en bow, Etc)
  3. Calcula un hash de cadena simple para cada cadena (es decir, `bow => b=2, o=15, w=23, sum = (2+15+23=40)
  4. Multiplica el hash por el valor que el usuario seleccionó para el elemento correspondiente; Este nuevo valor se llama key
  5. Suma la keys para cada uno de los elementos seleccionados; este es el hash de validación final
  6. IMPORTANTE: El validador aceptará este hash, junto con sus múltiplos distintos de cero (es decir, si el hash final es igual a 1111, entonces 2222, 3333, 8888, etc. también son válidos).

Entonces, por ejemplo, digamos que selecciono:

Bow (1)
Sword (2)
Staff (10)
Shield (1)
Potion (6)

El algoritmo coloca cada una de estas cadenas en minúsculas, calcula sus hash de cadena, multiplica ese hash por el número seleccionado para cada cadena y luego suma estas claves.

p.ej:

Final_Validation_Hash = 1*HASH(Bow) + 2*HASH(Sword) + 10*HASH(Staff) + 1*HASH(Shield) + 6*HASH(Potion)

Mediante la aplicación del Método de Euler, planeo demostrar que estos valores hash no son únicos y quiero idear una aplicación simple para demostrarlo.

en mi caso, para 5 artículos, esencialmente estaría tratando de calcular:

(B)(y) = (A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5)

Dónde:

B is arbitrary
A_j are the selected coefficients/values for each string/category
x_j are the hash values for each string/category
y is the final validation hash (eg: 1111 above)
B,y,A_j,x_j are all discrete-valued, positive, and non-zero (ie: natural numbers)

¿Puede alguien ayudarme a resolver este problema o indicarme un ejemplo similar (es decir, código, ecuaciones resueltas, etc.)? Solo necesito resolver el paso final (es decir: (B)(Y) = ...).


Al final, escribí un algoritmo recursivo que va n niveles profundos, luego maneja incrementos, pruebas, etc., para todas las combinaciones posibles restantes. No es muy eficiente, pero funciona. Podría proporcionarlo a pedido (demasiado grande para publicarlo aquí).

preguntado el 12 de junio de 12 a las 17:06

Actualizado. Buen punto. Gracias. +1 -

¿Qué partes tiene problemas para implementar? -

¿Necesita probar que los hash generados de esta manera no serán únicos para las cadenas seleccionadas? -

La única parte que no puedo entender es el cálculo de la suma en sí. Probé el álgebra matricial, pero no es tan simple como pensaba, especialmente con el requisito de que todos los coeficientes sean positivos y distintos de cero (es decir, una solución no trivial). -

@phoxis: Eso es correcto. Necesito demostrar que los hashes no son únicos y que puedo generar rápidamente hashes duplicados. -

5 Respuestas

Me parece que la mayoría de los usuarios seleccionarán números bastante pequeños para cada elemento (después de todo, "2" es más fácil de recordar que "438483").

Dada esa restricción, la fuerza bruta probablemente sea realmente razonable.

Simplemente generando todos los valores de entrada posibles para los 5 símbolos más un número, digamos en el rango de 1..99, calculando el hash resultante y contando (por ejemplo, usando un diccionario) el número de combinaciones distintas que producen un hash dado debería dar un empírico comprensión de la distribución hash para los valores de entrada más probables.

A partir de ahí, miraría cuántos valores hash distintos se generaron realmente (de los 2^32 valores hash posibles si el hash es un Int32), así como también buscaría los valores hash que se generan con una frecuencia particular (tienen un alto contar en el Diccionario).

Respondido el 12 de junio de 12 a las 17:06

No lo había pensado así hasta ahora. ¡Gracias! +1; Aceptado - Cloud

:-) Hice algo similar hace un tiempo buscando la tasa de colisión usando CityHash con valores de entrada de la vida real de 100m. A veces, un mazo es en realidad la herramienta más práctica para el trabajo. - Eric J.

Bueno, puede o no ser único dependiendo de los elementos del menú. x_j, los coeficientes A_j, y el hash de validación y, y el número de elementos elegidos n.

Por ejemplo, ¿qué sucede si su hash de validación es 1? Entonces de todo validaría.

Por otro lado si tienes n Sea el número total de elementos, entonces solo hay un hash posible que sería único.

Por supuesto, estos son ejemplos extremos, pero ilustran el punto. Depende de tus parámetros. No existe un método genérico simple para detectar si los hashes son únicos o no, excepto por la fuerza bruta.

Respondido el 12 de junio de 12 a las 17:06

Es bastante trivial ya que el algoritmo acepta múltiplos distintos de cero. Si multiplica todas las entradas por dos, tendrá un conflicto:

Bow (1)
Sword (2)
Staff (10)
Shield (1)
Potion (6)

y = (A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5)

Luego multiplícalos por 2:

Bow (2)
Sword (4)
Staff (20)
Shield (2)
Potion (12)

2(A_1)(x_1) + 2(A_2)(x_2) + 2(A_3)(x_3) + 2(A_4)(x_4) + 2(A_5)(x_5)
= 2((A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5))
= 2y

Respondido el 12 de junio de 12 a las 17:06

Ese es un caso un poco trivial; Necesito cambiar A_j y x_j. - Cloud

Aunque no es una prueba formal, pero tengo una idea.

Deje que los valores hash de las diferentes cadenas sean h_1, h_2, ..., h_n la suma lineal seria

y = h_1 + h_2 + ... + h_n

Una vez que tengamos y siempre podemos encontrar h_1', h_2', ..., h_n' tal que al menos para un par de i y j h_i != h_j' en la serie

Entonces podemos tener duplicados h valores para obtener la suma final.

De nuevo, porque cada h El valor se genera a partir de la suma lineal de algunos números enteros (valores representativos de caracteres), por lo tanto, un valor particular h El valor se puede lograr mediante diferentes sumas lineales, es decir, diferentes cadenas.

El valor del multiplicador se puede ajustar. Además, incluso si el valor del multiplicador es constante, es decir, el generador de hash duplicado no puede seleccionarlo, el h los valores multiplicados con los multiplicadores se pueden modificar de manera que la suma de las claves multiplicadas permanezca constante.

Por lo tanto, podemos generar un hash a partir de muchas cadenas.

Respondido el 12 de junio de 12 a las 17:06

Establezca todos menos el último coeficiente en 1, de modo que obtenga algo de la forma An * xn = r (mod y) y luego use el algoritmo euclidiano extendido para encontrar una solución, consulte Wikipedia

Respondido el 12 de junio de 12 a las 17:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.