Archivos para ‘python’

2 octubre 2011

Python: Cifrado por sustitución simple monoalfabética ó Cifrado César

por auraham

El cifrado de César es un tipo de cifrado simple que se basa en el uso de un sólo alfabeto, por lo regular, ordenado. Se emplea una llave para realizar la sustitución. Por ejemplo, si la llave vale 1 y el mensaje es ‘A’, entonces, el mensaje cifrado será ‘B’, y así sucesivamente.

A diferencia de otros algoritmos, como el de Vigenére, se emplea una sola llave para cifrar todo el mensaje.

Para saber más sobre el método de César, este es un libro excelente Cryptography Decrypted

Implementación
Vamos a crear cuatro funciones para el algoritmo:

  • get_alphabet()
  • get_index()
  • crypt()
  • decrypt()

La función get_alphabet() devolverá una lista con todos los elementos del alfabeto y otros, como números lo que se desee agregar.

def get_alphabet():
	"""Devuelve una lista con mayusculas, minuscula, numeros y un espacio"""
	alphabet = []

	# mayusculas:65-90
	for i in range(65,91):
		alphabet.append(chr(i))

	# minusculas:97-122
	for i in range(97,123):
		alphabet.append(chr(i))

	# numeros
	for i in range(10):
		alphabet.append(str(i))

	# espacio
	#alphabet.append(" ")

	return alphabet

La función get_index() se usa para validar la llave. En nuestro caso el alfabeto consta de 62 elementos (length), por lo que nuestro índice máximo (max_index) dentro de la lista es de 61 y el índice mínimo (min_index) es 0. Para que un índice sea válido, debe estar en este rango.

En teoría, el algoritmo sólo sirve para un cierto valor de llaves. En un alfabeto de 25 elementos, habrá un máximo de 25 llaves distintas, ya que después se repetirán los valores, es decir, si la llave vale 26, producirá el mismo cifrado que la llave con valor de 1.

def get_index(index = 0, length = 0):
	"""Devuelve un indice valido dentro de un rango, evitando desbordamiento"""
	
	min_index = 0			# indice minimo
	max_index = length - 1		# indice maximo = longitud - 1

	while True:
		
		# index excede el limite superior
		if index > max_index:
			index -= length

		# index es menor al limite inferior
		elif index < min_index:
			index += length
			
		# index es valido
		else:
			break

	return index

La función crypt() recibe dos parámetros, el mensaje a cifrar y la llave. Inicia con la declaración de variables. Enseguida, recorre cada letra del mensaje. Si la letra se encuentra dentro de alphabet, se devolverá su índice dentro de la lista. Sino es así, letter no existe dentro de alphabet, provocando una excepción y continuando con la siguiente letra.

La sustitución se realiza de esta forma. Se incrementa index el valor de key y se guarda en move. Si move no fuese un índice válido se evaluará con get_index(). Por ejemplo, si move vale 63 excede el valor de max_index, por lo que se devolverá 1.

Por último se agrega el elemento de alphabet en la posición move al crypted.

def crypt(message = "", key = 0):
	"""Cifra un mensaje usando sustitucion"""
	
	crypted = ""			# mensaje cifrado

	alphabet = get_alphabet()	# alfabeto
	length = len(alphabet) 		# longitud del alfabeto
	index = 0			# indice de la letra en el alfabeto

	for letter in message:

		# se obtiene el indice de letter dentro de alphabet, si existe
		try:		
			index = alphabet.index(letter)	# indice dentro del alfabeto
		except:
			print "No existe %s en el alfabeto" % (letter,)
			continue


		# se obtiene la nueva posicion, evitando desbordamiento
		move = index + key		# nueva posicion
		move = get_index(move,length)	
	
		# debug
		if debug:
			print "move %d"%(move,)

		crypted += alphabet[move]	# agrega la letra al mensaje cifrado

		#debug
		if debug:
			print "%s = %s" % (alphabet[index],alphabet[move])

	return crypted

