2010-07-05 10 views
5

Obtuve una excepción en el siguiente código para el algoritmo AES en java.Excepción en el algoritmo de descifrado AES en java

El código desencripta una cadena encriptada y devuelve la cadena original.

Por favor, ayúdenme a solucionarlo.

Código:

public class AES 

{ 

public byte[] encrypted; 

public byte[] original; 

public String originalString; 

public static String asHex (byte buf[]) 

{ 

StringBuffer strbuf = new StringBuffer(buf.length * 2); 

int i; for (i = 0; i < buf.length; i++) 

{ 

if (((int) buf[i] & 0xff) < 0x10) strbuf.append("0"); 

strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); 

} 

return strbuf.toString(); 

} 

public String AESencryptalgo(byte[] text) 

{ 

String newtext=""; 

// Get the KeyGenerator 

try 

{ 

    KeyGenerator kgen = KeyGenerator.getInstance("AES"); 

    kgen.init(128); // 192 and 256 bits may not be available 

// Generate the secret key specs. 

SecretKey skey = kgen.generateKey(); 

byte[] raw = skey.getEncoded(); 

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 

// Instantiate the cipher Cipher cipher = Cipher.getInstance("AES"); 

cipher.init(Cipher.ENCRYPT_MODE, skeySpec); encrypted = cipher.doFinal(text); 

System.out.println("encrypted string: " + asHex(encrypted)); 

cipher.init(Cipher.DECRYPT_MODE, skeySpec); original = cipher.doFinal(encrypted); 

originalString = new String(original); System.out.println("Original string: " + originalString + " " + asHex(original)); 

} 

catch(Exception e) 

{ } 

finally 

{ 

newtext=new String(encrypted); 

System.out.println("ENCRYPTED "+newtext); 

//AESdecryptalgo(newtext.getBytes()); 

return newtext; 

} 

} 

public String AESdecryptalgo(byte[] text) 

{ 

// Get the KeyGenerator 

try 

{ 

KeyGenerator kgen = KeyGenerator.getInstance("AES"); 

kgen.init(128); // 192 and 256 bits may not be available 

// Generate the secret key specs. 

SecretKey skey = kgen.generateKey(); 

byte[] raw = skey.getEncoded(); 

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 

// Instantiate the cipher 

Cipher cipher = Cipher.getInstance("AES"); 

cipher.init(Cipher.DECRYPT_MODE, skeySpec); 

original = cipher.doFinal(text); //Exception occurs here 

originalString = new String(original); 

System.out.println("Original string: " + originalString + " " + asHex(original)); 

} 

catch(Exception e) 

{ 

System.out.println("exception"); 

} 

finally 

{ 

System.out.println("DECRYPTED "+originalString); 

return originalString; 

} 

} 

public static void main(String[] args) 

