¿Python tiene una forma simple e incorporada de codificar / decodificar cadenas usando una contraseña?
Algo como esto:
>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
Entonces, la cadena "John Doe" se cifra como 'sjkl28cn2sx0'. Para obtener la cadena original, "desbloquearía" esa cadena con la clave 'mypass', que es una contraseña en mi código fuente. Me gustaría que esta fuera la forma en que puedo cifrar / descifrar un documento de Word con una contraseña.
Me gustaría usar estas cadenas encriptadas como parámetros de URL. Mi objetivo es la ofuscación, no una seguridad sólida; no se codifica nada crítico para la misión. Me doy cuenta de que podría usar una tabla de base de datos para almacenar claves y valores, pero estoy tratando de ser minimalista.
python
encryption
passwords
RexE
fuente
fuente
Respuestas:
Suponiendo que solo está buscando una ofuscación simple que oscurezca las cosas para el observador muy casual, y no está buscando usar bibliotecas de terceros. Recomendaría algo como el cifrado de Vigenere. Es uno de los cifrados antiguos simples más fuertes.
Cifrado de Vigenère
Es rápido y fácil de implementar. Algo como:
Decodificar es prácticamente lo mismo, excepto que resta la clave.
Es mucho más difícil de romper si las cadenas que está codificando son cortas y / o si es difícil adivinar la longitud de la frase de contraseña utilizada.
Si está buscando algo criptográfico, PyCrypto es probablemente su mejor opción, aunque las respuestas anteriores pasan por alto algunos detalles: el modo ECB en PyCrypto requiere que su mensaje tenga una longitud múltiple de 16 caracteres. Entonces, debes rellenar. Además, si desea utilizarlos como parámetros de URL, utilice
base64.urlsafe_b64_encode()
, en lugar del estándar. Esto reemplaza algunos de los caracteres en el alfabeto base64 con caracteres seguros para URL (como sugiere su nombre).Sin embargo, debe estar ABSOLUTAMENTE seguro de que esta capa muy delgada de ofuscación es suficiente para sus necesidades antes de usar esto. El artículo de Wikipedia al que me vinculé proporciona instrucciones detalladas para descifrar el cifrado, por lo que cualquier persona con una cantidad moderada de determinación podría descifrarlo fácilmente.
fuente
'str' object cannot be interpreted as an integer
Como declaras explícitamente que quieres oscuridad y no seguridad, evitaremos reprenderte por la debilidad de lo que sugieres :)
Entonces, usando PyCrypto:
Si alguien se apodera de su base de datos y su base de código, podrá decodificar los datos cifrados. ¡Mantén tu
secret_key
caja fuerte!fuente
encrypt
función en particular tiene estado dlitz.net/software/pycrypto/api/current/… así que no debes intentar reutilizarla.Python no tiene esquemas de cifrado integrados, no. También debe tomarse en serio el almacenamiento de datos cifrados; esquemas de cifrado triviales que un desarrollador entiende que son inseguros y un esquema de juguete bien puede ser confundido con un esquema seguro por un desarrollador menos experimentado. Si encripta, encripte correctamente.
Sin embargo, no necesita hacer mucho trabajo para implementar un esquema de cifrado adecuado. En primer lugar, no reinvente la rueda de criptografía , use una biblioteca de criptografía confiable para manejar esto por usted. Para Python 3, esa biblioteca confiable es
cryptography
.También recomiendo que el cifrado y el descifrado se apliquen a los bytes ; codificar mensajes de texto en bytes primero;
stringvalue.encode()
codifica a UTF8, fácilmente revertido nuevamente usandobytesvalue.decode()
.Por último, pero no menos importante, a la hora de cifrar y descifrar, hablamos de claves , no de contraseñas. Una clave no debe ser memorable por humanos, es algo que usted almacena en un lugar secreto pero legible por máquina, mientras que una contraseña a menudo puede ser legible y memorizada por humanos. Usted puede obtener una clave de una contraseña, con un poco de cuidado.
Pero para una aplicación web o un proceso que se ejecuta en un clúster sin atención humana para seguir ejecutándolo, debe usar una clave. Las contraseñas son para cuando solo un usuario final necesita acceder a la información específica. Incluso entonces, normalmente protege la aplicación con una contraseña y luego intercambia información cifrada mediante una clave, tal vez una adjunta a la cuenta de usuario.
Cifrado de clave simétrica
Fernet - AES CBC + HMAC, muy recomendable
La
cryptography
biblioteca incluye la receta de Fernet , una receta de mejores prácticas para usar la criptografía. Fernet es un estándar abierto , con implementaciones listas en una amplia gama de lenguajes de programación y empaqueta el cifrado AES CBC para usted con información de versión, una marca de tiempo y una firma HMAC para evitar la manipulación de mensajes.Fernet hace que sea muy fácil cifrar y descifrar mensajes y mantenerlo seguro. Es el método ideal para cifrar datos con un secreto.
Te recomiendo que lo uses
Fernet.generate_key()
para generar una clave segura. También puede usar una contraseña (siguiente sección), pero una clave secreta completa de 32 bytes (16 bytes para cifrar, más otros 16 para la firma) será más segura que la mayoría de las contraseñas que pueda imaginar.La clave que genera Fernet es un
bytes
objeto con URL y caracteres base64 seguros para el archivo, por lo que se puede imprimir:Para cifrar o descifrar mensajes, cree una
Fernet()
instancia con la clave dada y llame alFernet.encrypt()
oFernet.decrypt()
, tanto el mensaje de texto sin formato para cifrar como el token cifrado sonbytes
objetos.encrypt()
y lasdecrypt()
funciones se verían así:Manifestación:
Fernet con contraseña - clave derivada de contraseña, debilita un poco la seguridad
Puede utilizar una contraseña en lugar de una clave secreta, siempre que utilice un método de derivación de claves seguro . Luego, debe incluir la sal y el recuento de iteraciones HMAC en el mensaje, por lo que el valor cifrado ya no es compatible con Fernet sin separar primero sal, recuento y token de Fernet:
Manifestación:
La inclusión de la sal en la salida permite utilizar un valor de sal aleatorio, lo que a su vez garantiza que la salida cifrada sea totalmente aleatoria independientemente de la reutilización de la contraseña o la repetición de mensajes. La inclusión del recuento de iteraciones garantiza que pueda ajustar los aumentos del rendimiento de la CPU con el tiempo sin perder la capacidad de descifrar mensajes más antiguos.
Una contraseña sola puede ser tan segura como una clave aleatoria Fernet de 32 bytes, siempre que genere una contraseña aleatoria adecuada a partir de un grupo de tamaño similar. 32 bytes le dan 256 ^ 32 números de claves, por lo que si usa un alfabeto de 74 caracteres (26 superiores, 26 inferiores, 10 dígitos y 12 símbolos posibles), entonces su contraseña debe tener al menos
math.ceil(math.log(256 ** 32, 74))
== 42 caracteres. Sin embargo, una mayor cantidad de iteraciones de HMAC bien seleccionadas puede mitigar un poco la falta de entropía, ya que esto hace que sea mucho más costoso para un atacante ingresar por la fuerza bruta.Solo sepa que elegir una contraseña más corta pero razonablemente segura no paralizará este esquema, solo reduce el número de valores posibles que un atacante de fuerza bruta tendría que buscar; asegúrese de elegir una contraseña lo suficientemente segura para sus requisitos de seguridad .
Alternativas
Oscureciendo
Una alternativa es no cifrar . No se sienta tentado a usar un cifrado de baja seguridad o una implementación casera de, digamos Vignere. No hay seguridad en estos enfoques, pero pueden darle a un desarrollador sin experiencia que se le encomiende la tarea de mantener su código en el futuro la ilusión de seguridad, que es peor que ninguna seguridad.
Si todo lo que necesita es oscuridad, simplemente base64 los datos; para los requisitos de seguridad URL, la
base64.urlsafe_b64encode()
función está bien. No use una contraseña aquí, solo codifíquela y listo. Como máximo, agregue algo de compresión (comozlib
):Esto se convierte
b'Hello world!'
enb'eNrzSM3JyVcozy_KSVEEAB0JBF4='
.Integridad solamente
Si todo lo que necesita es una forma de asegurarse de que se puede confiar en que los datos no se modificarán después de haber sido enviados a un cliente que no son de confianza y recibidos de vuelta, entonces desea firmar los datos, puede usar la
hmac
biblioteca para esto con SHA1 (aún considerado seguro para la firma HMAC ) o mejor:Use esto para firmar datos, luego adjunte la firma con los datos y envíelo al cliente. Cuando reciba los datos, divida los datos y la firma y verifique. Establecí el algoritmo predeterminado en SHA256, por lo que necesitará una clave de 32 bytes:
Es posible que desee ver la
itsdangerous
biblioteca , que incluye todo esto con serialización y deserialización en varios formatos.Usar cifrado AES-GCM para proporcionar cifrado e integridad
Fernet se basa en AEC-CBC con una firma HMAC para garantizar la integridad de los datos cifrados; un atacante malintencionado no puede alimentar su sistema con datos sin sentido para mantener su servicio ocupado funcionando en círculos con una entrada incorrecta, porque el texto cifrado está firmado.
El cifrado de bloque en modo Galois / Counter produce texto cifrado y una etiqueta para el mismo propósito, por lo que puede usarse para los mismos propósitos. La desventaja es que, a diferencia de Fernet, no existe una receta única y fácil de usar para reutilizar en otras plataformas. AES-GCM tampoco usa relleno, por lo que este texto cifrado de cifrado coincide con la longitud del mensaje de entrada (mientras que Fernet / AES-CBC cifra los mensajes en bloques de longitud fija, oscureciendo un poco la longitud del mensaje).
AES256-GCM toma el secreto habitual de 32 bytes como clave:
luego usa
He incluido una marca de tiempo para admitir los mismos casos de uso de tiempo de vida que admite Fernet.
Otros enfoques en esta página, en Python 3
AES CFB - como CBC pero sin la necesidad de rellenar
Este es el enfoque que sigue All Іѕ Vаиітy , aunque incorrectamente. Esta es la
cryptography
versión, pero tenga en cuenta que incluyo el IV en el texto cifrado , no debe almacenarse como global (reutilizar un IV debilita la seguridad de la clave y almacenarlo como un módulo global significa que se volverá a generar la próxima invocación de Python, haciendo que todo el texto cifrado no se pueda cifrar):Esto carece del blindaje adicional de una firma HMAC y no hay marca de tiempo; tendrías que agregarlos tú mismo.
Lo anterior también ilustra lo fácil que es combinar incorrectamente los bloques de construcción de criptografía básica; Todo el manejo incorrecto de Vаиітy del valor de IV puede conducir a una violación de datos o que todos los mensajes encriptados sean ilegibles porque el IV se pierde. En cambio, usar Fernet lo protege de tales errores.
AES ECB - no seguro
Si implementó anteriormente el cifrado AES ECB y aún necesita admitirlo en Python 3, también puede hacerlo con
cryptography
. Se aplican las mismas advertencias, ECB no es lo suficientemente seguro para aplicaciones de la vida real . Reimplementando esa respuesta para Python 3, agregando manejo automático de relleno:Nuevamente, esto carece de la firma HMAC, y no debería usar ECB de todos modos. Lo anterior está solo para ilustrar que
cryptography
puede manejar los bloques de construcción criptográficos comunes, incluso los que realmente no debería usar.fuente
El "encoded_c" mencionado en la respuesta de cifrado Vigenere de @ smehmood debería ser "key_c".
Aquí están las funciones de codificación / decodificación en funcionamiento.
Descargo de responsabilidad: como se implica en los comentarios, esto no debe usarse para proteger datos en una aplicación real, a menos que lea esto y no le importe hablar con abogados:
¿Qué pasa con el cifrado XOR?
fuente
encodedmsg = encode('mypassword', 'this is the message éçàèç"')
print encodedmsg
print decode('mypassword', encodedmsg)
funciona bien.Aquí hay una versión de Python 3 de las funciones de @qneill 's respuesta :
La codificación / decodificación adicional es necesaria porque Python 3 ha dividido cadenas / matrices de bytes en dos conceptos diferentes y actualizó sus API para reflejar eso.
fuente
.encode()).decode()
. en la devolución deencode()
, y.decode()
en la segunda línea endecode()
.Descargo de responsabilidad: como se menciona en los comentarios, esto no debe usarse para proteger datos en una aplicación real.
¿Qué pasa con el cifrado XOR?
/crypto/56281/breaking-a-xor-cipher-of-known-key-length
https://github.com/hellman/xortool
Como se ha mencionado, la biblioteca PyCrypto contiene un conjunto de cifrados. El "cifrado" XOR puede usarse para hacer el trabajo sucio si no quiere hacerlo usted mismo:
El cifrado funciona de la siguiente manera sin tener que rellenar el texto sin formato:
Crédito a https://stackoverflow.com/a/2490376/241294 por las funciones de codificación / decodificación de base64 (soy un novato en Python).
fuente
sudo pip3 install pycrypto
.Aquí hay una implementación de cifrado y descifrado seguros de URL utilizando AES (PyCrypto) y base64.
Si tiene algún problema como este, https://bugs.python.org/issue4329 (
TypeError: character mapping must return integer, None or unicode
)str(cipher)
úselo mientras decodifica de la siguiente manera:Prueba:
fuente
TypeError: Object type <class 'str'> cannot be passed to C code
.b'...'
, ¡ edité la respuesta para referencia futura!Funciones de codificación / decodificación de trabajo en python3 (adaptado muy poco de la respuesta de qneill):
fuente
Gracias por unas excelentes respuestas. Nada original que agregar, pero aquí hay algunas reescrituras progresivas de la respuesta de qneill usando algunas instalaciones útiles de Python. Espero que esté de acuerdo en que simplifican y aclaran el código.
fuente
Si quiere estar seguro, puede usar Fernet, que es criptográficamente sólido. Puede usar una "sal" estática si no desea almacenarla por separado; solo perderá la prevención de ataques de diccionario y arco iris. Lo elegí porque puedo elegir contraseñas largas o cortas, lo que no es tan fácil con AES.
Si eso es demasiado complicado, alguien sugirió simplecrypt
fuente
Quienquiera que haya venido aquí (y el más generoso) parecía estar buscando frases ingeniosas sin mucha configuración, que otras respuestas no proporcionan. Así que propongo base64.
Ahora, tenga en cuenta que esto es solo una ofuscación básica, y está en ** NINGUNA MANERA ACEPTABLE PARA LA SEGURIDAD ** , pero aquí hay algunas frases ingeniosas:
Algunas cosas a tener en cuenta:
bytes()
ybytes::decode()
=
caracteres. La gente como yo va por ahí decodificándolos en la consola javascript cuando los vemos en sitios web. Es tan fácil comobtoa(string)
(js)Ahora, si lo que quería ni siquiera necesitaba una clave de ningún tipo, sino solo un poco de ofuscación, puede volver a usar base64, sin ningún tipo de clave:
fuente
Fernet(key).encrypt(message)
es solo una expresión como su llamada base64.key
conjunto. Las cargas de los desarrolladores van a copiar y pegar de desbordamiento de pila sin prestar atención y se asumen la clave para ser secreto. Si debe incluirlo, al menos no lo use y advierta o genere una excepción si se usa de todos modos. No subestime la estupidez de la cultura de copiar y pegar y sus responsabilidades para realizar funciones cuerdas.Daré 4 soluciones:
1) Uso de cifrado Fernet con
cryptography
bibliotecaAquí hay una solución usando el paquete
cryptography
, que puede instalar como de costumbre conpip install cryptography
:Puede adaptarse con su propia sal, conteo de iteraciones, etc. Este código no está muy lejos de la respuesta de @ HCLivess, pero el objetivo aquí es tener funciones
encrypt
y listas para usardecrypt
. Fuente: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet .Nota: use
.encode()
y en.decode()
todas partes si desea cadenas en'John Doe'
lugar de bytes comob'John Doe'
.2) Cifrado AES simple con
Crypto
bibliotecaEsto funciona con Python 3:
Nota: puede eliminar
base64.b64encode
y.b64decode
si no desea una salida legible en texto y / o si desea guardar el texto cifrado en el disco como un archivo binario de todos modos.3) AES con una mejor función de derivación de clave de contraseña y la capacidad de probar si "se ingresó una contraseña incorrecta", con
Crypto
bibliotecaLa solución 2) con el "modo CFB" de AES está bien, pero tiene dos inconvenientes: el hecho de que
SHA256(password)
se puede forzar fácilmente con una tabla de búsqueda y que no hay forma de probar si se ha ingresado una contraseña incorrecta. Esto se resuelve aquí mediante el uso de AES en "modo GCM", como se explica en AES: ¿cómo detectar que se ha introducido una contraseña incorrecta?y ¿Es seguro este método para decir "La contraseña que ingresó es incorrecta"? :4) Usando RC4 (no se necesita biblioteca)
Adaptado de https://github.com/bozhu/RC4-Python/blob/master/rc4.py .
(Desactualizado desde las últimas ediciones, pero guardado para referencia futura): Tuve problemas al usar Windows + Python 3.6 + todas las respuestas que involucran
pycrypto
(no puedopip install pycrypto
en Windows) opycryptodome
(las respuestas aquífrom Crypto.Cipher import XOR
fallaron porqueXOR
no es compatible con estapycrypto
bifurcación; y las soluciones que usan... AES
fallaron también conTypeError: Object type <class 'str'> cannot be passed to C code
). Además, la bibliotecasimple-crypt
tiene unapycrypto
dependencia, por lo que no es una opción.fuente
password_encrypt()
.Esto funciona, pero la longitud de la contraseña debe ser exacta
8
. Esto es simple y requiere pyDes .SALIDA:
fuente
Otra implementación del código @qneill que incluye la suma de comprobación CRC del mensaje original, lanza una excepción si la comprobación falla:
fuente
Puede utilizar AES para cifrar su cadena con una contraseña. Sin embargo, querrá elegir una contraseña lo suficientemente fuerte para que la gente no pueda adivinar fácilmente cuál es (lo siento, no puedo evitarlo. Soy un aspirante a pito de seguridad).
AES es fuerte con un buen tamaño de clave, pero también es fácil de usar con PyCrypto.
fuente
Las bibliotecas externas proporcionan algoritmos de cifrado de clave secreta.
Por ejemplo, el
Cypher
módulo de PyCrypto ofrece una selección de muchos algoritmos de cifrado:Crypto.Cipher.AES
Crypto.Cipher.ARC2
Crypto.Cipher.ARC4
Crypto.Cipher.Blowfish
Crypto.Cipher.CAST
Crypto.Cipher.DES
Crypto.Cipher.DES3
Crypto.Cipher.IDEA
Crypto.Cipher.RC5
Crypto.Cipher.XOR
MeTooCrypto es un
Python
contenedor para OpenSSL y proporciona (entre otras funciones) una biblioteca de criptografía de uso general con toda su potencia. Se incluyen cifrados simétricos (como AES).fuente
si desea un cifrado seguro:
para python 2, debe usar keyczar http://www.keyczar.org/
para python 3, hasta que keyczar esté disponible, he escrito simple-crypt http://pypi.python.org/pypi/simple-crypt
ambos utilizarán el fortalecimiento de claves que los hace más seguros que la mayoría de las otras respuestas aquí. y dado que son tan fáciles de usar, es posible que desee usarlos incluso cuando la seguridad no sea crítica ...
fuente
Por lo tanto, como no se codifica nada crítico para la misión y solo desea cifrar para la ocultación .
Déjame presentarte el cifrado de Caeser
El cifrado de César o cambio de César es una de las técnicas de cifrado más sencillas y conocidas. Es un tipo de cifrado de sustitución en el que cada letra del texto sin formato se reemplaza por una letra en un número fijo de posiciones en el alfabeto. Por ejemplo, con un desplazamiento a la izquierda de 3, D sería reemplazada por A, E se convertiría en B, y así sucesivamente.
Código de muestra para su referencia:
Ventajas: cumple con sus requisitos y es simple y realiza la codificación.
Desventaja: se puede descifrar mediante simples algoritmos de fuerza bruta (es muy poco probable que alguien intente pasar por todos los resultados adicionales).
fuente
Agregar un código más con decodificar y codificar como referencia
fuente