En este post incluyo y comento un script en python para el cifrado y descifrado utilizando el cifrado de Polibio.
Antes de poner el script, comentar cómo se cifraba y descifraba manualmente.
El cifrado de Polibio se basa en una tabla de 5 x 5 (5 filas y 5 columnas) cuyas celdas o casillas se completan, desde la primera a la última fila, y en cada una de ellas desde la primera a la última columna, con las letras del alfabeto (la "I" y la "J" comparten celda, y "Ñ" excluida), de la siguiente forma:
En el script las funciones de cifrado y descifrado se implementan de la siguiente manera:
- Cifrar:
Para cifrar se sustituía cada carácter del texto en claro por el dígito de la fila y el dígito de la columna en cuya intersección se encontraba éste. Por ejemplo: la letra "E" se sustituía por 15.
En el script el cifrado se implementa de la siguiente manera:
str((alfabeto.find(caracter)//5)+1) + str((alfabeto.find(caracter)%5)+1)
- alfabeto.find(caracter): el método find() encuentra la primera ocurrencia del valor especificado en una cadena de caracteres y devuelve la posición que ésta ocupa. La primera posición es 0 y si no se encuentra el valor devuelve -1.
En el script encuentra la ocurrencia del carácter del texto en claro en el alfabeto y devuelve su posición en el mismo (de 0 a 24).
Por ejemplo, si el carácter fuese la "E" devolvería 4.
- //: el operador // obtiene el cociente de dividir el operando 1 entre el operando 2.
- %: el operador % obtiene el resto de dividir el operando 1 entre el operando 2.
- (alfabeto.find(caracter)//5)+1): obtiene el primer dígito correspondiente al cifrado del carácter, que es el correspondiente a la fila en la que se halla éste.
Por ejemplo, si el carácter fuese la "E" devolvería el cociente de 4/5 más 1, es decir, 0 + 1 = 1.
- (alfabeto.find(caracter)%5)+1): obtiene el segundo dígito correspondiente al cifrado del carácter, que es el correspondiente a la columna en la que se halla éste.
Por ejemplo, si el carácter fuese la "E" devolvería el resto de 4/5 más 1, es decir, 4 + 1 = 5.
La concatenación de estos dos último dígitos da como resultado el par de dígitos que le corresponden en el criptograma al carácter a cifrar. si el carácter fuese la "E" el par de dígitos sería 15.
- Descifrar:
De forma recíproca, para descifrar se sustituía cada par de dígitos del criptograma por la letra que se encontraba en la intersección de la fila (primer dígito) y columna (segundo dígito). Por ejemplo: el par de dígitos 15 se sustituía por la "E".
En el script el descifrado se implementa de la siguiente manera:
str(alfabeto[((int(digito1)-1)*5) + (int(digito2)-1)])
alfabeto[((int(digito1)-1)*5) + (int(digito2)-1)]: obtiene el carácter descifrado buscando el que se encuentra en el alfabeto en la posición que resulta de la suma del primer dígito que le correspondió en el cifrado menos 1 y multiplicado por 5 (número de columnas) más el segundo dígito que le correspondió en el cifrado menos 1.
Por ejemplo, si el par de dígitos de un carácter a descifrar es 15, ((1 - 1) * 5) + (5 - 1) = 0 + 4 = 4, que es la posición en la que se encuentra la letra "E" en el alfabeto.
- Script python del cifrado de Polibio:
El script es el siguiente:
#!/usr/bin/env python # -*- coding: utf-8 -*- # CIFRADO DE POLIBIO # # Cifra y descifra textos en claro y criptogramas, respectivamente, # utilizando el cifrado de Polibio. # # http://mikelgarcialarragan.blogspot.com/ import re from unicodedata import normalize # ALFABETO: alfabeto = "ABCDEFGHIKLMNOPQRSTUVWXYZ" # FUNCIÓN DE CIFRADO: def cifrar(texto_claro): criptograma = '' for caracter in texto_claro: criptograma = criptograma + str((alfabeto.find(caracter)//5)+1) + str((alfabeto.find(caracter)%5)+1) return criptograma # FUNCIÓN DE DESCIFRADO: def descifrar(criptograma): texto_claro = '' for i in range(0,len(criptograma)-1,2): digito1 = criptograma[i] digito2 = criptograma[i+1] texto_claro = texto_claro + str(alfabeto[((int(digito1)-1)*5) + (int(digito2)-1)]) return texto_claro # MENÚ: # Se presenta el menú para que se seleccione una opción. def main(): salir = False while not salir: print ("") print ("*** MENÚ *****************************************") print ("1. Cifrar.") print ("2. Descifrar.") print ("3. Salir.") print ("") opcion = input("Por favor, seleccione una opción: ") if opcion == "1": print ("") print ("--- CIFRAR:") # Cifrar: Se introduce el texto en claro. Se convierten los caracteres a mayúsculas, # el carácter "J" se sustituye por "I" y la letra "Ñ" por "N", y se eliminan los espacios, # las tildes, diéresis, etc. texto_claro = "*" while not texto_claro.isalpha(): texto_claro = input('Texto en claro a cifrar: ').upper() texto_claro = texto_claro.replace('J','I') texto_claro = texto_claro.replace('Ñ','N') texto_claro = texto_claro.replace(' ','') texto_claro = re.sub(r"([^n\u0300-\u036f]|n(?!\u0303(?![\u0300-\u036f])))[\u0300-\u036f]+", r"\1", normalize("NFD", texto_claro), 0, re.I) texto_claro = normalize("NFC", texto_claro) if texto_claro.isalpha(): print ("[+] Texto en claro a cifrar:", texto_claro) criptograma = cifrar(texto_claro) print ("[+] Criptograma:", criptograma) else: print ("*** ERROR: El texto en claro a cifrar sólo debe contener caracteres alfabéticos.") elif opcion == "2": print ("") print ("--- DESCIFRAR:") # Descifrar: Se introduce el criptograma. criptograma = "*" while not criptograma.isnumeric() or len(criptograma)%2 != 0: criptograma = input('Criptograma a descifrar: ') if criptograma.isnumeric(): for digito in criptograma: if int(digito) < 1 or int(digito) > 5: criptograma = "*" break if criptograma.isnumeric(): if len(criptograma)%2 == 0: print ("[+] Criptograma a descifrar:", criptograma) texto_claro = descifrar(criptograma) print ("[+] Texto en claro:", texto_claro) else: print ("*** ERROR: El criptograma debe tener un número par de dígitos.") else: print ("*** ERROR: El criptograma a descifrar sólo debe contener dígitos del 1 al 5.") else: print ("*** ERROR: El criptograma a descifrar sólo debe contener dígitos.") elif opcion == "3": print ("*** FIN ******************************************") salir = True else: print ("*** ERROR: Opción no válida.") if __name__ == '__main__': main()
Lo ejecuto:
- Cifrar:
Nótese que el script ha sustituido el carácter "j" que se ha introducido en el texto en claro a cifrar por "I", ya que "I" y "J" comparten la misma celda en el cuadrado de Polibio. Además, si se hubiera introducido la letra "Ñ" el script la habría sustituido por "N".
- Descifrar:
Comentarios
Publicar un comentario