La función decrypt() es similar a la anterior, pero en lugar de incrementar el valor de key, se decrementa.

def decrypt(message = "", key = 0):
	"""Decifra un mensaje usando sustitucion"""
	
	decrypted = ""			# mensaje decifrado

	alphabet = get_alphabet()	# alfabeto
	length = len(alphabet)		# longitud del alfabeto
	index = 0

	for letter in message:

		try:
			index = alphabet.index(letter)	# indice dentro del alfabeto
		except:
			print "No existe %s en el alfabeto" % (letter,)
			continue		

		move = index - key		# nueva posicion
		move = get_index(move,length)

		# debug
		if debug:
			print "move %d"%(move,)


		decrypted += alphabet[move]	# agrega al mensaje decifrado
		
		#debug
		if debug:
			print "%s = %s" % (alphabet[index],alphabet[move])

	return decrypted

Por último, este es todo el código. Al final, se manda llamar la función crypted() y se imprime el mensaje cifrado.

#!/usr/bin/python

debug = False

# Cifrado por sustitucion

def get_alphabet():
	"""Devuelve una lista con mayusculas, minuscula, numeros y un espacio"""
	alphabet = []

	# mayusculas:65-90
	for i in range(65,91):
		alphabet.append(chr(i))

	# minusculas:97-122
	for i in range(97,123):
		alphabet.append(chr(i))

	# numeros
	for i in range(10):
		alphabet.append(str(i))

	# espacio
	#alphabet.append(" ")

	return alphabet
	

def get_index(index = 0, length = 0):
	"""Devuelve un indice valido dentro de un rango, evitando desbordamiento"""
	
	min_index = 0			# indice minimo
	max_index = length - 1		# indice maximo = longitud - 1

	while True:
		
		# index excede el limite superior
		if index > max_index:
			index -= length

		# index es menor al limite inferior
		elif index < min_index:
			index += length
			
		# index es valido
		else:
			break

	return index	




def crypt(message = "", key = 0):
	"""Cifra un mensaje usando sustitucion"""
	
	crypted = ""			# mensaje cifrado

	alphabet = get_alphabet()	# alfabeto
	length = len(alphabet) 		# longitud del alfabeto
	index = 0			# indice de la letra en el alfabeto

	for letter in message:

		# se obtiene el indice de letter dentro de alphabet, si existe
		try:		
			index = alphabet.index(letter)	# indice dentro del alfabeto
		except:
			print "No existe %s en el alfabeto" % (letter,)
			continue


		# se obtiene la nueva posicion, evitando desbordamiento
		move = index + key		# nueva posicion
		move = get_index(move,length)	
	
		# debug
		if debug:
			print "move %d"%(move,)

		crypted += alphabet[move]	# agrega la letra al mensaje cifrado

		#debug
		if debug:
			print "%s = %s" % (alphabet[index],alphabet[move])

	return crypted


def decrypt(message = "", key = 0):
	"""Decifra un mensaje usando sustitucion"""
	
	decrypted = ""			# mensaje decifrado

	alphabet = get_alphabet()	# alfabeto
	length = len(alphabet)		# longitud del alfabeto
	index = 0

	for letter in message:

		try:
			index = alphabet.index(letter)	# indice dentro del alfabeto
		except:
			print "No existe %s en el alfabeto" % (letter,)
			continue		

		move = index - key		# nueva posicion
		move = get_index(move,length)

		# debug
		if debug:
			print "move %d"%(move,)


		decrypted += alphabet[move]	# agrega al mensaje decifrado
		
		#debug
		if debug:
			print "%s = %s" % (alphabet[index],alphabet[move])

	return decrypted


# inicio
print "Cifrado por sustitucion"
print "Mensaje:"
message = raw_input()

print "Llave:"
key = int(raw_input())

# mensaje cifrado
crypted = crypt(message,key)
print crypted
	

Ejemplos

# key = 1
auraham@machine:~/projects/python$ python -i cifrar_sustitucion.py 
Cifrado por sustitucion
Mensaje:
hola
Llave:
1
ipmb

