Criptografía clásica con Python
Para empezar vamos a describir qué consideramos como criptografía clásica.
Para ello se emplearon diferentes sistemas de cifrado, mediante diferentes transformaciones del mensaje original con operaciones lineales de sustitución y transposición de caracteres.
Estas transformaciones dependían de una clave privada que debía mantenerse en secreto para poder descifrar el texto. Aquellos que no tuvieran acceso a esta clave se encontrarían con un mensaje aparentemente sin sentido.
En algunos casos, esto cambió la historia como la conocemos.
El 17 de Enero de 1917 William Montgomery, criptoanalista de la sección diplomática de la famosa Habitación 40 del Almirantazgo de la Marina Británica en Londres, interceptó un telegrama lleno de códigos que el Ministro de Relaciones Exteriores alemán Arthur Zimmermann envió a su embajador en los Estados Unidos. Tras romper los códigos, descubrieron atónitos que entre otras cosas el mensaje anunciaba la guerra con los Estados Unidos. Con ello entraron en la confrontación mundial y ayudaron a los aliados a ganar la guerra.
En comparación, los sistemas de criptografía moderna hacen uso de propiedades matemáticas como la dificultad computacional del cálculo del logaritmo discreto o el problema de la factorización de grandes números basados en la representación binaria de la información. Gracias a esto el algoritmo puede quedar expuesto públicamente sin comprometer la seguridad. Algunos sistemas incluso pueden compartir una clave pública, como es el caso del RSA.
Otros algoritmos modernos basados en clave secreta como el DES (ya en desuso) o el actualmente utilizado AES hacen uso de conceptos clásicos como los explicados anteriormente, pero su funcionamiento es público.
Por tanto, podemos afirmar que la criptografía clásica abarca los sistemas criptográficos desde el siglo V a.C. hasta la mitad del siglo XX.
La herramienta que te presento permite cifrar, descifrar y romper con fuerza bruta tres de estos sistemas:
Cifrado César
Uno de los cifrados más simples y antiguos, basado en la sustitución de cada uno de los carácteres por aquella letra que se encuentra un número fijo de posiciones en el alfabeto. Este número es la clave de este cifrado. Julio César, quien da nombre a este sistema, utilizaba una clave con un desplazamiento de 3 posiciones.
Realizar esto en Python es bastante sencillo:
MODULE = len(string.ascii_lowercase) # 26 para el alfabeto ASCII inglés
def shift_by(char, shift):
if char.isalpha():
aux = ord(char) + shift
z = 'z' if char.islower() else 'Z'
if aux > ord(z):
aux -= MODULE
char = chr(aux)
return char
def caesar(text, key):
return ''.join(map(lambda char: shift_by(char, key), text))
Cifrado con Escítala
El cifrado utilizado por el ejército espartano consistía en escribir el mensaje en una tira de cuero o papiro enrollada en una vara con un grosor determinado. Esta vara toma el nombre de Escítala y era necesaria una copia exacta para poder descifrar el mensaje enrollando de nuevo la tira en ella.
La escítala se puede representar como una matriz de caracteres donde el grosor o clave es el número de filas. El mensaje cifrado será la matriz leída por columnas.
Así se cifraría en Python, utilizando la librería NumPy:
import numpy as np
import math
def scytale(text, key):
rows = key
cols = math.ceil(size/rows)
m = np.array(list(text.ljust(rows*cols, ' '))).reshape((rows, cols))
return ''.join([''.join(row) for row in m.transpose()]).strip()
Cifrado de Vigenère
Este cifrado utiliza múltiples cifrados césar entrecruzados, de forma que es un cifrado de sustitución polialfabética.
La clave del cifrado es una palabra que se corresponde con una secuencia de desplazamientos césar de forma que un desplazamiento nulo se traduce en una A
, un desplazamiento de 2 se traduce en una B
y así sucesivamente hasta la Z
, que corresponde a un desplazamiento de 25 en caso del alfabeto inglés y a 26 en caso del alfabeto español.
Esta palabra clave se repite hasta que cada palabra del mensaje a cifrar tenga una letra de la clave asociada. Después se realiza el cifrado césar para cada letra del mensaje con el desplazamiento correspondiente a la letra clave asociada.
Para cifrar manualmente nos podemos ayudar de la tabla de Vigenère, también conocida como tabula recta, de forma que tomando la fila con la letra de la clave para cifrar podemos buscar la letra correspondiente en la columna de la letra del mensaje.
Este sería el cifrado en Python, utilizando el método shift_by
del cifrado César:
def vigenere(text, key, decrypt=false):
shifts = [ord(k) - ord('a') for k in key.lower()]
i = 0
def do_shift(char):
nonlocal i
if char.isalpha():
shift = shifts[i] if not decrypt else MODULE - shifts[i]
i = (i + 1) % len(key)
return shift_by(char, shift)
return char
return ''.join(map(do_shift, text))
Para instalar y jugar con estos sistemas de cifra clásica tan sólo tienes que seguir las instrucciones del repositorio de GitHub:
CryptToolsTambién puedes mirar cómo se implementa el criptoanálisis para romper cada uno de estos sistemas, e incluso puedes colaborar a mejorar este proyecto 😉.
Hay que tener en cuenta que los sistemas de cifrado clásico no son seguros para las comunicaciones digitales (esta herramienta y muchas otras permiten romperlos en cuestión de segundos), por lo que su uso debe restringirse al didáctico y personal.
Para cifrar mensajes telemáticos se utilizan otros sistemas criptográficos modernos como AES, RSA o BCrypt.
Espero que disfrutes con esta herramienta y nos vemos en el próximo post.