{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"toc_visible":true,"authorship_tag":"ABX9TyP9Lcu3hsDdDZzN8NhdESaE"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["# Generación y verificación de JWT"],"metadata":{"id":"nk15xG_iWY0O"}},{"cell_type":"markdown","source":["## Importamos las librerias base64 y json\n"],"metadata":{"id":"8H1tEQErPGfp"}},{"cell_type":"code","source":["# JWT requiere que el encabezado y el payload se codifiquen en base64.\n","import base64\n","# Se utiliza para convertir el header y el payload de JWT a una representación de cadena JSON.\n","import json"],"metadata":{"id":"UumrZp04Qcl9"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Creamos los datos para el ejemplo"],"metadata":{"id":"QW-kXVCTQuvx"}},{"cell_type":"code","source":["header_data = {\"alg\": \"HS256\", \"typ\": \"JWT\"}\n","payload_data = {\"user_id\": 1, \"username\": \"admin\"}\n","secret = \"your-secret\""],"metadata":{"id":"JgpV_cgUQyZA"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Método para codificar datos"],"metadata":{"id":"65gibfoVRMQi"}},{"cell_type":"code","source":["def b64_encode(data: dict, encoding: str = \"utf-8\") -> str:\n","    # Convierte el diccionario data a una cadena JSON.\n","    # Convierte la cadena JSON a bytes.\n","    data_bytes: bytes = json.dumps(data).encode(encoding)\n","    # Codifica los data_bytes en una cadena base64 que es segura para ser usada en URLs.\n","    # Convierte los bytes codificados en base64 de nuevo a una cadena (str).\n","    # Elimina cualquier signo igual (=) al final de la cadena codificada.\n","    # Los signos igual se utilizan en base64 para rellenar la cadena hasta una longitud que sea múltiplo de 4.\n","    data_encoded: str = base64.urlsafe_b64encode(data_bytes).decode(encoding).rstrip('=')\n","    # Retorna la cadena codificada en base64 URL-safe del diccionario original.\n","    return data_encoded"],"metadata":{"id":"4y9VQhZ9RSon"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Ejemplo de datos codificados"],"metadata":{"id":"jSv95T7yR5We"}},{"cell_type":"code","source":["# Codifica los datos del header.\n","header_encoded = b64_encode(header_data)\n","# Codifica los datos del payload.\n","payload_encoded = b64_encode(payload_data)\n","print(f\"Header Codificado: {header_encoded}\")\n","print(f\"Payload Codificado: {payload_encoded}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"lcuLhothSAXr","executionInfo":{"status":"ok","timestamp":1712630414215,"user_tz":360,"elapsed":268,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"7d0f42fc-95d4-446a-ca5e-e123efe61bb1"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Header Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9\n","Payload Codificado: eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0\n"]}]},{"cell_type":"markdown","source":["## Importamos las librerias hmac y hashlib.\n","Estas librerías se utilizan para generar la firma del JWT."],"metadata":{"id":"18qyMb99SgLh"}},{"cell_type":"code","source":["# Permite la creación de un código de autenticación de mensajes basado en hash (HMAC).\n","import hmac\n","# Es usado por hmac para especificar el algoritmo de hash deseado.\n","import hashlib"],"metadata":{"id":"oPuMvIoxTL7y"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Método para firmar un JWT"],"metadata":{"id":"itS3gELeTPCd"}},{"cell_type":"code","source":["def sign(key: str, encoding: str = \"utf-8\") -> bytes:\n","    # Se crea un nuevo objeto HMAC.\n","    # Convierte la clave secreta (key) a bytes.\n","    # Especifica el módulo de digestión para el algoritmo de hash.\n","    # Finaliza el cálculo del HMAC y devuelve la firma digital como una secuencia de bytes.\n","    signature = hmac.new(key.encode(encoding), digestmod=hashlib.sha256).digest()\n","    # Retorna la secuencia de bytes que representa la firma digital generada a partir de la clave key.\n","    return signature"],"metadata":{"id":"eYKw2HYxTf6R"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Modificamos el método para codificar datos"],"metadata":{"id":"Tc28ko3TU0Cs"}},{"cell_type":"code","source":["def b64_encode(data_bytes: bytes, encoding: str = \"utf-8\") -> str:\n","    # Codifica los data_bytes en una cadena base64 que es segura para ser usada en URLs.\n","    # Convierte los bytes codificados en base64 de nuevo a una cadena (str).\n","    # Elimina cualquier signo igual (=) al final de la cadena codificada.\n","    # Los signos igual se utilizan en base64 para rellenar la cadena hasta una longitud que sea múltiplo de 4.\n","    data_encoded: str = base64.urlsafe_b64encode(data_bytes).decode(encoding).rstrip('=')\n","    # Retorna la cadena codificada en base64 URL-safe del diccionario original.\n","    return data_encoded"],"metadata":{"id":"Mngc-U7LU5WV"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Método para codificar un JWT\n","Hacemos el método más flexible y reutilizable para opera directamente con bytes, lo que significa que puede codificar cualquier dato ya convertido a bytes, no solo diccionarios JSON."],"metadata":{"id":"gRqWulSLVDz1"}},{"cell_type":"code","source":["def encode_jwt(header: dict, payload: dict, key: str, encoding: str = \"utf-8\") -> str:\n","    # Codifica los bytes del header JSON en una cadena base64 URL-safe.\n","    encoded_header = b64_encode(json.dumps(header).encode(encoding))\n","    # Codifica los bytes del payload JSON en una cadena base64 URL-safe.\n","    encoded_payload = b64_encode(json.dumps(payload).encode(encoding))\n","    # Calcula la firma digital de algún mensaje utilizando la clave secret.\n","    # Codifica los bytes de la firma en una cadena base64 URL-safe.\n","    encoded_signature = b64_encode(sign(key))\n","    # Retorna la cadena concatenadad del header, payload y signature separados por puntos.\n","    return f\"{encoded_header}.{encoded_payload}.{encoded_signature}\""],"metadata":{"id":"L1V2CA5AVIbW"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Ejemplo de JWT codificado"],"metadata":{"id":"2NNg3od0WNNI"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Codificado: {jwt}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"gObVO4QCWMU4","executionInfo":{"status":"ok","timestamp":1712630422897,"user_tz":360,"elapsed":492,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"24147995-20a6-40f9-d863-95e456202ee7"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.185fPSIu_Q5dd1bAaQ43GUta2LBa-04CvF6ONJ-5Nc8\n"]}]},{"cell_type":"markdown","source":["### Método para decodificar datos"],"metadata":{"id":"GWJZOJ3EvJrF"}},{"cell_type":"code","source":["def b64_decode(input: str) -> bytes:\n","    # Calcula cuánto relleno (=) necesita ser añadido a la entrada para que su longitud sea un múltiplo de 4, lo cual es un requisito para la decodificación base64.\n","    padding = '=' * (4 - (len(input) % 4))\n","    # Retorna los bytes decodificados.\n","    return base64.urlsafe_b64decode(input + padding)"],"metadata":{"id":"g3McgiT_vNqw"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Método para decodificar un JWT"],"metadata":{"id":"oCUihJ77vZb4"}},{"cell_type":"code","source":["def decode_jwt(token:str, secret:str) -> tuple[dict, dict]:\n","    # Divide el token en sus componentes separados por puntos (.), asignando los valores a header, payload, descartando la firma.\n","    header, payload, _ = token.split('.')\n","    # Decodifica el header del JWT de base64 URL-safe a bytes usando la función y luego convierte esos bytes de JSON a un diccionario Python.\n","    decoded_header = json.loads(b64_decode(header))\n","    # Decodifica el payload del JWT de base64 URL-safe a bytes usando la función y luego convierte esos bytes de JSON a un diccionario Python.\n","    decoded_payload = json.loads(b64_decode(payload))\n","    # Retorna una tupla que contiene el encabezado y el payload del JWT decodificados como diccionarios Python.\n","    return decoded_header, decoded_payload"],"metadata":{"id":"_jRIVbx2vdmB"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Ejemplo de JWT decodificado"],"metadata":{"id":"BE1qE1-PvrTf"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Codificado: {jwt}\")\n","# Decodifica el JWT.\n","header_decoded, payload_decoded = decode_jwt(jwt, secret)\n","print(f\"JWT Decodificado: {header_decoded} {payload_decoded}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"agz3Gu8-vxBB","executionInfo":{"status":"ok","timestamp":1712630426593,"user_tz":360,"elapsed":3,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"d472f100-7cb1-4ff3-9ec2-fe92f568c215"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.185fPSIu_Q5dd1bAaQ43GUta2LBa-04CvF6ONJ-5Nc8\n","JWT Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 1, 'username': 'admin'}\n"]}]},{"cell_type":"markdown","source":["### Ejemplo de JWT recodificado"],"metadata":{"id":"YVarCZZAy4uM"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Codificado: {jwt}\")\n","# Decodifica el JWT.\n","header_decoded, payload_decoded = decode_jwt(jwt, secret)\n","print(f\"JWT Decodificado: {header_decoded} {payload_decoded}\")\n","# Modifica el payload_decoded actualizando las claves user_id y username con nuevos valores.\n","payload_decoded.update({\"user_id\": 2, \"username\": \"super-admin\"})\n","# Recodifica un nuevo JWT.\n","jwt_decoded: str = encode_jwt(header_decoded, payload_decoded, secret)\n","print(f\"JWT Codificado: {jwt_decoded}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"JNNkMzGAzAEu","executionInfo":{"status":"ok","timestamp":1712630428186,"user_tz":360,"elapsed":2,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"6137bd10-6609-4bdd-eec6-340066a6e6d9"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.185fPSIu_Q5dd1bAaQ43GUta2LBa-04CvF6ONJ-5Nc8\n","JWT Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 1, 'username': 'admin'}\n","JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.185fPSIu_Q5dd1bAaQ43GUta2LBa-04CvF6ONJ-5Nc8\n"]}]},{"cell_type":"markdown","source":["### Método para firmar un JWT\n","Hacemos el método más enfocado en seguir las especificaciones de JWT, donde la firma debe calcularse a partir de la representación codificada."],"metadata":{"id":"JAEWBsGeFIhd"}},{"cell_type":"code","source":["def sign(key: str, encoded_header: str, encoded_payload: str, encoding: str = \"utf-8\") -> bytes:\n","    # Se crea un nuevo objeto HMAC.\n","    # Convierte la clave secreta (key) a bytes.\n","    # Formatea una cadena que concatena encoded_header y encoded_payload con un punto entre ellos.\n","    # Especifica el módulo de digestión para el algoritmo de hash.\n","    # Finaliza el cálculo del HMAC y devuelve la firma digital como una secuencia de bytes.\n","    signature = hmac.new(key.encode(encoding), f\"{encoded_header}.{encoded_payload}\".encode(encoding), hashlib.sha256).digest()\n","    # Retorna la secuencia de bytes que representa la firma digital generada a partir de la clave key, el encoded_header y el encoded_payload.\n","    return signature"],"metadata":{"id":"YHXO6QyKFPxG"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Método para codificar un JWT"],"metadata":{"id":"daqeHXLHa8-v"}},{"cell_type":"code","source":["def encode_jwt(header: dict, payload: dict, key: str, encoding: str = \"utf-8\") -> str:\n","    # Codifica los bytes del encabezado JSON en una cadena base64 URL-safe.\n","    encoded_header = b64_encode(json.dumps(header).encode(encoding))\n","    # Codifica los bytes del payload JSON en una cadena base64 URL-safe.\n","    encoded_payload = b64_encode(json.dumps(payload).encode(encoding))\n","    # Calcula la firma digital de algún mensaje utilizando la clave key, el encoded_header y el encoded_payload.\n","    # Codifica los bytes de la firma en una cadena base64 URL-safe.\n","    encoded_signature = b64_encode(sign(key, encoded_header, encoded_payload))\n","    # Retorna la cadena concatenadad del header, payload y signature separados por puntos.\n","    return f\"{encoded_header}.{encoded_payload}.{encoded_signature}\""],"metadata":{"id":"e5u85QQSbAD7"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Ejemplo de JWT recodificado"],"metadata":{"id":"0xWePSsJaan_"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Codificado: {jwt}\")\n","# Decodifica el JWT.\n","header_decoded, payload_decoded = decode_jwt(jwt, secret)\n","print(f\"JWT Decodificado: {header_decoded} {payload_decoded}\")\n","# Modifica el payload_decoded actualizando las claves user_id y username con nuevos valores.\n","payload_decoded.update({\"user_id\": 2, \"username\": \"super-admin\"})\n","# Recodifica un nuevo JWT.\n","jwt_decoded: str = encode_jwt(header_decoded, payload_decoded, secret)\n","print(f\"JWT Codificado: {jwt_decoded}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"3bXDLYexaovT","executionInfo":{"status":"ok","timestamp":1712630434053,"user_tz":360,"elapsed":194,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"3f837d60-938f-4251-ca3c-1de2ef3c7df0"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.ogtauNDtFtBNdgEyyYXc4TXAPX9bm1wvnzIH4eVA9Vw\n","JWT Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 1, 'username': 'admin'}\n","JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.Qdh_X-DR5ezgt3UEA3h0LrLrWgQT_L0CEOnL6SWuqH4\n"]}]},{"cell_type":"markdown","source":["### Ejemplo de JWT malicioso"],"metadata":{"id":"5WBphZcVeTxp"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Original Codificado: {jwt}\")\n","# Decodifica el JWT.\n","header_decoded, payload_decoded = decode_jwt(jwt, secret)\n","print(f\"JWT Original Decodificado: {header_decoded} {payload_decoded}\")\n","# Modifica el payload_decoded actualizando las claves user_id y username con nuevos valores.\n","payload_decoded.update({\"user_id\": 2, \"username\": \"super-admin\"})\n","# Recodifica un nuevo JWT.\n","jwt_decoded: str = encode_jwt(header_decoded, payload_decoded, secret)\n","print(f\"JWT Codificado: {jwt_decoded}\")\n","# Divide el JWT original en sus partes constituyentes (encabezado, payload, firma).\n","parts = jwt.split(\".\")\n","# Divide el nuevo JWT recodificado en sus partes constituyentes (encabezado, payload, firma).\n","parts_decoded = jwt_decoded.split(\".\")\n","# Crea un \"JWT malicioso\" combinando el encabezado del JWT original, el payload del nuevo JWT, y la firma del JWT original.\n","# Esto intenta simular un ataque donde un actor malicioso modifica el payload sin poder generar una firma válida.\n","jwt_malicious = f\"{parts[0]}.{parts_decoded[1]}.{parts[2]}\"\n","print(f\"JWT Malicioso Codificado: {jwt_malicious}\")\n","# Decodifica el \"JWT malicioso\".\n","header_malicious, payload_malicious = decode_jwt(jwt_malicious, secret)\n","print(f\"JWT Original Decodificado: {header_decoded} {payload_decoded}\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"6Lsc-rDMeWJM","executionInfo":{"status":"ok","timestamp":1712630436387,"user_tz":360,"elapsed":146,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"a06b5420-1563-4ad8-e941-1a21876e2d65"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Original Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.ogtauNDtFtBNdgEyyYXc4TXAPX9bm1wvnzIH4eVA9Vw\n","JWT Original Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 1, 'username': 'admin'}\n","JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.Qdh_X-DR5ezgt3UEA3h0LrLrWgQT_L0CEOnL6SWuqH4\n","JWT Malicioso Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.ogtauNDtFtBNdgEyyYXc4TXAPX9bm1wvnzIH4eVA9Vw\n","JWT Original Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 2, 'username': 'super-admin'}\n"]}]},{"cell_type":"markdown","source":["### Método para decodificar un JWT\n","Hacemos el método más enfocado en seguir las especificaciones de JWT, donde la firma debe validarse."],"metadata":{"id":"AcDNmA51hA3X"}},{"cell_type":"code","source":["def decode_jwt(token:str, key:str, encoding: str = \"utf-8\") -> tuple[dict, dict]:\n","    # Divide el token en sus componentes separados por puntos (.), asignando los valores a header, payload y signature.\n","    header, payload, signature = token.split('.')\n","    # Decodifica el header del JWT de base64 URL-safe a bytes usando la función y luego convierte esos bytes de JSON a un diccionario Python.\n","    decoded_header = json.loads(b64_decode(header))\n","    # Decodifica el payload del JWT de base64 URL-safe a bytes usando la función y luego convierte esos bytes de JSON a un diccionario Python.\n","    decoded_payload = json.loads(b64_decode(payload))\n","    # Genera una nueva firma digital utilizando la clave secreta (key) y los componentes header y payload del JWT.\n","    signature_to_verify = hmac.new(key.encode(encoding), f\"{header}.{payload}\".encode(encoding), hashlib.sha256).digest()\n","    # Compara la firma recién generada (signature_to_verify) con la firma original del JWT (signature) después de decodificarla de base64 URL-safe a bytes.\n","    # Si la firma no coincide, se lanza una excepción ValueError\n","    if not hmac.compare_digest(signature_to_verify, b64_decode(signature)):\n","      raise ValueError(\"La firma del JWT no coincide.\")\n","    # Retorna una tupla que contiene el encabezado y el payload del JWT decodificados como diccionarios Python.\n","    return decoded_header, decoded_payload"],"metadata":{"id":"XHY-jVkkhVnF"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### Ejemplo modificando un JWT"],"metadata":{"id":"rjYTZC8EiWA9"}},{"cell_type":"code","source":["# Codifica el JWT.\n","jwt: str = encode_jwt(header_data, payload_data, secret)\n","print(f\"JWT Original Codificado: {jwt}\")\n","# Decodifica el JWT.\n","header_decoded, payload_decoded = decode_jwt(jwt, secret)\n","print(f\"JWT Original Decodificado: {header_decoded} {payload_decoded}\")\n","# Modifica el payload_decoded actualizando las claves user_id y username con nuevos valores.\n","payload_decoded.update({\"user_id\": 2, \"username\": \"super-admin\"})\n","# Recodifica un nuevo JWT.\n","jwt_decoded: str = encode_jwt(header_decoded, payload_decoded, secret)\n","print(f\"JWT Codificado: {jwt_decoded}\")\n","# Divide el JWT original en sus partes constituyentes (encabezado, payload, firma).\n","parts = jwt.split(\".\")\n","# Divide el nuevo JWT recodificado en sus partes constituyentes (encabezado, payload, firma).\n","parts_decoded = jwt_decoded.split(\".\")\n","# Crea un \"JWT malicioso\" combinando el encabezado del JWT original, el payload del nuevo JWT, y la firma del JWT original.\n","# Esto intenta simular un ataque donde un actor malicioso modifica el payload sin poder generar una firma válida.\n","jwt_malicious = f\"{parts[0]}.{parts_decoded[1]}.{parts[2]}\"\n","print(f\"JWT Malicioso Codificado: {jwt_malicious}\")\n","# Decodifica el \"JWT malicioso\".\n","try:\n","  header_malicious, payload_malicious = decode_jwt(jwt_malicious, secret)\n","  print(f\"JWT Original Decodificado: {header_decoded} {payload_decoded}\")\n","except ValueError as e:\n","    print(e)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"dSCOU0lZiYSP","executionInfo":{"status":"ok","timestamp":1712630442088,"user_tz":360,"elapsed":143,"user":{"displayName":"Ulises Navarrete Macías","userId":"14476419551800716209"}},"outputId":"eec25f25-3e31-4223-a8bb-45e61d576ec6"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["JWT Original Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImFkbWluIn0.ogtauNDtFtBNdgEyyYXc4TXAPX9bm1wvnzIH4eVA9Vw\n","JWT Original Decodificado: {'alg': 'HS256', 'typ': 'JWT'} {'user_id': 1, 'username': 'admin'}\n","JWT Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.Qdh_X-DR5ezgt3UEA3h0LrLrWgQT_L0CEOnL6SWuqH4\n","JWT Malicioso Codificado: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJ1c2VyX2lkIjogMiwgInVzZXJuYW1lIjogInN1cGVyLWFkbWluIn0.ogtauNDtFtBNdgEyyYXc4TXAPX9bm1wvnzIH4eVA9Vw\n","La firma del JWT no coincide.\n"]}]}]}