¿Este método de confirmación de contraseña pone en riesgo la integridad del archivo cifrado?

1

Estoy tratando de hacer un script básico de cifrado / descifrado para uso personal, y funciona perfectamente bien. Estoy publicando esto en la sección de infosec porque mi pregunta gira en torno a qué tan fácil es romper el cifrado.

NOTA: Sé poco sobre criptología, de ahí la pregunta simplista.

Aquí hay una rápida maqueta de mi código:

from Crypto.Cipher import AES
import hashlib
from random import randint
import struct
from getpass import getpass
import os

infile = sys.argv[1]
password = hashlib.sha256(getpass('[*] Enter Password: ')).digest()
ivector = ''.join(chr(randint(0, 0xFF)) for i in range(16))

encryptor = AES.new(password, AES.MODE_CBC, ivector)

with open(infile, 'rb') as infile:
    to_encrypt = infile.read()

to_encrypt += 'password_is_correct'
while len(to_encrypt)%16 != 0:
    to_encrypt += ' ' #Pad file to a multiple of 16 for encryption

encrypted = encryptor.encrypt(to_encrypt)
size = os.path.getsize(infile)
with open(infile, 'wb') as outfile:
    outfile.write(struct.pack(size, '<Q'))
    outfile.write(ivector)
    outfile.write(encrypted)

print '[*] Encryption Completed!'

Para resumir. Este código cifrará un archivo con un vector de inicialización aleatorio y una contraseña proporcionada por el usuario. Leerá el archivo para cifrar y agregará la cadena "password_is_correct" al final de la cadena. Una vez descifrado, el vector de inicialización se leerá del archivo y se tomará una contraseña del usuario. Si la contraseña es correcta, entonces la cadena "password_is_correct" debería estar en la cadena descifrada. ¿Es este un método válido una verificación de contraseña? ¿Esto supone algún tipo de riesgo para la integridad del archivo que facilita el proceso de descifrado de archivos?

El código completo se puede encontrar aquí .

    
pregunta The Defalt 10.06.2016 - 08:37
fuente

2 respuestas

4

Sí, este es un método válido de verificación de contraseña.

Una desventaja es que un atacante ahora sabe que el texto simple "password_is_correct" corresponde al último bloque en el texto cifrado. Afortunadamente, AES es no vulnerable por texto llano conocido ataques.

PGP también comprueba los datos descifrados , pero utiliza propiedades de un bloque aleatorio en lugar de una cadena fija. Otra forma que a menudo se usa incorrectamente es verificar el relleno del mensaje. Esto puede hacer posible un ataque de Oracle oráculo , aunque esto no se aplica a su situación.

Otra forma típica es almacena un hash de la clave en el mensaje, para que la contraseña pueda verificarse antes de descifrar el mensaje.

Hay otras cosas que pueden mejorarse con su script:

  • Use SystemRandom para obtener la IV, ya que lo normal no es criptográficamente seguro.
  • Use una función de derivación de clave real como PBKDF2 en lugar de SHA256 para derivar la clave de cifrado de la contraseña.
  • Almacene un HMAC del texto cifrado y verifíquelo antes del cifrado. CBC es vulnerable a un ataque de intercambio de bits .
  • Es posible que también desee cifrar el campo de tamaño de archivo.
respondido por el Sjoerd 10.06.2016 - 09:42
fuente
-1

Lo que básicamente estás haciendo aquí es derivar una clave de una contraseña manualmente y verificar la integridad del archivo manualmente. La respuesta estándar a este tipo de pregunta es "no lo hagas". En resumen, intente usar las bibliotecas para realizar comprobaciones de la clave, el cifrado y la integridad. La contraseña y el archivo / archivo cifrado entran, el archivo cifrado / descifrado sale.

Integridad del archivo

El problema aquí es que está intentando verificar el descifrado correcto al verificar que existe una cadena. Sin embargo, lo que realmente está comprobando es solo el final del archivo. El problema con eso es que su proceso de encriptación no protege contra la manipulación del resto del archivo (encriptado). El porqué es un poco complicado, pero básicamente podría ser posible voltear bits en el archivo cifrado de manera inteligente para cambiar la salida. Luego, el contenido de su archivo "ABCpassword_is_correct" podría convertirse en "AB D password_is_correct".

Como lo ha preguntado, este podría en algunos casos también afecta la calidad de la confidencialidad (le preocupa si otra persona puede leer el archivo sin la clave). Si desea saber más sobre eso, le recomiendo que haga una pregunta al respecto en crypto , ya que está fuertemente relacionado con la forma en que trabajos criptográficos reales.

Verificación de contraseña

Hay un concepto en criptografía llamado función de derivación de clave basada en contraseña, que es probablemente lo que estás buscando. También hay una biblioteca de Python que implementa esta funcionalidad que se encuentra aquí . Si entiendo correctamente, la implementación se ajusta a OpenSSL.

Algún contexto: PBKDF2 es un protocolo estandarizado (criptográfico) que le proporciona una clave de un secreto. La parte más importante que esto hace más allá de lo que escribió es agregar un salt al proceso de contraseña. Podría preguntarse por qué esto es importante; la razón principal es que puede querer claves diferentes para archivos diferentes. Entonces, incluso cuando el IV es el mismo y partes de los archivos son iguales, sus archivos cifrados serán indistinguibles. Debería ser suficiente usar el nombre del archivo o la ruta como sal.

Otros problemas

No estoy seguro de si el proceso de cifrado que está utilizando es seguro. Creo que tienes problemas similares con el relleno. Lo ideal sería utilizar implementaciones estandarizadas para ellos. Esto no solo evita errores (la recuperación de datos es difícil ...) sino que también garantiza que su implementación no debilite su seguridad. La mayoría de los problemas de seguridad se deben a una mala implementación, y este también es el caso de la criptografía.

    
respondido por el Rens van der Heijden 10.06.2016 - 08:55
fuente

Lea otras preguntas en las etiquetas