Skip to content

naibu3/cifrado-afin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 

Repository files navigation

cifrado-afin

Cifrador/descifrador de código afin

Suponiendo que tenemos un alfabeto como el indicado en la pregunta 1 (indicado a continuación), utilizar un sistema de cifrado César adecuado para descifrar el siguiente texto: FDEXDXZTFDTPLCZDPXKWX

Introducción

Tras leer el enunciado, extraemos como datos el alfabeto [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] y la expresión codificada FDEXDXZTFDTPLCZDPXKWX. Además, se nos dió la pista de que se trata de un cifrado afín.

Para resolverlo utilizaremos python, en su versión 3.8, ya que permite un manejo cómodo de listas y cadenas de texto, además de poseer una sintaxis sencilla. La metodología será un ataque de fuerza bruta, con la que intentaremos romper la contraseña probando todas las combinaciones posibles. Ya definido el problema, vamos con el código.

Código

Empezaremos con la cabecera clásica y el tipo de encoding, además importaremos la función del máximo común divisor (gcd()) de la librería matemática para usarla más adelante.

#!/usr/bin/python3
#_*_utf-8_*_

from math import gcd

A continuación definiremos tres variables con los datos del problema para utilizarlos más cómodamente.

n_elem=26

abcedario=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
	 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

codigo="FDEXDXZTFDTPLCZDPXKWX"

Después, implementaremos la función de descifrado. En el ejercicio anterior explicamos como se cifra y descifra, así como las fórmulas y procedimientos. En concreto, la función que descifra sería: D(x) = a⁻¹*(x-b) mod m, donde x es el índice de cada letra en el alfabeto, a y b, las constantes de decimación y desplazamiento; y m el número de elementos del alfabeto.

def descifrar(code, abc, elem, a, b):

	#Dclaramos una lista para guardar el resultado
	code_descif=[]

	#Recorremos la cadena de codigo cifrado
	for i in code:

		#Guardamos el indice en el alfabeto de cada elemento cifrado
		ind = int(abc.index(i))

		#Aplicamos la formula inversa y lo añadimos a la lista 
		ind_orig=int( (ind-b)*pow(a, -1, elem) % elem )

		code_descif.append(abc[ind_orig])
	
	#Devolvemos la lista de elementos descifrados convertida a cadena
	return "".join(code_descif)

En el bucle principal, probaremos todas las posibles combinaciones de a y b para el alfabeto dado. Esto implica que solo servirán las a que sean primas entre sí con el número de elementos (el máximo común divisor es 1), condición que semencionó anteriormente.

if __name__=="__main__":

	for a in range(0, n_elem+1):

		if (gcd(a, n_elem)==1):

			for b in range(0,n_elem+1):

				#Imprimo el codigo descifrado junto a la a y b correspondientes
				print(descifrar(codigo, abcedario, n_elem, a, b) + " -> a=" + str(a) + ", b=" + str(b))
				print("")

Tras la ejecución obtendremos una lista de más de 300 elementos por pantalla, que podremos leer uno a uno para encontrar aquel que sea legible. Puede parecer tedioso pero es la forma más simple de resolverlo. Sin embargo, en caso de que se quiera mejorar el script, se puede implementar con un análisis de frecuencia que muestre las opciones más probables primero para facilitar este último paso.

[...]

XHCLHLBFXHFZTMBHZLYQL -> a=5, b=20

CMHQMQGKCMKEYRGMEQDVQ -> a=5, b=21

HRMVRVLPHRPJDWLRJVIAV -> a=5, b=22

MWRAWAQUMWUOIBQWOANFA -> a=5, b=23

RBWFBFVZRBZTNGVBTFSKF -> a=5, b=24

WGBKGKAEWGEYSLAGYKXPK -> a=5, b=25

BLGPLPFJBLJDXQFLDPCUP -> a=5, b=26

XTIHTHLZXTZRJELTRHUSH -> a=7, b=0

IETSESWKIEKCUPWECSFDS -> a=7, b=1

TPEDPDHVTPVNFAHPNDQOD -> a=7, b=2

EAPOAOSGEAGYQLSAYOBZO -> a=7, b=3

PLAZLZDRPLRJBWDLJZMKZ -> a=7, b=4

AWLKWKOCAWCUMHOWUKXVK -> a=7, b=5

LHWVHVZNLHNFXSZHFVIGV -> a=7, b=6

WSHGSGKYWSYQIDKSQGTRG -> a=7, b=7

HDSRDRVJHDJBTOVDBRECR -> a=7, b=8

SODCOCGUSOUMEZGOMCPNC -> a=7, b=9

DZONZNRFDZFXPKRZXNAYN -> a=7, b=10

OKZYKYCQOKQIAVCKIYLJY -> a=7, b=11

[...]

Como ya encontré la frase cifrada pude comprobar rápidamente si el script funcionaba:

❯ python3 afindecoder.py | grep SUERTE

OSDESEAMOSMUCHASUERTE -> a=19, b=25

Fuentes

Este código es fruto de la investigación recogida en mi post sobre cifrado cesar y afin, donde se encuntran las fuentes consultadas y una explicación detallada. Además dejaré tanto el script como la versión mejorada con análisis de frecuencias en mi github por si alguien quisiera descargarlo.

¡ TPLCZDJKZLVZDYFKAXXKXDWXYFDW !

About

Cifrador/descifrador de código afin

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published