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