# key = 62, tiene el mismo efecto de key = 0, es decir, no cifra
auraham@machine:~/projects/python$ python -i cifrar_sustitucion.py 
Cifrado por sustitucion
Mensaje:
hola
Llave:
62
hola

# key = 63, tiene el mismo efecto que key = 1
auraham@machine:~/projects/python$ python -i cifrar_sustitucion.py 
Cifrado por sustitucion
Mensaje:
hola
Llave:
63
ipmb

30 septiembre 2011

Python: Mutables

por auraham

#!/usr/bin/python

# Mutables e inmutables (personal)
# Las listas y los diccionarios son mutables porque es posible modificar sus elementos
# aun despues de haber sido definidos

# definicion
lista = [1,2,3]
print lista

# modificacion
lista[0] = "modificado"
print lista

# definicion
dic = {"uno":1, "dos":2}
print dic

# modificacion
dic["uno"] = "modificado"
print dic

# Las tuplas en cambio, son inmutables, ya que no es posible modificar sus elementos
# despues de hacer sido definidos

# definicion
tupla = (1,2,3)
print tupla

# no se podra modificar y mostrara este error
# TypeError: 'tuple' object does not support item assigment
tupla[0] = "no se puede modificar, mostrando un error"

Fuente:
Python para todos

30 septiembre 2011

Python: Funciones

por auraham

#!/usr/bin/python 

# Funciones
# Una funcion es un fragmento de codigo con un nombre asociado
# que realiza una serie de tareas y devuelve un valor.
# 
# Un procedimiento es similar a la funcion, pero no devuelve valor.
# 
# En Python no existen los procedimientos, ya que cuando no se especifica
# un valor de retorno, se devuelve None
# 
# def function_name(params):
#	"""docstring"""
#	...
# 
# Para mostrar la ayuda de la funcion, el docstring, usa
# help(function_name)
# 
# Para salir usa q
# 


def mi_funcion(param1, param2):
	"""imprime dos valores"""
	print param1
	print param2


# Mostrar ayuda
help(mi_funcion)

# Llamada a la funcion
# 1
# 2
print "llamada a la funcion"
mi_funcion(1,2)

# Para no cerrar el interprete al terminar el programa, usa
#	python -i script.py
# 
#
# Valores por defecto
# Cuando se manda llamar una funcion se debe pasar el numero 
# de parametros de acuerdo a la declaracion de la funcion, sino se mostrara
# un error. Por ejemplo, al pasar solo un parametro, se mostrara
# TypeError: mi_funcion() takes exactly 2 arguments (1 given)
#
# Se puede evitar eso colocando valores por defecto en los parametros
def otra_funcion(param1 = "param1", param2 = "param2"):
	print param1
	print param2

# Llama a la funcion con solo un parametro
# un parametro
# param2
print "parametros por defecto"
otra_funcion("un parametro")


# Cambio de orden
# Es posible cambiar el orden de los valores en los parametros
# indicando el nombre del parametro al momento de llamar a la funcion
# 
# param 2
# param 1
print "cambio de orden"
otra_funcion(param2 = "param 1", param1 = "param 2")


# Multiples parametros
# Se pueden pasar un numero variable de argumentos antecediendo un *
# al parametro en la definicion
# Se crea una tupla llamada parametros en la funcion indefinidos
def funcion_lista(*parametros):
	for item in parametros:
		print item

# Llamada a la funcion
# 1
# 2
# 3
# 4
print "lista de parametros"
funcion_lista(1,2,3,4)

# Tambien es posible usar ** antes de la definicion del parametro
# creando un diccionario. Al momento de llamar a la funcion se deben
# pasar los valores en pares, (key, value) para cada elemento del diccionario
# 
# Para mostrar los valores (y no las llaves) del diccionario se usa la el metodo items()
def funcion_diccionario(**params):
	for item in params.items():
		print item

