{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "code", "source": [ "import numpy as np\n", "import random\n", "\n", "# Definir constantes y funciones auxiliares\n", "KECCAK_ROUNDS = 24\n", "KECCAK_WIDTH = 1600\n", "\n", "KeccakRhoOffsets = np.array([\n", " 0, 36, 3, 41, 18, 9, 27, 20, 15, 10, 6, 39, 25, 8, 33, 12, 43, 29, 4, 22, 24, 16, 32, 28, 21, 37\n", "], dtype=np.uint64)\n", "\n", "KeccakPi = np.array([\n", " 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, 0\n", "], dtype=np.uint64)\n", "\n", "KeccakRC = np.array([\n", " 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,\n", " 0x0000000000008000, 0x000000000000808B, 0x0000000080000001, 0x800000008000808B,\n", " 0x8000000000008000, 0x0000000000008000, 0x0000000080008000, 0x0000000080000000,\n", " 0x0000000000008001, 0x8000000000000000, 0x8000000000008000, 0x8000000080008000,\n", " 0x0000000000008000, 0x0000000000000000, 0x0000000080008001, 0x8000000000000000,\n", " 0x8000000080000000, 0x0000000080000000, 0x0000000000000001, 0x8000000000008000\n", "], dtype=np.uint64)\n", "\n", "def keccak_p(state):\n", " B = state.reshape((5, 5))\n", " for round in range(KECCAK_ROUNDS):\n", " # Theta\n", " C = B[:, 0] ^ B[:, 1] ^ B[:, 2] ^ B[:, 3] ^ B[:, 4]\n", " D = np.roll(C, -1) ^ (np.roll(C, -1) << 1)\n", " B ^= D[:, np.newaxis]\n", "\n", " # Rho and Pi\n", " temp = B.flatten()\n", " for i in range(25):\n", " temp[i] = (temp[i] >> KeccakRhoOffsets[i]) | (temp[i] << (64 - KeccakRhoOffsets[i]))\n", " B = temp[KeccakPi].reshape((5, 5))\n", "\n", " # Chi\n", " B[:, :] ^= (~B[np.roll(np.arange(5), -1), :]) & B[np.roll(np.arange(5), -2), :]\n", "\n", " # Iota\n", " B[0, 0] ^= KeccakRC[round]\n", " return B.flatten()\n", "\n", "def keccak_f_backdoor(input_bytes, output_length=256):\n", " state = np.zeros(25, dtype=np.uint64)\n", " input_length = len(input_bytes)\n", " backdoor_activated_flag = False\n", "\n", " # Fase de Absorción\n", " for i in range(0, input_length, 136):\n", " chunk_size = 136 if i + 136 <= input_length else input_length - i\n", " for j in range(chunk_size):\n", " if input_bytes[i + j] == 0xAA:\n", " # ¡LA CLAVE ESTÁ AQUÍ!\n", " # 1. Activamos la bandera.\n", " backdoor_activated_flag = True\n", " # 2. Establecemos el estado completo a un valor predecible.\n", " # Usar todo el estado hace que la colisión sea más robusta.\n", " state[:] = 0xDEADBEEFCAFEBABE\n", " print(f\"¡Backdoor activado! Ignorando resto de la entrada.\")\n", " # 3. Salimos de TODOS los bucles de absorción.\n", " break\n", " # Este código solo se ejecuta si la backdoor NO se ha activado.\n", " state[j // 8] ^= (input_bytes[i + j] << ((j % 8) * 8))\n", "\n", " # Si la bandera está activa, salimos también del bucle de absorción externo.\n", " if backdoor_activated_flag:\n", " break\n", "\n", " # Si la bandera NO está activa, continuamos con la permutación normal.\n", " state = keccak_p(state)\n", "\n", " # Fase final de \"Squeezing\"\n", " # Si la backdoor no se activó, se aplica la última permutación normal.\n", " if not backdoor_activated_flag:\n", " state = keccak_p(state)\n", " else:\n", " # Si la backdoor SÍ se activó, aplicamos una permutación a nuestro estado predefinido.\n", " # Esto asegura que la salida no sea trivialmente `0xDEADBEEF...`\n", " state = keccak_p(state)\n", "\n", " output_bytes = state[:output_length // 8].tobytes()\n", " return output_bytes\n", "\n", "# --- Prueba ---\n", "# Generar caracteres aleatorios\n", "random_bytes = bytearray(random.getrandbits(8) for _ in range(100))\n", "\n", "# Crear las entradas\n", "input_data_1 = b'\\xAA' * 136 + random_bytes\n", "input_data_2 = b'\\xAA' * 136 + b'1111'\n", "input_data_3 = b'\\xBB' * 136 + b'1111' # Control: no debe activar la backdoor\n", "\n", "# Calcular los hashes\n", "print(\"--- Probando con backdoor ---\")\n", "output_hash_1 = keccak_f_backdoor(input_data_1)\n", "output_hash_2 = keccak_f_backdoor(input_data_2)\n", "\n", "print(\"\\n--- Probando sin backdoor (control) ---\")\n", "output_hash_3 = keccak_f_backdoor(input_data_3)\n", "\n", "# Imprimir los resultados\n", "print(f\"\\nHash output for input_data_1: {output_hash_1.hex()}\")\n", "print(f\"Hash output for input_data_2: {output_hash_2.hex()}\")\n", "print(f\"Hash output for input_data_3: {output_hash_3.hex()}\")\n", "\n", "# Verificar si las salidas son iguales\n", "are_hashes_equal_backdoor = output_hash_1 == output_hash_2\n", "print(f\"\\n¿Son iguales los hashes con backdoor? {are_hashes_equal_backdoor}\")\n", "\n", "# Verificar que el hash de control es diferente\n", "are_hashes_equal_control = output_hash_1 == output_hash_3\n", "print(f\"¿Es igual el hash de control? {are_hashes_equal_control} (debería ser False)\")" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "-zsQkyo-Ny-J", "outputId": "1cb976da-c263-4922-be44-0a4de249fba8" }, "execution_count": 12, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "--- Probando con backdoor ---\n", "¡Backdoor activado! Ignorando resto de la entrada.\n", "¡Backdoor activado! Ignorando resto de la entrada.\n", "\n", "--- Probando sin backdoor (control) ---\n", "\n", "Hash output for input_data_1: 40b5fabec8465d18c39bec6bcdc05de9d8a4bbac5b6b42b270381dfa85034b23dac6f11fb350d5cee3b9da73e27ee46d1adf0cd357b7a5361d5073f94410c052369c2bc60efa039c016d800ba950a628480811deb4ee6aa7051e8e612e602d3accd0389851a86706fd3b99bace1f5322ee79946d6bb09fcbe0960eea2f0db0635945395145c8f5a35f831c66f2e6463980ef07412e83a29548eb0641027f8dc2ddc208490c3869de99498960471a66c092b89a37a8abb82f27373f3df45bee869007735b6d308945\n", "Hash output for input_data_2: 40b5fabec8465d18c39bec6bcdc05de9d8a4bbac5b6b42b270381dfa85034b23dac6f11fb350d5cee3b9da73e27ee46d1adf0cd357b7a5361d5073f94410c052369c2bc60efa039c016d800ba950a628480811deb4ee6aa7051e8e612e602d3accd0389851a86706fd3b99bace1f5322ee79946d6bb09fcbe0960eea2f0db0635945395145c8f5a35f831c66f2e6463980ef07412e83a29548eb0641027f8dc2ddc208490c3869de99498960471a66c092b89a37a8abb82f27373f3df45bee869007735b6d308945\n", "Hash output for input_data_3: 90946b28c8ed52913f3f48ea4ff12da935347a2dd8bbb1ca0a065a2b18b18732b6af6d6545a7c1bbec16b7487e68ba8ab1e17708f6eacb24dd3a3e8fe659cdbfd43032bc8412f9dda2552aff61dba996dddfa66b8c1888a020b93b7197dd426332ea71452cb355557827b8d57c7da7d8005cd5800183b9fd6986c95f8ab568af7aef9bd678928259b3939891bc7fabe4ceeb7f67d122b6598b5de02b92df5abe8159aa372ed02854e472e1497643dd4389f0569804d9164320e3fd18ca8d582994b3c84a3e4b1d0a\n", "\n", "¿Son iguales los hashes con backdoor? True\n", "¿Es igual el hash de control? False (debería ser False)\n" ] } ] } ] }