¿Por qué openssl enc -aes-256-cbc -a -salt aumenta el tamaño del archivo?

5

Estoy usando openssl enc -aes-256-cbc -a -salt para copias de seguridad diferenciales automatizadas en Amazon Glacier. Pero noté que el uso de este comando aumenta el tamaño del archivo casi perfectamente en un 35%.
A mi entender, un cifrado de bloque no debería cambiar tanto el tamaño del archivo, con mi conocimiento actual, sé que agrega como máximo 16 bytes al final para crear el relleno. Pero eso no cuenta para 17MB + en mis copias de seguridad.

¿Qué está causando este aumento de tamaño?

Líneas de registro:

09:09:16 Created tarbal of 165 files of size            106M
09:09:50 Created /archief/2014-05-10.encrypted of size  143M

09:09:11 Created tarbal of 186 files of size            132M
09:09:52 Created /archief/2014-05-17.encrypted of size  179M
    
pregunta gnur 20.05.2014 - 16:00
fuente

1 respuesta

12

El aumento principal es el indicador -a , que significa que base64 codifica el texto cifrado.

Desde man enc :

NAME
   enc - symmetric cipher routines

SYNOPSIS
   openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e] [-d] [-a] [-A] [-k password]
   [-kfile filename] [-K key] [-iv IV] [-p] [-P] [-bufsize number] [-nopad] [-debug]

   [...]

   -a  base64 process the data. This means that if encryption is taking place the data is base64 encoded
       after encryption. If decryption is set then the input data is base64 decoded before being
       decrypted.

La codificación Base64 significa que por cada tres bytes de datos binarios (un byte es un número de 8 bits, lo que significa que tiene un valor de 0 a 2 8 -1 = 255) que está codificado en cuatro bytes de datos de 6 bits (con valor 0 a 2 6 -1 = 63, aunque están representados en símbolos ASCII imprimibles). Base64 es conveniente ya que los símbolos para los 64 valores pueden elegirse para ser caracteres ASCII imprimibles (por ejemplo, típicamente 0 = 'A', 1 = 'B', ... 25 = 'Z', 26 = 'a' ,. ..51 = 'z', 52 = '0', ..., 61 = '9', 62 = '+', 63 = '/' aunque los dos últimos a menudo se definen de manera diferente en diferentes variantes). Tenga en cuenta que tres bytes 8 * 3 tienen 24 bits, al igual que cuatro grupos de números codificados en base64 6 * 4.

Por ejemplo, si su texto cifrado tenía tres bytes (en hexadecimal): f0 bb 5c (240, 187, 92) en binario, los bits agrupados en tres bytes serían:

 11110000 10111011 01011100

en base64 serían los mismos bits, excepto agrupados en cuatro grupos de 6 bits:

 111100 001011 101101 011100

que se asigna a los valores 60, 11, 45, 28, que en una tabla base64 típica se asignaría a los caracteres ASCII imprimibles 8Ltc que tomará cuatro bytes en el disco (en lugar de los tres bytes que habría tomado sin codificación base64).

Por lo tanto, la codificación base64 debería representar aproximadamente un aumento de archivo del 33%. Es un poco más que eso, ya que openssl también agrega caracteres de nueva línea cada 64 caracteres de ascii codificado en base64 (por lo que el texto se ajusta a 64 bytes). Estas dos características juntas representan un aumento general de tamaño de archivo de (4/3 * 65/64 - 1) = 35.4%

También hay un poco de sobrecarga de su esquema. La especificación de -salt toma su contraseña de texto simple y concatena una sal aleatoria de ocho bytes al mensaje junto con un encabezado Salted__ que especifica que se usó una sal, y estos también estarán codificados en base64. (El propósito de la sal es hacer que sea menos rentable que un atacante realice un cálculo previo de las tablas del arco iris para contraseñas comunes). Si cifro un archivo aleatorio en su esquema (especificando la sal como DEADBEEFDEADBEEF usando openssl enc -aes-256-cbc -a -salt -S DEADBEEFDEADBEEF , la primera fila de mi archivo cifrado fue

U2FsdGVkX1/erb7v3q2+7ybJfdPaLlVzOp7lKpOljvNK8ONCrgFrQpaJHQ8EqO1X

que se decodifica (usando python):

>>> import base64
>>> base64.b64decode("U2FsdGVkX1/erb7v3q2+7ybJfdPaLlVzOp7lKpOljvNK8ONCrgFrQpaJHQ8EqO1X")
'Salted__\xde\xad\xbe\xef\xde\xad\xbe\xef&\xc9}\xd3\xda.Us:\x9e\xe5*\x93\xa5\x8e\xf3J\xf0\xe3B\xae\x01kB\x96\x89\x1d\x0f\x04\xa8\xedW'

Combinando así la codificación base64, los saltos de línea, la sal, el vector de inicialización (para el modo CBC) y el relleno (para que sean divisibles de manera uniforme para que sean bloques de 128 bits para AES), la sobrecarga de ~ 35% parece perfectamente razonable.

EDITAR: En realidad, openssl no almacena un vector de inicialización cuando se deriva una clave de una contraseña con un salt. De man enc : "Cuando se especifica una contraseña usando una de las otras opciones, el IV se genera a partir de esta contraseña". Usando esto y haciendo un par de archivos de prueba, los tamaños de los archivos coinciden perfectamente. El salt 8 bytes más Salted__ agrega 16 bytes al archivo. El archivo se rellena para ser un múltiplo de 16 bytes (agregando como máximo 16 bytes). Si no codifica en base64, el tamaño del archivo coincide perfectamente, y luego puede obtener un archivo que coincida exactamente con la versión base64 si aplica base64 --wrap=64 .

    
respondido por el dr jimbob 20.05.2014 - 16:06
fuente

Lea otras preguntas en las etiquetas