2010-09-15 36 views
13

Al haber comenzado recientemente a usar criptografía en mi aplicación, me sorprende la relación entre la longitud del texto de entrada y el texto cifrado. Antes de aplicar crypto, era fácil determinar la base de datos tamaño de columna Ahora, sin embargo, el tamaño de la columna varía ligeramente.Relación entre entrada y longitud de texto cifrado en AES

dos preguntas:

  1. Estoy en lo cierto al suponer esto es debido al acolchado de mi entrada, de forma que encaje requirments del cifrado?
  2. ¿Hay alguna forma de predecir con precisión la longitud máxima del texto cifrado en función de la longitud máxima de la entrada?

Y para puntos de bonificación: ¿debería estar almacenando el texto cifrado base64-codificado en varchar, o mantenerlo como bytes sin procesar y almacenarlos en un varbinary? ¿Hay riesgos relacionados con el almacenamiento de los bytes en mi base de datos (estoy usando consultas parametrizadas, por lo que en teoría la ruptura accidental del escape no debería ser un problema)?

TIA!

Supplemental: El cifrado que estoy usando es AES/Rijndael-256 - ¿Esta relación varía entre los algoritmos disponibles?

+0

¿Por qué necesita para especificar la longitud máxima en absoluto? No son los años 80: las bases de datos admiten campos con límites de longitud grandes o inexistentes durante algún tiempo. –

+0

Rendimiento y menos almacenamiento necesarios. Los campos TEXTO y BLOB son asombrosos, pero para pequeños bits de datos (es decir, estamos hablando de contraseñas encriptadas ... no grandes cantidades de datos XML o novelas), la sobrecarga parece extraña. TEXT y BLOB se almacenan en un área separada en su base de datos de los registros de los que forman parte, lo que hace que su motor de base de datos haga dos lecturas en lugar de una. – kander

Respuesta

25

La relación depende de la el relleno y el encadenamiento modos que está utilizando, y el tamaño del bloque algoritmo (si se trata de una cifra del bloque).

Algunos algoritmos de cifrado son cifrados de flujo que cifran los datos "bit a bit" (o "byte por byte"). La mayoría de ellos produce una secuencia dependiente de clave de bytes pseudoaleatorios, y el cifrado se realiza mediante XORing esa secuencia con los datos (el descifrado es idéntico). Con un cifrado de flujo, la longitud cifrada es igual a la longitud de datos simples.

Otros algoritmos de cifrado son cifra de bloque. Un cifrado de bloque, nominalmente, encripta un solo bloque de datos de una longitud fija. AES es un cifrado de bloques con bloques de 128 bits (16 bytes). Tenga en cuenta que AES-256 también usa bloques de 128 bits; el "256" es sobre la longitud de la llave, no la longitud del bloque. El modo de encadenamiento trata de cómo los datos se dividirán en varios de esos bloques (esto no es fácil de hacer de forma segura, pero el modo CBC está bien). Dependiendo del modo de encadenamiento, los datos pueden requerir un relleno de , es decir, unos pocos bytes adicionales agregados al final para que la longitud sea apropiada para el modo de encadenamiento. El relleno debe ser tal que se pueda eliminar sin ambigüedades al descifrar.

Con el modo CBC, los datos de entrada deben tener un múltiplo longitud de la longitud del bloque, por lo que es costumbre añadir PKCS # 5 padding: si la longitud de bloque es n, a continuación, se añade al menos 1 byte, en más n, de manera que el tamaño total es un múltiplo de n, y los últimos bytes añadidos (posiblemente todos ellos) tienen valor numérico k donde k es el número de bytes añadidos. Al descifrar, basta con mirar el último byte descifrado para recuperar k y así saber cuántos bytes de relleno deben eliminarse en última instancia.

Por lo tanto, con el modo CBC y AES, suponiendo PKCS # 5 relleno, si los datos de entrada tiene una longitud d entonces la longitud cifrada se (d + 16) & ~15. Estoy usando notación tipo C aquí; en pocas palabras, la longitud es de entre d + 1 y d + 16, y múltiplo de 16.

Hay un modo llamado CTR (como "counter") en el que el cifrado de bloque encripta valores sucesivos de un contador, produciendo una secuencia de bytes pseudoaleatorios. Esto efectivamente convierte el cifrado de bloque en un cifrado de flujo y, por lo tanto, un mensaje de longitud d se cifra en d bytes.

Advertencia: sobre todos los sistemas de cifrado (incluyendo cifras de la corriente) y modos requieren un valor extra llamado el IV (Valor inicial). Cada mensaje tendrá su IV y ningún mensaje cifrado con la misma clave deberá usar el mismo IV. Algunos modos tienen requisitos adicionales; en particular, tanto para CBC como para CTR, el IV se seleccionará aleatoria y uniformemente con un generador de números pseudoaleatorios criptográficamente fuerte. El IV no es secreto, pero debe ser conocido por el descifrador. Como cada mensaje tiene su propio IV, a menudo se necesita codificar el IV junto con el mensaje encriptado. Con CBC o CTR, el IV tiene longitud n, entonces, para AES, son 16 bytes adicionales. No sé lo que mcrypt hace con el IV, pero, criptográficamente hablando, el IV debe ser administrado en algún momento.

En cuanto a Base64, es bueno para transferir datos binarios a través de medios de solo texto, pero esto no debería ser necesario para una base de datos adecuada. Además, Base64 amplía los datos en aproximadamente un 33%, por lo que no debe aplicarse a ciegas. Creo que es mejor evitar Base64 aquí.

+0

+1 @Thomas, buena explicación. ¿No es posible que use/no use un IV para el modo AES CBC, si genera una nueva clave de sesión para cada archivo que desea encriptar? Gracias – Raj

+1

Si genera una nueva clave para cada archivo, puede usar una IV convencional (por ejemplo, una IV totalmente nula) que no necesita ser codificada.Pero generar una nueva clave secreta aleatoria para cada archivo es al menos tan difícil como generar una nueva IV aleatoria para cada archivo. Lo que sea mejor depende de la situación. –

+0

Gracias por su respuesta muy detallada: estoy almacenando el IV en una columna separada de los datos cifrados, en el mismo registro, porque el IV tiene una longitud fija. Me mantendré alejado de Basin en el texto cifrado. – kander

1

Según tengo entendido, en los modos de bloque (cbc, ecb) la longitud de salida se redondeará al tamaño de bloque, como lo devuelve mcrypt_enc_get_block_size. Además, debe almacenar IV junto con los datos, por lo que el tamaño se redondeará strlen (datos) + mcrypt_enc_get_iv_size().

En cuanto a la codificación base64, no me molestaría (pero asegúrese de usar la codificación hexadecimal al descargar su db).

1

Para AES CBC cifrado en bloque con el relleno PKCS # 5,

#define BLOCKSIZE 16 

size_t CipherTextLen = (PlainTxtLen/BLOCKSIZE + 1) * BLOCKSIZE; 

Esto no toma en cuenta el vector de inicialización

Cuestiones relacionadas