<jupyter_start><jupyter_text>Trabajo final de Criptografía El secreto Japonés: la Máquina PúrpuraMarta <NAME> y <NAME>  ¿Qué es la máquina púrpura?La ___Type B Cipher Machine___ o la ___System 97 Typewriter for European Characters___ fue una máquina criptográfica usada por el gobierno japonés antes y durante la __Segunda Guerra Mundial__. El nombre en clave que EEUU le dio a esta máquina es ___Purple___. La información que EEUU obtenía descifrando los mensajes tuvo el nombre en clave de ___Magic___.La marina japonesa pensaba que la _Purple_ era tan difícil de romper que no se molestaron en revisarla y mejorar su seguridad. Al parecer, esto era debido a que el matemático _Teiji Takagi_ (que no tenía mucha base sobre criptoanálisis) así lo dijo. Nadie en el gobierno japonés se dio cuenta de los puntos débiles que tenía la máquina.Al final de la guerra, el ejército advirtió a la marina sobre un punto débil en _Purple_, pero la marina no le hizo caso._Purple_ fue una revisión mejorada de la máquina ___Red___ introducida a principios del año 1939, que introducía una mayor complejidad y sofisticación que su máquina antecesora.. _Purple_ heredó de _Red_ un punto débil (y además ya conocido): seis letras del alfabeto se encriptaban de forma separada. La diferencia entre ambas es que la _Purple_ cambiaba dichas letras cada nueve días y en la _Red_, eran fijas. El funcionamiento de PurplePurple es una máquina criptográfica muy especial por varias razones. Una de ellas es su propia mecánica, y es que era de las pocas máquinas que utilizaban __interruptores de paso__ o __relés paso a paso__ como elemento de cifrado, y la otra razón es la división que hacía del alfabeto.Purple dividía el alfabeto en dos grupos. Uno de ellos contiene 6 letras del alfabeto y el otro grupo 20, y ambos grupos utilizan algoritmos de cifrado distintos.Purple fue y es aún hoy, una complicada máquina de cifrado, compuesta principalmente por tres partes:* __Una máquina de escribir eléctrica__: esta máquina era la encargada de introducir la preciada información en la máquina para su cifrado.* __Sistema de cifrado__: este sistema consisitía en la _plugboard_ al que estaban conectados cuatro interruptores paso a paso, junto con los distintos cables.* __Sistema de impresión__: este sistema imprimía el mensaje encriptado por la máquina. Interruptores paso a paso![switch](http://cryptocellar.org/simula/purple/stepsw.gif)Este tipo de interruptores conectaba una entrada a una de las posibles 25 salidas, que dada una entrada, se aplciaba un pulso electromagnético que daba una salida y avanzaba el interruptor a la siguiente posición, lo que permitía obtener un cifrado en el que las letras no estaban relacionadas si se conectaba correctamente.Este tipo de interruptores son una de las diferencias de la máquina Enigma de la que nació originalmente la máquina Red, y es que Enigma usaba rotores, mientras que Purple, apostó por los _switches_ eléctricos.La máquina constaba de cuatro _switches_, uno conocido como ___sixes___, que indicaban la posición inicial del primer rotor, que cifraba seis letras, y tres rotores más conocidos como los ___twenties___, de los cuales se configuraría un interruptor rápido, uno medio y uno lento.Los tres _twenties_ pueden configurarse como __rápido__, __medio__ y __lento__. Cifrado del mensajeLa máquina era capaz de aceptar tres alfabetos diferentes, el ___alfabeto inglés___, el ___alfabeto romaji___ (romanización del alfabeto japonés) y el ___alfabeto del latín___. Uno de los problemas que tenía la máquina es que no era capaz de encriptar los símbolos de puntuación del lenguaje o números, por lo que el operario que introdujera el mensaje, tendría que mirar estos caracteres en un libro que guardaba los códigos correspondientes e introducirlos en la máquina.Para poder usar la máquina, se debía establecer una clave simétrica que usarían ambas partes tanto para cifrar como para descifrar el mensaje, siendo esta clave el abecedario a usar, qué letras corresponderían a los _sixes_, a los _twenties_, y la configuración de los switches. Para que el cifrado funcionara, ambas máquinas deben tener la misma configuración inicial.![switch1](http://cryptocellar.org/simula/purple/purple1z.gif)Cada letra de la máquina de entrada podía estar conectada a cualquier letra de la máquina Purple, siendo posible conectar una letra a los _sixes_ y a los _twenties_, por lo que si la señal eléctrica pasaba al cable de los _sixes_, se cifraría con este switch, sin embargo, si pasaba a los _twenties_, se cifraría con estos.![switch2](http://cryptocellar.org/simula/purple/purpleplugboard2.gif)Esto supone un escenario muy curioso, ya que, las letras que se cifran con los _sixes_, se usa un switch de 6 niveles con 25 posiciones, donde cada posición produce un alfabeto distinto, y cada vez que se cifra un caracter, se avanza una posición el switch. Por lo tanto, en este caso, el alfabeto que genera cada una de los niveles de la máquina se repetirá cada 25 letras.Sin embargo, el caso de los _twenties_ viene a ser algo muy diferente, y consiste en que para cifrar un carácter, se utilizan todos los rotores _twenties_, entrando una letra al primer switch, cifrándola y usando la salida como entrada para el siguiente switch. Así los tres _twenties_. Cada vez que se cifra un carácter de los _twenties_, __sólo uno de los switches avanza__, lo que hace que, para que se repita el alfabeto que produce el caracter necesitamos $25^3 = 5^6 = 15625$ caracteres cifrados. Además de esto, cualquiera de los tres switches puede ser el rápido, el medio o el lento, lo que aumenta la dificultad del cifrado al haber más variedad en el movimiento de la máquina, lo que produce elementos casi aleatorios. La configuración de estos switches hacía que cuando el rápido avanzara 25 posiciones, el medio avanzaría una y cuando este último avanzara 25 posiciones, el lento rotaría una posición. ¿Cómo se rompió Purple?Una vez los estadounidenses interceptaron suficientes mensajes encriptados por _Purple_, empezaron a intentar romper su cifrado. Hay varios puntos clave sobre este proceso:* La predecesora de _Purple_, _Red_, ya se había roto varios años atrás y esto dio a los criptoanalistas varias pistas para poder romper _Purple_.* Los estadounidenses sabían la estructura general de los mensajes. Por ejemplo, muchos mensajes solían empezar diciendo "I have the honor to inform Your Excellency...".* A veces los criptoanalistas obtenían información sobre el contenido del mensaje y trataban de adivinar dónde se encontraban estas palabras clave en el mensaje.* Otras veces obtenían directamente el texto plano y su correspondiente cifrado con _Purple_.* De vez en cuando, los operarios se equivocaban con la clave y enviaban el mismo texto cifrado con dos claves diferentes.* Y, también hubo otras veces en las cuales obtuvieron el mismo texto cifrado tanto con _Red_ como con _Purple_. Al estar _Red_ ya rota, obtenían el texto plano directamente.Todo esto, dio patrones a los criptoanalistas claves para poder romper _Purple_. Una vez consiguieron un modelo matemático aproximado de cómo funcionaba _Purple_, hicieron una máquina réplica. Tras esto, trataron de adivinar cómo los japoneses generaban las diferentes claves. Descubrieron que cada mes se dividía en tres grupos (períodos de 10 días) en el que cada grupo tenía un tipo de patrón. También descubrieron que la clave del primer día de cada grupo, era la misma que la de los siguientes 9 días pero cambiando el orden. Aún así, aún tenían el problema de adivinar la clave cada 10 días.  Paquete `purple` de PythonHay disponible un paquete de Python y programa para la línea de comandos que emula el comportamiento de _Purple_. Vamos a cifrar y descifrar varios mensajes para mostrar su funcionamiento.En primer lugar, debemos crear una instancia de la clase `Purple97`, que representa una máquina Purple con una determinada configuración de rotores y alfabeto. El alfabeto por defecto es AEIOUYBCDFGHJKLMNPQRSTVWXZ.<jupyter_code>from purple.machine import Purple97

cypher_machine = Purple97(switches_pos=[6,1,24,15], fast_switch=3,
            middle_switch=2, alphabet=None)
encrypted = cypher_machine.encrypt('KUNGFUALAMANECER')
print("Encrypted message:", encrypted)<jupyter_output>Encrypted message: KUJGJAELAXYXECOP<jupyter_text>Para descifrar el texto, tenemos que crear otra máquina diferente pero con la misma configuración que la primera. Si no, estaríamos cifrando el texto cifrado de nuevo.<jupyter_code>decypher_machine = Purple97(switches_pos=[6,1,24,15], fast_switch=3,
            middle_switch=2, alphabet=None)
decrypted = decypher_machine.decrypt(encrypted)
print("Decrypted message:", decrypted)<jupyter_output>Decrypted message: KUNGFUALAMANECER<jupyter_text>También se puede probar a cambiar el alfabeto de entrada en la máquina, y ver cómo la misma configuración cambia totalmente el cifrado.<jupyter_code>from random import shuffle
from string import ascii_uppercase

# Obtenemos un nuevo alfabeto
def generate_alphabet():
    alphabet = list(ascii_uppercase)
    shuffle(alphabet)          # lo barajamos
    alphabet=''.join(alphabet) # y obtenemos la cadena
    return alphabet
    
alphabet = generate_alphabet()
print(alphabet)
# Creamos las máquinas de cifrado y descifrado
cypher_machine = Purple97(switches_pos=[6,1,24,15], fast_switch=3,
            middle_switch=2, alphabet=alphabet)
decypher_machine = Purple97(switches_pos=[6,1,24,15], fast_switch=3,
            middle_switch=2, alphabet=alphabet)

# Encriptamos el mensaje
encrypted = cypher_machine.encrypt('KUNGFUALAMANECER')
descifrado = decypher_machine.decrypt(encrypted)

print("Mensaje cifrado:", encrypted)
print("Mensaje descifrado:", decrypted)<jupyter_output>Mensaje cifrado: JLAGOWSQWWQSTPBD
Mensaje descifrado: KUNGFUALAMANECER<jupyter_text>E incluso cambiar las posiciones de los switches y la qué switch es el lento, el rápido...<jupyter_code>new_alphabet = generate_alphabet()

cypher_machine = Purple97(switches_pos=[2,8,1,22], fast_switch=2,
            middle_switch=3, alphabet=new_alphabet)
decypher_machine = Purple97(switches_pos=[2,8,1,22], fast_switch=2,
            middle_switch=3, alphabet=new_alphabet)

message = "ELPODERDESGASTAAQUIENNOLOTIENE"

encrypted = cypher_machine.encrypt(message)
decrypted = decypher_machine.decrypt(encrypted)

print("Mensaje cifrado:", encrypted)
print("Mensaje descifrado:", decrypted)<jupyter_output>Mensaje cifrado: BVDGYXWSJFSANJMANLFUKXHDJBPITU
Mensaje descifrado: ELPODERDESGASTAAQUIENNOLOTIENE
{'fraction_non_alphanumeric': 0.041943442778515846, 'fraction_numerical': 0.00958436135889163, 'mean_word_length': 5.37953995157385, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '289989', 'license': 'MIT', 'n_tokens_mistral': 3470, 'n_tokens_neox': 3431, 'n_words': 1426, 'path': 'Purple-Machine.ipynb', 'repo_name': 'BraulioV/Maquina-Purple', 'size': '10558'}