# Llamada a la funcion
print "diccionario de parametros"
funcion_diccionario(param1 = "param 1", param2 = "param 2", param3 = "param 3")

Fuente
Python para todos

30 septiembre 2011

Python: Condicional

por auraham

#!/usr/bin/python

# condicional

cadena = "arenita"

if cadena == "arenita":
	print("es una ardilla")	# es una ardilla
elif cadena == "bob":
	print("es una esponja")
else:
	print("mmmm no se que es :p")

# A if C else B
# se evalua C y devuelve 
# A si es correcto
# B si no es correcto
numero = 10
par = True if (numero %2 == 0) else False

print(numero)		# True

26 agosto 2011

Python: Diccionarios

por auraham

#!/usr/bin/python

# Diccionarios
# O tambien matrices asociativas, contienen pares de la forma {key:value}

d = {"bob":"esponja","patricio":"estrella","calamardo":"tentaculos"}
print(d)		# {'bob':'esponja','patricio':'estrella','calamardo':'tentaculos'}

# Donde key es cualquier valor inmutable, como numeros, cadenas, boleanos, tuplas
# pero no listas o diccionarios, los cuales son mutables.
#
# NOTA PERSONAL: Las tuplas no son mutables porque una vez definidas no se pueden modificar 
# sus elementos. Las listas y diccionarios son mutables porque se pueden modificar sus elementos
# aun despues de ser definidos. Vease mutables.py
#
# Esto es asi porque los diccionarios se implementan como tablas hash
# y cuando se inserta un nuevo par key:value se calcula el hash de key para
# despues encontrarlo rapidamente.
# Si se cambiara el valor de key, tambien cambiaria el hash, por lo que no se podria
# encontrar el par

# para acceder a los elementos no se usa un indice (porque no estan ordenados)
# sino que se usa el valor de key dentro del operador []
print(d["bob"])		# esponja

# al igual que las listas, (pero no las tuplas, pag 26)
# se pueden editar con el operador []
d["bob"] = False
print(d["bob"])		# False

# pero no se puede usar slicing, entre otras cosas, debido a que
# los diccionarios no son secuencias, sino mappings (mapeados o asociaciones)



# Recorrido de un diccionario
# Se puede usar el ciclo for in de varias formas, dependiendo de lo que se
# se desee usar, la llave o el valor 
dic = {"key_1":1,"key_2":2,"key_3":3}

# Mostrar solo llaves
# Se recorre de manera normal
print "Mostrar solo llaves"
for item in dic:
	print item		# key_1

# Mostrar el par de llave y valor
# Para recuperar el valor, se usa el metodo items(), propio 
# de los diccionarios, el cual devuelve una tupla por cada par 
print "Mostra llaves y valores"
for item in dic.items():
	print item		# ('key_1',1)
	print type(item)	# <type 'tuple'>
	print "key:" + item[0] + ",value:" + str(item[1])

26 agosto 2011

Python: Tuplas

por auraham

#!/usr/bin/python

# tuplas
# algunas de las operaciones de las listas se pueden aplicar a las tuplas

# las tuplas se construyen dentro de parantesis, separando los elementos
# por comas
tupla = (1,2,3)
print(tupla)		# (1,2,3)

# aunque en realidad, el constructor es la coma
tupla = 1,2,3
print(tupla)		# (1,2,3)

# ademas, se debe agregar una coma al final del elemento
# en el caso de una tupla con un solo elemento
# para diferenciar de un elemento entre parentesis
tupla = (1,)
print(tupla)		# (1,)
print type(tupla)	# <type 'tuple'>

no_tupla = (1)
print(no_tupla)		# 1
print type(no_tupla)	# <type 'int'>

# al igual que las listas, se puede usar el operador []
# para acceder a los elementos de la tupla
# debido a que ambos son de un tipo de objetos llamado secuencias
# al igual que las cadenas de texto
tupla = (1,2,3,4,5)
print(tupla[2])		# 3

