Fundamentos Prácticos de Criptografía, Redes y Esteganografía en Ingeniería Informática

PRÁCTICA 1: Concurrencia y Criptografía Básica

Limitaciones de recv y accept (Sockets Bloqueantes)

  • La función recv bloquea la ejecución del programa hasta que el otro extremo del socket envía datos o cierra la conexión.
  • La función accept bloquea la ejecución del programa hasta que se conecta un cliente.
  • Esto implica que solo se pueda atender a un cliente a la vez (esquema cliente: enviar–recibir–enviar / servidor: recibir–enviar–recibir).

select: Solución al Bloqueo de Sockets

(SOLUCIONA EL PROBLEMA DE BLOQUEO DE RECV Y ACCEPT)

  • Permite manejar múltiples conexiones simultáneas monitorizando varios sockets.
  • Evita bloqueos indefinidos de recv/accept y permite salir mediante temporizador.
  • Permite gestionar varios clientes sin crear un hilo por conexión (menor consumo de recursos).
  • Puede esperar lectura, escritura o condiciones excepcionales (como mensajes urgentes).

Hilos (Threads) para Concurrencia

  • En un chat multiusuario sencillo se suelen usar dos hilos: uno para la gestión del socket y otro para la entrada por teclado.
  • Se utiliza el módulo threading y la clase Thread.
  • Ejemplo de creación de hilo: nuevo_hilo = threading.Thread(target=función, args=(param,))

Cifrado Afín

La inversa modular a⁻¹ se calcula como ainv = pow(a, −1, m). Este concepto no se utiliza directamente para el cifrado y descifrado AES.

Cifrador OTP (One-Time Pad)

  • Basado en la operación XOR.
  • Generación de flujo de claves (keystream) con el módulo secrets:
import secrets
keystream = ''
for i in range(key_length):
	keystream += secrets.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ')

PRÁCTICA 2: Cifrado Simétrico Avanzado (AES)

Cifrado Simétrico AES en Modo ECB

  • Se utiliza la biblioteca cryptography.
  • Generación de clave: key = os.random(16) genera una clave de 16 bytes (128 bits).
  • Inicialización del cifrador: aesCipher = Cipher(algorithms.AES(key), modes.ECB())
  • Creación de objetos de cifrado/descifrado:
    • aesEncryptor = aesCipher.encryptor()
    • aesDecryptor = aesCipher.decryptor()
  • La función update() solo devuelve salida cuando acumula 16 bytes (un bloque completo).

Ejemplos de Comportamiento de update() (Bloque de 16 bytes)

  • b'Alice' (5 bytes) → nada
  • b'Alice Alice' (10 bytes) → nada
  • b'Alice Alice Alice' (15 bytes) → nada
  • b'Alice Alice Alice A' (20 bytes) → Devuelve 16 bytes cifrados (AliceAliceAliceA), y los 4 bytes restantes (“lice”) se guardan internamente.

Funciones de Conversión de Datos

  • bytes.fromhex(): Convierte una cadena hexadecimal a bytes.
  • hex(): Convierte bytes a una cadena hexadecimal.

Conversión entre Enteros y Bytes

def int_to_bytes(i):

return i.to_bytes(16, byteorder="big") (Convierte de entero a bytes, usando 16 bytes y orden big-endian)

def bytes_to_int(b):

return int.frombytes(b, byteorder="big") (Convierte de bytes a entero, usando orden big-endian)

Cifrado de Imágenes .BMP

  • Apertura del archivo: img = open('imagen.bmp','rb')
  • Lectura de datos: data = img.read()
  • Importante: No cifrar los primeros 54 bytes (que corresponden a la cabecera de la imagen).
  • Cifrar solo los datos de los píxeles.

Cifrado AES en Modo CBC y Padding

  • El modo CBC (Cipher Block Chaining) requiere que los datos se procesen en bloques completos. Si el mensaje no es múltiplo del tamaño del bloque (16 bytes), es necesario usar padding (relleno).
  • El padding más sencillo es añadir ceros (y quitarlos al descifrar), aunque se recomienda PKCS7.

Añadir Relleno (Padding PKCS7)

data = b'mensaje'
padder = padding.PKCS7(128).padder()
padded_data = padder.update(data) + padder.finalize()

Eliminar Relleno (Unpadding PKCS7)

unpadder = padding.PKCS7(128).unpadder()
data = unpadder.update(padded_data) + unpadder.finalize()

