Skip to content

Instantly share code, notes, and snippets.

@iordic
Created July 21, 2019 17:45
Show Gist options
  • Save iordic/76508bdf29cd4625a9e5d015b32d6b4a to your computer and use it in GitHub Desktop.
Save iordic/76508bdf29cd4625a9e5d015b32d6b4a to your computer and use it in GitHub Desktop.
Cifrador muy simple basado en Vernam, para uso conceptual
"""Cifrador simple basado en cifrado de Vernam
hecho por @iordic
Este script está creado con fines educativos para tener nociones de cifrado simétrico
basándonos en el algoritmo más simple que se me ha ocurrido: el cifrado Vernam.
Se puede usar con cualquier fichero, ya que el fichero de entrada se lee la
información binaria del fichero. De todos modos te recomiendo que uses ficheros de
texto para comprobar los resultados.
No usar para cifrar información sensible, no es un programa creado con esa finalidad
ni es seguro, ni pretende ser un script que se use para un entorno real.
No se ofrece ninguna garantía asociada a este software, no me culpes de ningún daño
ocasionado ni me hagas reclamaciones de ningún tipo por el uso de este.
"""
import os
import sys
import getopt
FICHERO_CLAVE = "clave.bin"
EXTENSION_CIFRADO = ".enc"
def generar_clave(datos, fichero):
"""Genera una clave del mismo tamaño que el fichero a cifrar.
Se obtienen n bytes aleatorios y los devuelve. Además los guarda en un fichero
para poder descifrarlo en un futuro, ese fichero es la clave, sin ella no se puede
descifrar el fichero.
"""
n_bytes = len(datos)
clave = os.urandom(n_bytes)
escribir_fichero(fichero, clave)
return clave
def cifrar(clave, datos):
"""Aplica el cifrado de Vernam
Para cada byte de datos y byte de la clave en la misma posición se aplica la
operación XOR. Si no coninciden los tamaños se devuelve un error.
"""
n = len(datos)
if len(clave) != n:
print("Error: la longitud de clave y los datos no coincide.")
return
resultado = []
for i in range(0, n):
resultado.append(clave[i] ^ datos[i])
return resultado
def descifrar(clave, datos):
"""Recordemos que es cifrado simétrico, se cifra del mismo modo que descifra.
El uso de esta función le da mas legibilidad al código aunque sea inútil.
"""
return cifrar(clave, datos)
def cargar_fichero(fichero):
"""Cargar la información binaria del fichero en una variable
A veces da error de codificación UTF-8 porque no reconoce lo que lee
al tratarse de información binaria aleatoria. Para ello en internet
aconsejan leer los ficheros como "latin-1" pero no hace falta para
el uso que le vamos a dar, si quieres arreglarlo usa: f.read('latin-1').
"""
with open(fichero, 'rb') as f:
datos = bytearray(f.read())
f.close()
return datos
def escribir_fichero(fichero, datos):
with open(fichero, 'wb') as f:
f.write(bytearray(datos))
f.close()
return
def main(args):
try:
opts, args = getopt.getopt(args, "c:d:k:h", ["cifrar=", "descifrar=", "clave=", "help"])
except getopt.GetoptError as err:
usage()
fichero = None
fichero_clave = None
cifra = False
descifra = False
for opt, arg in opts:
if opt in ('-h', '--help'):
usage()
if opt in ('-c', '--cifrar'):
fichero = arg
cifra = True
if opt in ('-d', '--descifrar'):
fichero = arg
descifra = True
if opt in ('-k', '--clave'):
fichero_clave = arg
if fichero is None:
usage()
datos = cargar_fichero(fichero)
if fichero_clave is None and cifra:
fichero_clave = FICHERO_CLAVE
clave = generar_clave(datos, fichero_clave)
elif fichero_clave is None and descifra:
clave = cargar_fichero(FICHERO_CLAVE)
else:
clave = cargar_fichero(fichero_clave)
if cifra and not descifra:
resultado = cifrar(clave, datos)
fichero += EXTENSION_CIFRADO
escribir_fichero(fichero, resultado)
print("Se ha cifrado el fichero en {}".format(fichero))
elif not cifra and descifra:
resultado = descifrar(clave, datos)
fichero = fichero.strip(EXTENSION_CIFRADO)
escribir_fichero(fichero, resultado)
print("Se ha descifrado el fichero en {}".format(fichero))
else:
usage()
def usage():
print("\nCifrador simple basado en Vernam:")
print("uso: python3 cifrador.py [argumentos]\n")
print("Argumentos:")
print("-h, --help Imprime este mensaje.")
print("-c, --cifrar=<fichero> Genera una clave aleatoria del mismo tamaño que")
print(" el fichero a cifrar y lo guarda en \"{}\"."
.format(FICHERO_CLAVE))
print("-d, --descifrar=<fichero> Descifra el fichero con la clave (debe existir en")
print(" directorio el fichero \"{}\").".format(FICHERO_CLAVE))
print("-k, --clave=<fichero> Usa el fichero como clave, si no se proporciona una")
print(" se buscará el fichero \"{}\"".format(FICHERO_CLAVE))
quit()
if __name__ == '__main__':
if len(sys.argv) > 1:
main(sys.argv[1:])
else:
usage()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment