Created
July 21, 2019 17:45
-
-
Save iordic/76508bdf29cd4625a9e5d015b32d6b4a to your computer and use it in GitHub Desktop.
Cifrador muy simple basado en Vernam, para uso conceptual
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
"""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