Vector de Inicialización (IV) en AES

  • El IV es necesario en CBC para aportar aleatoriedad al cifrado.
  • Se combina mediante XOR con el primer bloque de texto plano, y el resultado del cifrado se usa como IV para el siguiente bloque.
  • Debe ser único para cada mensaje, no necesita ser secreto, y se transmite junto con el mensaje cifrado.

Concepto de Padding en AES

  • AES utiliza bloques de 128 bits (16 bytes).
  • Si el mensaje no es un múltiplo exacto de 16 bytes, debe agregarse relleno (padding) para completar el último bloque.

PRÁCTICA 3: Esteganografía LSB

Biblioteca PIL (Pillow)

  • Biblioteca fundamental para la manipulación de imágenes, utilizada comúnmente para implementar marcas de agua y esteganografía.

Esteganografía LSB (Least Significant Bit)

  • Oculta información en el bit menos significativo de cada componente de color (RGB).
  • Los cambios resultantes son imperceptibles al ojo humano.
  • No aumenta el tamaño del archivo de imagen.

Cálculo del Máximo de Bits Ocultables

max_bits = imagen.size[0] * imagen.size[1] * canales * n

  • canales: 3 para RGB, 4 para RGBA.
  • n: Número de bits LSB utilizados por canal (por defecto, n=1 si no se especifica).

Ocultación de Mensajes: Conversión a Binario

Para ocultar un mensaje, primero se convierte cada carácter en su representación de 8 bits:

mensaje_bin = ''.join([format(ord(x), '08b') for x in mens])

Esto genera una cadena de bits del mensaje, donde cada carácter ocupa 8 bits (formato binario 00000000–11111111).

Modificación del Bit Menos Significativo

Acceder y modificar el bit menos significativo de un componente de color (r): r = r[:-1] + bit_a_ocultar

CONCEPTOS ADICIONALES Y CIFRADO CLÁSICO

Conversión de Bases y Manipulación de Cadenas

  • int(num_binario, 2): Convierte una cadena binaria a su representación decimal (entero).
  • text = text.upper(): Convierte todo el texto a mayúsculas.

Cifrado César: Implementación y Ataque

Fórmula de Cifrado César (para mayúsculas)

chr((ord(char) − 65 + s) % 26 + 65)

  • ord(char): Obtiene el código ASCII del carácter.
  • ord(char) - 65: Ajusta el rango para que ‘A’ sea 0, ‘B’ sea 1, etc.
  • (ord(char) - 65 + s) % 26: Aplica el desplazamiento (s) y asegura que el resultado se mantenga dentro de las 26 letras del alfabeto (módulo 26).
  • + 65: Vuelve al rango ASCII de las letras mayúsculas.
  • chr(...): Convierte el número resultante de nuevo en un carácter.

Funcionalidad: El código toma un carácter (almacenado en char), lo desplaza en el alfabeto por la cantidad definida por la variable s utilizando el cifrado de César, y devuelve el carácter cifrado.

Ataque por Fuerza Bruta al Cifrado César

Se prueban todos los posibles desplazamientos (claves) de 1 a 25:

for s in range(1, 26):
	result = ""
	# probar todos los resultados

Intercambio de Mensajes Cifrados con RSA (Alice y Bob)

Alice envía a Bob

  • Alice necesita la clave pública de Bob (n_Bob, e_Bob).
  • Alice cifra el mensaje con la clave pública de Bob.
  • Bob descifra el mensaje con su clave privada (n_Bob, d_Bob).

Bob envía a Alice

  • Bob necesita la clave pública de Alice (n_Alice, e_Alice).
  • Bob cifra el mensaje con la clave pública de Alice.
  • Alice descifra el mensaje con su clave privada (n_Alice, d_Alice).

Resumen de Conceptos Clave

  1. En un servidor TCP sin hilos, recv se bloquea esperando datos y accept esperando conexiones, impidiendo atender a varios clientes a la vez. select monitoriza múltiples sockets y avisa cuáles tienen actividad, de modo que el servidor solo usa recv o accept cuando realmente hay algo que atender, evitando bloqueos y permitiendo gestionar varios clientes sin necesidad de hilos.
  2. Ejemplo de manipulación de bits: int(a[:-4], 2)
    • 1. Se toman todos los números de la cadena a excepto los 4 últimos.
    • 2. La subcadena resultante se convierte a entero (decimal) asumiendo que está en base 2 (binario). Ejemplo: si la subcadena es 0011, el resultado es 3 (1*1 + 1*2 + 0*4 + 0*8 = 3).

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.