2009-08-04 14 views
8

Estoy implementando el cifrado/descifrado usando Java Cipher y AES. Todo funciona bien, excepto que hay 5 bytes adicionales escritos en la llamada a doFinal(). Entonces, termino con una cadena decodificada correctamente con 5 bytes adicionales añadidos.Java cipher.doFinal() escribiendo bytes adicionales

Creo que la razón es que se está escribiendo todo el bloque de 16 bytes. Veo 3 bloques de 16 bytes escritos, incluido el último. El archivo encriptado de entrada es de 64 bytes. El texto no encriptado debe tener 43 bytes.

La documentación para doFinal indica que puede devolver el número de bytes escritos en el búfer de salida. Sin embargo, es 0,16,16,16. Probé todas las formas de doFinal y actualicé y no obtuve cambios en el comportamiento.

Tiene sentido escribir un bloque completo, ya que así es como funcionan la mayoría de estos algoritmos. Sin embargo, si no me va a decir el tamaño de los datos de salida, ¿cómo se supone que debo evitar el exceso de datos?

¿Debería estar utilizando otro algoritmo? AES256 es un requisito, pero me pregunto si un tipo de bloque o relleno diferente podría permitirle escribir la cantidad correcta de bytes.

¿Alguna orientación?

cortó para (a) la brevedad:

decryptCipher = Cipher.getInstance("AES"); 
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey); 

parte de negocios de la rutina de descifrado.

long bytesToRead = inputFile.length(); 

    while ((inLen = in.read(buffer)) > 0) { 
     int bytesOut = 0; 
     byte[] cryptBytes = null; 
     int outLen = cipher.getOutputSize(inLen); 
     cryptBytes = new byte[outLen]; 

     if (bytesToRead <= buffer.length) { 
      try { 
       bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } else 
      try { 
       bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     out.write(cryptBytes, 0, bytesOut); 
     bytesToRead -= inLen; 

    } 
    try { 
     out.flush(); 
     in.close(); 
     out.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

Respuesta

14

Debe especificar un mecanismo de relleno al llamar a Cipher.getInstance(); obviamente, debe ser el mismo tanto en tiempo de cifrado como de desencriptado. por ejemplo:

decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

Sin un mecanismo de relleno, el lado de descifrado no tiene información de la ubicación del final del texto claro es (dentro del último bloque).

+0

Impresionante, muchas gracias. Eso lo resolvió Tenía la impresión de que si solo especificaba AES, obtenía el modo de bloque ECB y el PCKS5Padding por defecto. Supongo que eso es incorrecto. – wadesworld

+1

, lo mismo se aplica a todos los motores AES, incluidos los que no están en Java. – Cheeso

1

AES es un cifrado de bloques , naturalmente, que va a darle bloques enteros, al igual que todas las cifras de bloque.

Consulte el Wikipedia article on AES para obtener más información.

Dijiste que querías que saliera el "número correcto de bytes". ¿Cómo has decidido cuál es la cantidad correcta de bytes?

+1

Creo que él sabe que AES lo hace, la pregunta es acerca de cómo usar la API de Java. – skaffman

+0

Para saber el tamaño no encriptado correcto después de descifrarlo, debe escribir el tamaño original en la secuencia. –

Cuestiones relacionadas