¿Cómo se incrusta el IV en un archivo cifrado cuando no lo indicas?

¿Cómo se incrusta el IV en un archivo cifrado cuando no lo indicas?

Supongamos que cifro con una clave "1234" un archivo que contiene "abcd" con:

openssl enc -iv BABA -aes128 -in file.txt -out file.enc -p

Yo obtengo:

salt=1B929D9049534D22
key=0326A1E8F4875B26FE2D04E02425C5AD
iv =BABA0000000000000000000000000000

Hasta ahora, todo bien.

Puedo descifrar el archivo con:

openssl enc -d -aes128 -iv BABA -in file1.enc -out file1.dec.txt -p

Y obviamente recibo la misma sal, clave e intravenosa que antes.

La primera pregunta es: ¿en qué sentido "0326A1E8F4875B26FE2D04E02425C5AD" es la "clave"?

¿Cuál es su relación con mi clave "1234"? (Parece un hash md5. Pero... ¿de qué?)

Continúemos. Ahora hago lo mismo (mismo texto plano, misma clave) sin proporcionar el iv:

openssl enc -aes128 -in file.txt -out file2.enc -p

Yo obtengo:

salt=237F07334625A768
key=F746D2B53EB82F7129BAEB2FCE2C310F
iv =BA28DBA00442BD4BACEBCAE7C01BA412

Ahora descifro con:

openssl enc -d -aes128 -in file2.enc -out file2.dec.txt -p

y me sale lo mismo SIN poner la iv!

salt=237F07334625A768
key=F746D2B53EB82F7129BAEB2FCE2C310F
iv =BA28DBA00442BD4BACEBCAE7C01BA412

Ahora, aunque puedo ver el salt en el archivo cifrado y proporciono la clave del programa, no escribo el iv ni puedo ver el iv en el archivo cifrado.

Por lo tanto, la segunda pregunta es: ¿cómo sabe el programa de descifrado el iv necesario para descifrar el archivo? O, para decirlo de otra manera, si el iv está incrustado en el archivo cifrado (como lo está el salt), ¿cómo se hace?

Respuesta1

Tanto la clave como el IV se calculan a partir de la contraseña utilizando un PBKDF. En el caso de OpenSSL el método utilizado es EVP_BytesToKey. Esta es una función similar a PBKDF1 que no utiliza muchas iteraciones. La sal es un parámetro de entrada al PBKDF. Se asegura de que la clave y el IV sean siempre diferentes, incluso si usa la misma contraseña.

Puedes echar un vistazo al código fuente.aquípara tener una idea de cómo se lleva a cabo la derivación de la clave y el IV ( EVP_BytesToKeyno se describe muy bien, es un mecanismo propietario dentro de OpenSSL).

Básicamente, durante el cifrado:

openssl_encrypt(password: string, plaintext: bytes): bytes
{
    salt:bytes = random(8) # 8 bytes = 64 bits
    iterations:int = 1
    key:bytes, iv:bytes = pbkdf(password, iterations, salt)
    ciphertext:bytes = encrypt_aes_cbc_pkcs7padding(key, iv, plaintext)
    encoded_ciphertext:bytes = "Salted__" | salt | ciphertext
    return encoded_ciphertext
}

y este es el descifrado:

openssl_decrypt(password:string, encoded_ciphertext:bytes)
{
    salt:bytes = take(encoded_ciphertext, from: 8, size: 8) # 8 bytes = 64 bits
    ciphertext:bytes = take(encoded_ciphertext, from: 16, size: sizeof(encoded_ciphertext - 16)
    iterations:int = 1
    key:bytes, iv:bytes = pbkdf(password, iterations, salt)
    plaintext:bytes = decrypt_aes_cbc_pkcs7padding(key, iv, ciphertext)
    return plaintext
}

información relacionada