La ventaja principal de utilizar éste algoritmo, es que hace que aunque nuestro mensaje cifrado sea visible para personas distintas del emisor y receptor, éstas no puedan realizar ataques estadísticos, ni algún tipo de intuición para acercarse al mensaje original.
Al final se elimina la clave o claves utilizadas, para darle aún más seguridad a nuestro envío y recepción de mensajes.
Existen tres programas con sus respectivas funciones dentro del algoritmo.
El primero, se encarga de crear las claves y almacenarlas en la libreta y su copia.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import shuffle #importamos la funcion shuffle desde random | |
def stringear(claves): #Funcion que transforma las claves en un string | |
cadena="" | |
for k in claves: #for que toma los elementos de la lista claves | |
cadena += str(claves[k]) + " " #se agrega cada elemento a la cadena y los separa con un espacio | |
cadena +="\n" #se agrega un salto de linea | |
return cadena #devuelve cadena | |
def crearclaves (n, cant): #funcion que crea las claves | |
f_nuevo= open("pruebas/libreta.txt", "w") #creamos el archivo de las claves | |
f_nuevo2= open("pruebas/copialibreta.txt", "w") #creamos la copia | |
claves= range(cant) #obtenemos todos los elementos desde 0 hasta cant en una lista | |
#for e in claves: | |
# claves[e]= claves[e]+1 | |
for i in range(n): #ciclo for desde 0 hasta el numero claves o keys | |
shuffle(claves) #revuelve los elementos presentes en la lista claves | |
f_nuevo.write(stringear(claves)) #se escribe cada mensaje convertido en string en el archivo | |
f_nuevo2.write(stringear(claves)) #se hace lo mismo para la copia | |
f_nuevo.close() #cierre del archivo | |
f_nuevo2.close() | |
return | |
def main(): | |
n= abs(int(raw_input("Cantidad de hojas en libreta: "))) #se pide el numero de claves a generar | |
cant= int(raw_input("Tamano de las claves en cada hoja: ")) #se pide el tamano de las claves | |
crearclaves(n, cant) #se crean las claves | |
main() |
El segundo, es el que pide el mensaje, lo encripta y lo envía.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def noespacios(clave): #Funcion que quita los espacios vacios en los keys | |
for t in range(len(clave)): #for que se repite desde 0 hasta el largo de la clave | |
if " "in clave: # si hay un " " en la clave | |
clave.remove(" ") # lo elimina | |
return clave | |
def encriptar(mensaje, cifras, alfabeto): #funcion que encripta el mensaje | |
resultado="" | |
f_nuevo= open("pruebas/libreta.txt", "r") #se abre el archivo en modo solo lectura | |
clavel= f_nuevo.readline() #se obtiene la primer linea del archivo en un string | |
f_nuevo.close() #cierre de archivo | |
limit=len(alfabeto) | |
alfabetolist = list(alfabeto) #alfabeto se hace una lista | |
clavelist=list(clavel) #se transforma la clave en una lista | |
clave = noespacios(clavelist) #se quitan los espacios de la clave obtenida del archivo | |
for j in range(cifras): #ciclo for empezando en 0 y terminando en el numero de cifras | |
pos= alfabetolist.index(mensaje[j]) #se almacena la posicion de cada letra del mensaje en el alfabeto | |
num=int(clave[j]) #se transforma cada numero de la clave en entero | |
if (pos+num)<=limit: | |
newpos = pos + num #se suma la posicion original mas el numero correspondiente en la clave | |
if (pos+num)>limit: | |
newpos = pos - num | |
resultado += str(alfabetolist[newpos]) #se obtiene el mensaje encriptado obteniendo cada letra de su nueva posicion | |
print resultado #se imprime el mensaje encriptado | |
return resultado #devuelve el resultado | |
def main(): | |
alfabeto = "abcdefghijklmnopqrstuvwxyz ," #caracteres aceptados en mensajes | |
resultado="" | |
mensaje= raw_input("Ingrese el mensaje: ") #se pide al usuario que ingrese el mensaje | |
cifras = int(len(mensaje)) #se obtiene el largo del mensaje | |
resultado =encriptar(mensaje, cifras, alfabeto) #se encripta el mensaje | |
#eliminarlinea() #se elimina la linea que contenia la clave ya utilizada | |
message = open("pruebas/mensajes.txt", "w") #se escribe el mensaje en el "sobre" | |
message.write(resultado) #se escribe el mensaje encriptado | |
message.close() #se cierra el archivo | |
main() |
El tercero, es el que obtiene el mensaje original, nuestro programa desencriptador.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def noespacios(clave): #funcion para quitar espacios | |
for t in range(len(clave)): #recorremos con un for | |
if " "in clave: #si, hay un espacio | |
clave.remove(" ") #lo removemos | |
return clave #devuelve clave | |
def desencriptar(resultado, cifras, alfabeto): #funcion inversa a la de encriptacion | |
mensaje="" | |
f_nuevo2 = open("pruebas/copialibreta.txt", "r") #se abre la copia de la libreta | |
clavel= f_nuevo2.readline() #se obtiene la clave a utilizar | |
f_nuevo2.close() #se cierra el archivo | |
limit=0 #se establece el limite como 0 | |
alfabetolist = list(alfabeto) #se transforma el string alfabeto en lista | |
clavelist=list(clavel) #se transforma la clave en una lista | |
clave=noespacios(clavelist) #se le quitan espacios a la clave | |
for j in range(cifras): #se recorre con un for desde 0 hasta el numero de cifras del mensaje | |
pos = alfabetolist.index(resultado[j]) #se obtiene la posicion de cada letra en la lista de alfabeto | |
num= int(clave[j]) #se almacenan los numeros de la clave | |
if (pos-num)>=limit: #checa si la resta no usa una posicion negativa | |
newpos = pos - num #se resta el valor de la posicion | |
if (pos-num)<limit: #se checa que sea mayor a 0 | |
newpos = pos + num #se suma la posicion original mas el numero correspondiente en la clave | |
mensaje += str(alfabetolist[newpos]) #se obtiene el mensaje original | |
return mensaje #devuelve mensaje | |
def main(): | |
alfabeto = "abcdefghijklmnopqrstuvwxyz ," #se establece el alfabeto | |
arch = open("pruebas/mensajes.txt", "r") #se abre el archivo en modo lectura | |
resultado= arch.readline() #se guarda en resultado el mensaje encriptado | |
cifras = int(len(resultado)) #se obtienen el largo del mensaje | |
mensaje =desencriptar(resultado, cifras, alfabeto) #funcion que descencripta el mensaje | |
#eliminarlinea() #elimina la linea que contiene la clave utilizada | |
print mensaje #se imprime el mensaje | |
main() |
En la implementación de éste algoritmo no se logró:
El desecho de claves o keys ya utilizados debido a un error de identación el cual no encontré explicación alguna.
Aquí muestro la función que tenía dentro de mi programa para eliminar la clave ya utilizada.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def eliminarlinea(): #funcion que elimina la primer linea utilizada esta desactivada | |
newkeys=list() #convertimos new keys en lista | |
cont=0 #inicializamos un contador | |
with open("pruebas/copialibreta.txt") as archivo: #abrimos el archivo de libretas | |
for line in archivo: #lo recorremos con un for | |
newkeys[cont]=line | |
if cont==0: | |
newkeys[cont]=line #sobrescribimos la primera línea con la segunda | |
cont+=1 #aumentamos el contador dentro del for | |
f2=open("pruebas/copialibreta.txt", "w") #abrimos archivo para escritura | |
for li in range(cont): #ciclo for desde 0 hasta el numero maximo de lineas | |
f2.write(newkeys[li]) #escribimos sobre el archivo | |
f2.close() #cerramos el archivo | |
return |
Después de correr varias veces el programa me dí cuenta que no siempre la encriptación y desencriptación arroja perfectos resultados, por lo tanto una solución sería que en lugar de que la clave tuviera valores desde 0, fuera desde 1, para que sí afecte a la hora de sumar o restar posiciones en los métodos de encriptación o su inversa.
El programa no se encuentra completamente validado, cuando existe la entrada de un número y se pide una cadena, es necesario volverlo a correr y viceversa cuando existe la entrada de una cadena y se pide un número, ésto se soluciona volviendo a pedir una entrada del usuario y no dejar avanzar al programa hasta que no se ingrese el tipo de dato que se necesita.
Aquí se muestra cómo se almacenan las claves en el texto:
Y aquí se muestra en qué orden se corren los programas y los resultados que arrojan.
[ramsmunoz@RamsMunoz Escritorio]$ python libreta.py
Cantidad de hojas en libreta: 10
Tamano de las claves en cada hoja: 12
[ramsmunoz@RamsMunoz Escritorio]$ python enviar.py
Ingrese el mensaje: hernandez
ifrqbodkq
[ramsmunoz@RamsMunoz Escritorio]$ python recibido.py
hernandeh
[ramsmunoz@RamsMunoz Escritorio]$ python enviar.py
Ingrese el mensaje: benito
cfnlup
[ramsmunoz@RamsMunoz Escritorio]$ python recibido.py
benito
Referencias:
Raúl González Duque "Python para todos" Fecha: -- URL: https://launchpadlibrarian.net/18980633/Python%20para%20todos.pdf
Autor: Banyut Título: "Python: Las listas" Fecha: sábado, 02 de agosto del 2008 URL: http://banyut.obolog.com/python-listas-115312
Autor: Javier Montero Título: "Python: Aprendiendo a leer" Fecha: 15/10/2012 URL: http://elclubdelautodidacta.es/wp/2012/10/python-aprendiendo-a-leer/