{ 

AES a=new AES(); 

a.AESencryptalgo("hello".getBytes()); 

System.out.println(); 

}} 
` 

excepción:

javax.crypto.BadPaddingException: Given final block not properly padded at 
com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at 
com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) at 
com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) at 
javax.crypto.Cipher.doFinal(DashoA13*..) 
+2

debe reformatear su código –

+0

@ Xavier Combelle He reformateado – sparkle

+2

@user: ¿Qué * es * la excepción? Por lo menos, reemplace su impresión con 'e.printStackTrace()' e informe. –

Respuesta

0

Bueno, si esta es la longitud de entrada de error debe ser múltiplo de 16 años cuando el descifrado de cifrado con acolchado. Que el answear es obvio, la longitud de su buffer debe ser un múltiplo de 16. ¿Ha comprobado la longitud de buf []?

14

Según Java™ Cryptography Architecture (JCA) Reference Guide (énfasis mío):

Cipher objetos se obtienen mediante el uso de uno de los Cipher getInstance() static factory methods. Aquí, el nombre del algoritmo es ligeramente diferente que con otras clases de motor, en el sentido de que especifica no solo un nombre de algoritmo, sino una "transformación". Una transformación es una cadena que describe la operación (o el conjunto de operaciones ) que se realizará en la entrada dada para producir alguna salida. Una transformación siempre incluye el nombre de un algoritmo criptográfico (por ejemplo, DES), y puede estar seguido por un modo y un esquema de relleno.

Una transformación es de la forma:

  • "algoritmo/modo/relleno" o
  • "algoritmo"

Por ejemplo, los siguientes son transformaciones válidas:

  • "DES/CBC/PKCS5Padding"
  • "DES"

Si se especifica un nombre de transformación, el sistema determinar si hay un aplicación de la solicitada transformación disponible en el entorno , y si hay más de uno , vuelve hay uno preferido.

Si no se especifica un nombre de transformación y un proveedor paquete, el sistema determinará si hay un aplicación de la transformación solicitada en el paquete solicitado, y lanzar una excepción si no lo hay.

Si no se especifica ningún modo o relleno, valores predeterminados específicos del proveedor para se utilizan el modo y el esquema de relleno. Por ejemplo, el proveedor de SunJCE utiliza ECB como el modo por defecto, y PKCS5Padding como el esquema predeterminado de relleno para DES, DES-EDE y Blowfish sistemas de cifrado. Esto significa que en el caso de que el proveedor SunJCE:

Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding"); 

y

Cipher c1 = Cipher.getInstance("DES"); 

declaraciones son equivalentes.

Uso de los modos como CFB y OFB, los cifrados de bloque se cifrar los datos en unidades más pequeñas que el tamaño de bloque real la de cifrado. Cuando solicitando un modo tal, puede especificar opcionalmente el número de bits para ser procesados ​​a la vez añadiendo este número para el nombre del modo como se muestra en el "DES/CFB8/NoPadding" y "DES/OFB32/PKCS5Padding " transformaciones. Si no se especifica dicho número , se utiliza un valor predeterminado específico del proveedor. (Por ejemplo, el SunJCE proveedor utiliza un valor predeterminado de 64 bits para DES). Así, los cifrados de bloque se pueden convirtió en byte-orientada a flujo sistemas de cifrado mediante el uso de un modo de 8 bits como CFB8 o OFB8.

Appendix A de este documento contiene una lista de nombres estándar que pueden ser utilizada para especificar el nombre del algoritmo, modo y componentes esquema de relleno de una transformación .

Los objetos devueltos por los métodos de fábrica no están inicializados, y deben inicializarse en antes de que se puedan utilizar.

Como el código no especifica el modo o el relleno, se están utilizando los valores predeterminados específicos del proveedor. Parece que su proveedor es SunJCE y que su relleno predeterminado es probablemente "NoPadding". Con este relleno, usted es responsable de garantizar que el tamaño de la matriz de bytes que se cifra sea un múltiplo de la cantidad de bytes en la clave secreta. Usted puede hacer la vida más fácil que eres especificando el modo y el relleno en su transformación:

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 

ADVERTENCIA: No use el modo BCE en código real. Pruebe CBC en su lugar.

Actualización: yo no creía que fuera justo para recomendar el modo CBC sin ofrecer una pequeña muestra de cómo funciona:

public static void main(String... args) throws Exception { 
    byte[] data = "hello".getBytes(); 

    KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); 
    keyGenerator.init(128); // 192 and 256 bits may not be available 

    SecretKey secretKey = keyGenerator.generateKey(); 

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

    // By initializing the cipher in CBC mode, an "initialization vector" has been randomly 
    // generated. This initialization vector will be necessary to decrypt the encrypted data. 
    // It is safe to store the initialization vector in plain text for later use. You can obtain 
    // it's bytes by calling iv.getIV(). 
    cipher.init(Cipher.ENCRYPT_MODE, secretKey); 
    IvParameterSpec iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class); 
    byte[] encryptedData = cipher.doFinal(data); 

    // When decrypting the encrypted data, you must provide the initialization vector used 
    // during the encryption phase. 
    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv); 
    byte[] decryptedData = cipher.doFinal(encryptedData); 

    if (!Arrays.equals(data, decryptedData)) { 
     throw new Exception("Data was not decrypted successfully"); 
    } 
} 
+1

+1 para advertencia de ECB + muestra –

+1

Gracias Adam ... pero sigo teniendo problemas con esto .. – sparkle

+0

@sparkle: ¿Es el mismo error? –

0

Su código se las arregla para conseguir casi todo mal. Para comenzar, sus errores incluyen:

  1. generando una nueva clave simétrica aleatoria antes del cifrado y descifrado. Debe usar la misma clave para descifrar que se utilizó para encriptar.
  2. Uso de String como contenedor de datos binarios. La salida de cifrado no se puede convertir de manera confiable en una Cadena a menos que use una codificación, como base64.
  3. Su manejo de excepciones es incorrecto.

Además, su código se ejecuta sin excepciones para mí.

Cuestiones relacionadas