# tambien podemos usar slicing
tupla = (0,1,2,3,(4,5,6))
print(tupla)		# (0,1,2,3,(4,5,6))
print(tupla[::2])	# (0:2:(4,5,6))

# ademas, son inmutables, es decir, sus valores no se pueden
# modificar una vez creada y tienen tamano fijo
tupla[0] = False
print(tupla)		# TypeError: 'tuple' object does not support item assigment

26 agosto 2011

Python: Listas

por auraham

#!/usr/bin/python

# listas
# es una coleccion ordenada similar al array
# puede contener numeros, cadenas, boleanos, listas...

lista = [1,2,3,"cadena",False,[10,20]]

# para acceder a los elementos
# usa indices
print(lista[0])		# 1

# para acceder a un elemento de una lista
# dentro de otra lista, usa dos indices
doble = [1,2,[3,4]]
print(doble[2][1])	# 4	
ndice fin - 1

# el operador [] de python tambien permite el uso de
# indices negativos
# contando desde el final de la lista
secuencia = [0,1,2,3,4,5,6,7,8,9]
print(secuencia[-10])	# 0	primer elemento de la lista (-length)
print(secuencia[-9])	# 1	segundo elemento de la lista
print(secuencia[-1])	# 9	ultimo elemento de la lista (-1)



# slicing o particionado
# permite obtener porciones de la lista con el formato
# [inicio:fin:salto]
# donde
# inicio: indice inicial
# fin: indice fin - 1
# salto: indica cada cuantas posiciones tomar un elemento
print("slicing")		# slicing
print(secuencia[0:3])		# [0,1,2]
print(secuencia[1:3])		# [1,2]
print(secuencia[0:10])		# [0,1,2,3,4,5,6,7,8,9]
print(secuencia[0:10:1])	# [0,1,2,3,4,5,6,7,8,9]
print(secuencia[0:10:2])	# [0,2,4,6,8]
print(secuencia[0:10:3])	# [0,3,6,9]
print(secuencia[0:10:4])	# [0,4,8]

# se puede omitir el inicio y fin
# tomando el primer y ultimo elemento, respectivamente
print(secuencia[::1])		# [0,1,2,3,4,5,6,7,8,9]

# tambien se puede modificar la lista por slicing
lista = [0,1,"c","d"]		
print(lista)			# [0,1,c,d]

lista[0:2] = ["a","b"]
print(lista)			# [a,b,c,d]

# incluso se puede cambiar el tamano de la lista
lista = [0,1,2,"b","c"]
lista[0:3] = ["a","b"]
print(lista)			# [a,b,b,c]


# note la diferencia entre modificar una lista
# por indice y por slicing
print("indice & slicing")	# indice & slicing

# por slicing agrega la lista ["a"] como si fuera solo "a"
print("por slicing")		# por slicing
lista = [0,1,2,3,4,5]
lista[0:3] = ["a"]
print(lista)			# [a,3,4,5]

# por indice agrega la lista ["a"] y se toma como una lista dentro de otra lista
print("por indice")		# por indice
lista = [0,1,2,3,4,5]
lista[0] = ["a"]
print(lista)			# [[a],1,2,3,4,5]


26 agosto 2011

Python: Tipos

por auraham

#!/usr/bin/python

# cadena
cadena = "hola"
print type(cadena)	#<type 'str'>

# entero
entero = 23
print type(entero)	#<type 'int'>

# entero largo (long)
largo = 23L
print type(largo)	#<type 'long'>

# octal
octal = 010
print type(octal)	#<type 'int'>

#hexadecimal
hex = 0x17
print type(hex)		#<type 'int'>

#real (float)
real = 0.0001		#<type 'float'>
print type(real)

real = 0.1e-3
print type(real)	#<type 'float'>


# complejo (complex)
complejo = 2.1 + 3.4j
print type(complejo)	#<type 'complex'>


# boleano (bool)	#<type 'bool'>
boleano = True
print type(boleano)

Seguir

Get every new post delivered to your Inbox.