Nuestro Código Python

 La respuesta es.... SIII!!!


Hemos desarrollado un código en Python que realiza todo el proceso que hemos explicado anteriormente, lo que nos puede ahorrar mucho tiempo de trabajo. 

Para ver, ejecutar o modificar el código por tu cuenta, puedes acceder a este enlace Encriptación - Métodos Numéricos. Aunque en este post te vamos a mostrar el código principal que hemos desarrollado.

Todo el proceso principal está metido dentro de una clase que hemos llamado Proceso().

La primera función con la que nos encontramos es la función f, que define la ecuación no lineal con la que trabajaremos. En nuestro caso, hemos definido esta ecuación como f(x) = 3,5x^3 + xe^x, pero si quieres modificarla puedes cambiar esta línea de código. Justo después tenemos otra función que nos define la correspondiente función de Newton-Raphson. En el caso de haber modificado la función f, también se debe modificar su función de Newton-Raphson a mano.

def f(self, x):

        return 3.5 * x**3 + x * math.exp(x)

def gN(self, x):

        return x - (self.f(x) / (10.5 * x**2 + x * math.exp(x) + x*math.exp(x)))

La siguiente función que encontramos es ya la función que realiza la encriptación del mensaje

def encriptar(self):

        print('Introduce el mensaje a encriptar:')

        mensaje = input('>> ')  

        mensaje_encriptado = []

        for c in mensaje:

            valor_ascii = ord(c)

            eq = lambda x: 3.5 * x**3 + x * math.exp(x) - valor_ascii

            raiz = self.newton_raphson(eq, 2)

            mensaje_encriptado.append(str(raiz))

        return '|'.join(mensaje_encriptado)

En esta función vemos que nos pide introducir el mensaje a encriptar y lo guarda en la variable mensaje

. Después va iterando cada carácter del mensaje, le asigna su valor ASCII, crea su correspondiente ecuación de Newton-Raphson y finalmente obtiene su solución a través de la función newton_raphson(), que toma dos argumentos: la ecuación y la semilla. La función devuelve cada una de estas soluciones unidas por el símbolo '|'.

Tras encriptar, tenemos la función desencriptar que, al igual que la función anterior, nos pide un mensaje a desencriptar. Analiza el mensaje introducido y genera una lista de raíces, identificando donde empiezan y dónde terminan por el símbolo '|' que anteriormente hemos usado para unirlas. Itera cada una de las raíces y encuentra su valor ASCII introduciéndolas en la función f() definida al principio del código. 

def desencriptar(self, mensaje = ''):

        if mensaje == '':

            print('Introduce el mensaje a desencriptar:')

            mensaje = input('>> ')

        mensaje_desencriptado = ""

        raices = mensaje.split('|')

        for raiz in raices:

            raiz = float(raiz)

            valor_ascii = round(self.f(raiz))

            mensaje_desencriptado += chr(valor_ascii)

        return mensaje_desencriptado

Por último, nos encontramos con la función newton_raphson() que previamente hemos usado en encriptar(). Esta función itera hasta encontrar la raíz de la función.

def newton_raphson(self, f, x0, epsilon=1e-8, max_iterations=100):

        x = x0

        for _ in range(max_iterations):

            fx = f(x)

            f_prime_x = (f(x + epsilon) - fx) / epsilon

            x = x - fx / f_prime_x

            if abs(fx) < epsilon:

                return x

        return x