claves seguras

Pepe Aracil pepe en diselpro.com
Lun Mayo 22 10:04:21 CEST 2006


....Y aqui tienes la version que pasa de un string MD5 a letras y números.


import md5
m = md5.new()
m.update("C/Rue del 13 percebe")
m.update("Viva Zapataaaa!!")
m.update("1234")
md5_str = m.digest()
r = range(ord("0"),ord("9")+1)+range(ord("A"),ord("Z")+1)+range(ord("a"),ord("z")+1)
l = len(r)
output=""
for c in md5_str:
     index = ord(c) % l
     output += chr(r[index])

print output


Tny escribió:
> Aquí va el script que me anda jodiendo con las dichosos caracteres 
> 'extraños'
> 
> Funciona como un comando: se le puede ejecutar pasándole los parámetros 
> correspondientes,
> como una consola: si ejecuta sin parámetros.
> y claro está, se puede importar para emplear algunas de sus funciones en 
> otros programas.
> 
> El programa se encarga de generar una clave segura a partir de tres 
> cadenas de texto y un número:
> una inspirada en el sitio, otra inspirada en el usuario, y una clave 
> sencilla de recordar, que uno puede emplear para todos los sitios y 
> usuarios, como número puede emplearse el 1, los muy paranoicos que 
> pongan un número más grande...
> 
> La clave generada no hace falta memorizarla ni apuntarla ni nada raro, 
> sólo es necesario tener el programa que la genero, y recordar los datos 
> con la que fue generada.
> 
> A partir de la clave segura generada es imposible sacar alguno de los 4s 
> datos, incluso conociendo los otros 3 y teniendo el programa que la 
> generó (salvo mediante fuerza brutisima), por lo que incluso aunque una 
> de las claves seguras fuese interceptada, (con un man in the middle, o 
> con un sitio fraudulento, por ejemplo) las otras claves seguras 
> seguirían siéndolo.
> 
> Por último para poder compartir el programa sin que suponga un peligro 
> para la seguridad de las claves que hayamos generado, éste incorpora una 
> función que crea una copia incompatible, de modo que la clave generada 
> con los mimos datos por el programa original y por la copia 
> incompatible, son diferentes.
> 
> Ahí lo dejo para que lo podáis mirar, emplear, mejorar o lo que os de la 
> gana.
> 
> No seais muy críticos que es la primera cosa semi seria que hago en python.
> 
> Salud.
> 
> 
> ------------------------------------------------------------------------
> 
> # -*- coding: iso-8859-15 -*-
> #!/usr/bin/env python
> #algoritmo para la clave segura
> 
> import sys
> import random
> #Random sólo se emplea para generar la copia no compatible
> 
> 
> def caracteres():
>     "Devuelve una lista con los caracteres."
>     "el orden de esta lista es lo que incompatibiliza unas copias de otras"
>     return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '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', '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']
> 
> 
> 
> #Esta función puede ser sustituida por cualquier otra que genere un número a partir de una cadena de texto
> #Al sustir esta función se obtiene una versión personal incompatible con el resto de versiones
> #Es imprescindible que siempre devuelve el mismo número para la misma cadena de texto
> #Es recomendable que devuelva números grandes
> #No es necesario que sea biyectiva, es decir un mismo número puede ser generado por cadenas diferentes
> #Se recomienda que sea una función rápida
> def md(texto):
>     "Transforma una cadena de texto en un número."
>     r=len(texto)
>     for i in texto:
>         x=ord(i)
>         r=(r*(x-1))^2-1
>     return r
> 
> #Esta función puede ser modificada
> def reordenar(caracteres, orden):
>     "altera el orden de los caracteres según un número"
>     i=len(caracteres)           
>     nuevos=[]
>     while i!=0:
>         x=orden % i                     #se puede modificar siempre que se mantenga x entre 0 e i-1
>         nuevos.append(caracteres[x])    
>         del caracteres[x]               #lo eliminamos de la lista de caracteres
>         orden=orden/(i+1)               #se puede modificar, no se recomienda emplear el producto pues fácilmente hace que ord%i=0  
>         i=i-1
>     return nuevos
> 
> #Su puede hacer de modo más eficiente, creo que hay una función para hacer esto mismo
> def intercambiar(c1,c2,texto):
>     "intercambia los caracteres de texto, de la lista de caracteres c1 a la lista c2)"
>     txt=""
>     for i in texto:       
>         txt=txt + c2[c1.index(i)]
>     return txt
> 
> 
> 
> #según el valor que de md() a sitio,usuario y clave se reordenan los caracteres
> #sitio usuario y clave se modifican según estos caracteres reordenados
> #se dan tantas vueltas como se indique (con una vuelta debería bastar, pero no esta de más hacer unas cuantas)
> #para cada letra de la clave segura se repite todo el proceso con los nuevos sitio, usuario, clave y caracteres
> def generar(sitio, usuario, clave, vueltas):
>     "genera una clave segura"
>     c=caracteres()   
>     sitio=limitar(sitio,c) 
>     usuario=limitar(usuario,c)
>     clave=limitar(clave,c)
>     txt=""
>     for x in range(0,len(clave)):
>         for i in range(0,vueltas):
>             c=reordenar(c,md(sitio+usuario))
>             sitio=intercambiar(caracteres(),c,sitio)
>             usuario=intercambiar(c,caracteres(),sitio)
>         for i in range(0,vueltas):              
>             c=reordenar(c,md(clave))            
>             clave=intercambiar(caracteres(),c,clave)
>         txt=txt+c[caracteres().index(clave[x])]
>     print txt
>    
> 
> def limitar(texto,caracteres):
>     "Elimina los caracteres que no aparecen en la lista."
>     txt=""
>     for i in texto:
>         if caracteres.count(i)==1:
>             txt=txt+i
>     return txt
>     
> 
>     
> #consola
> # A partir de aquí se encuentra el código para la consola, el modo automático y el modo de parámetros
> # Se supone que se puede hacer más rápido y fácil empleando expresiones regulares, un módulo que incluye python para estás cosas, pero como no lo domino lo suficiente lo he hecho a pelo
> # Para automatismos importar y llamar directamente a las funciones.
> # La consola y el modo comando estan pensado para ser eficientes en tiempos humanos.
> def main():
>     "Modo consola."
>     valores=nuevosvalores()
>     print sys.argv[0]
>     print "Tny 2006"
>     print "Claves Seguras. licencia totalmente libre"
>     print "Carácteres válidos:"
>     ca=caracteres()
>     ca.sort()
>     for c in ca:
>         print c,
>     print""
>     print""
>     while(True):
>         comando=raw_input("-> ")
>         if comando=="salir":
>             break
>         procesar(comando,valores)
> 
> def nuevosvalores():
>     "Devuelve valores nulos"
>     return ["","","",0]
> 
> def procesar(comando,valores):
>     "Procesa los comandos."
>     c1=palabrasiguiente(comando,"")
>     c2=comando[len(c1):]
>     if c1=="":
>         automatico()
>     elif c1=="sitio":
>         if c2!="":
>             valores[0]=c2.strip()
>         print "   "+valores[0]
>     elif c1=="usuario":
>         if c2!="":
>             valores[1]=c2.strip()
>         print "   "+valores[1]
>     elif c1=="clave":
>         if c2!="":
>             valores[2]=c2.strip()
>         print "   "+valores[2]
>     elif c1=="vueltas":
>         if c2!="":
>             if c2.strip().isdigit():
>                 valores[3]=int(c2)
>         print valores[3]      
>     elif c1=="generar":
>         pregenerar(c2,valores)
>     elif c1=="copia":
>         reproducir(c2)
>     elif c1=="resetear":
>         valores[0:]=nuevosvalores()
>     elif c1=="carácteres":
>         print caracteres()
>     else:
>         ayuda(c1,c2)
> 
> def pregenerar(c2,valores):
>     "El comando generar, con todas sus variantes"
>     c2=" "+c2+" "
>     sn=c2.lower().find(" /sitio ")
>     un=c2.lower().find(" /usuario ")
>     cn=c2.lower().find(" /clave ")
>     vn=c2.lower().find(" /vueltas ")
>     sitio=""
>     usuario=""
>     clave=""
>     vueltas=0
>     if sn==-1 and un==-1 and cn==-1 and vn==-1:
>         sitio=palabrasiguiente(c2,"")
>         if sitio!="":
>             usuario=palabrasiguiente(c2,sitio)
>         if usuario!="":
>             clave=palabrasiguiente(c2,usuario)
>         if clave!="":
>             vueltas=palabrasiguiente(c2,clave)
>             if vueltas.isdigit():
>                 vueltas=int(vueltas)
>             else:
>                 vueltas=0
>     else:
>         sitio=palabrasiguiente(c2," /sitio ")
>         usuario=palabrasiguiente(c2,"usuario")
>         clave=palabrasiguiente(c2,"clave")
>         vueltas=palabrasiguiente(c2," /vueltas ")
>         if vueltas.isdigit():
>             vueltas=int(vueltas)
>         else:
>             vueltas=0  
>     if sitio=="":
>         sitio==valores[0]
>     if usuario=="":
>         usuario=valores[1]
>     if clave=="":
>         clave=valores[2]
>     if vueltas==0:
>         vueltas=valores[3]
>     c=caracteres()
>     sitio=limitar(sitio,c)
>     usuario=limitar(usuario,c)
>     clave=limitar(clave,c)
>     while sitio=="":
>         sitio=limitar(raw_input("?-> sitio "),c)
>     while usuario=="":
>         usuario=limitar(raw_input("?-> usuario "),c)
>     while clave=="":
>         clave=limitar(raw_input("?-> clave "),c)
>     while (vueltas==0):
>         vueltas=raw_input("?-> vueltas ")
>         if vueltas.isdigit():
>             vueltas=int(vueltas)
>         else:
>             vueltas=0        
>     generar(sitio,usuario,clave,vueltas)
> 
> def palabrasiguiente(texto,palabra):
>     "Devuelve la palabra siguiente a una dada, o '' si no hay tal palabra"
>     texto=texto+" "
>     i=texto.find(palabra)
>     if i==-1:
>         return ""
>     i+=len(palabra)
>     while texto[i]==" ":
>         i+=1
>         if i==len(texto):
>             return ""
>     return texto[i:texto.find(" ",i)]
>     
>     
> def automatico():
>     "El modo automático equivale al comando generar sin parámetros ni valores guardados"
>     pregenerar("",nuevosvalores())
> 
> def ayuda(c1,c2):
>     "Una pequeña ayuda"
>     print "            Ayuda:"
>     print ""
>     print "     Establecer o recuperar valores"
>     print "sitio [texto]    -->  devuelve o establece sitio"
>     print "usuario [texto]  -->  devuelve o establece usuario"
>     print "clave [texto]    -->  devuelve o establece clave"
>     print "vueltas [numero] -->  devuelve o establece vueltas"
>     print ""
>     print "     Comandos"
>     print "generar [/variable valor][/variable valor]...  --> genera clave segura"
>     print "generar [sitio usuario clave vueltas]          --> genera clave segura"
>     print "preguntan por los valores no establecidos ni pasados como argumentos"
>     print ""
>     print "resetear     --> resetea los valores establecidos"
>     print "copia        --> genera una copia con diferente secuenciación"
>     print "salir        --> sale"
>     print "carácteres   --> secuenciación de esta copia"
>     print ""
>     print "Tny 2006 se permite la copia, distribución, traducción y modificación del archivo, código y algoritmos contenidos en él"
>     print "http://a.porrua.googlepages.com/"
>     print ""
>     print "intro para modo automatico"
> 
>     
> 
> #copia unica
> #Automatiza el proceso de generar copias personalizadas
> #Lo que hace es modificar el orden de los caracteres.
> #para que funcione, los primeros corchetes del archivo deben ser los de la función caracteres()
> #si por algún motivo hay que introducir algún corchete antés, se debería también modificar esta función para que sigua funcionando
> def reproducir(c2):
>     "genera una copia incompatible"
>     o=open(sys.argv[0],'r')     
>     original=o.read()
>     o.close()
>     a=original.index("[")+1     
>     z=original.index("]")        
>     final=original[:a]          
>     c=caracteres()              
>     random.shuffle(c)           
>     for i in range(0,len(c)-1):     
>         final=final+"'"+c[i]+"', "   
>     final=final+"'"+c[i+1]+"'"  
>     final=final + original[z:]  
>     o=open(sys.argv[0]+".copia.py","w")
>     o.write(final)
>     o.close()                   
> 
> #el modo comando o consola, según si se le pasan parámetros o no
> if __name__ == "__main__":
>     if len(sys.argv)>1:
>         try:
>             generar(sys.argv[1],sys.argv[2],sys.argv[3],int(sys.argv[4]))
>         except:
>             print "Error: Parametros incorrectos"
>             print ""
>             print "Modo comando:"
>             print sys.argv[0],"sitio usuario clave vueltas"
>             print ""
>             print "Modo consola:"
>             print sys.argv[0]
>         sys.exit(0)
>     main()
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Python-es mailing list
> Python-es en aditel.org
> http://listas.aditel.org/listinfo/python-es




Más información sobre la lista de distribución Python-es