2010-04-02 22 views
9

Estoy tratando de crear un método de cifrado AES, pero por alguna razón me siguen dandode cifrado AES de Java Clave no válida longitud

java.security.InvalidKeyException: Key length not 128/192/256 bits

Aquí está el código:

public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 
    // NOTE: last argument is the key length, and it is 256 
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); 
    SecretKey tmp = factory.generateSecret(spec); 
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
    return(secret); 
} 


public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 
    SecretKey secret = getSecretKey(password, salt); 

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

    // NOTE: This is where the Exception is being thrown 
    cipher.init(Cipher.ENCRYPT_MODE, secret); 
    byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); 
    return(ciphertext); 
} 

¿Alguien puede ver lo que estoy haciendo mal? Estoy pensando que puede tener algo que ver con el algoritmo SecretKeyFactory, pero es el único que puedo encontrar que es compatible con el sistema final en el que me estoy desarrollando. Cualquier ayuda sería apreciada. Gracias.

+1

¿Puedes por favor pegar la excepción? –

+0

Hay una respuesta en una publicación anterior en [este enlace] (http://stackoverflow.com/questions/992019/java-256bit-es_encryption/992413#992413). ¡Espero que esto ayude! –

+0

entonces, parece que la instancia java no es compatible con lo que necesito: 'A java.security.InvalidKeyException con el mensaje "Tamaño de clave ilegal o parámetros predeterminados"' – wuntee

Respuesta

-1

utilizando cualquier mecanismo de relleno para rellenar los bits vacíos

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

Vaya, disculpe este relleno para la entrada no para la clave –

8

Para un cifrado fuerte clave más fuerte que se necesita para descargar Java Cryptography Extension (JCE) Archivos de política de jurisdicción de fuerza ilimitada.

http://java.sun.com/javase/downloads/index.jsp (ver otras descargas).

+0

He descargado los archivos adicionales, los he añadido al proyecto, pero sigo obteniendo la excepción ... – wuntee

+0

No los agrega al proyecto, son bibliotecas de tiempo de ejecución . El archivo README.txt indica que debe instalarlos en su carpeta de seguridad de tiempo de ejecución (sobrescribir los archivos allí) Si utiliza JDK, entonces:/ruta/a/jdk/jre/libs/security/ Si usa JRE en su lugar :/ruta/a/jre/libs/seguridad/ –

+0

¿Eso resolvió su pregunta? –

-1

Cuando coloco el siguiente código y ejecutarlo, no recibo ninguna excepción:

import java.io.UnsupportedEncodingException; 
import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.security.spec.InvalidKeySpecException; 
import java.security.spec.InvalidParameterSpecException; 
import java.security.spec.KeySpec; 

import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.crypto.SecretKeyFactory; 
import javax.crypto.spec.PBEKeySpec; 
import javax.crypto.spec.SecretKeySpec; 


public class Main 
{ 
    public static void main(String[] args) 
    { 
     String pass = "this is the pass"; 
     char[] pw = new char[pass.length()]; 
     for(int k=0; k<pass.length();++k) 
     { 
      pw[k] = pass.charAt(k); 
     } 
     try { 
      byte[] q = encrypt(pw,"asdf".getBytes(),"der text"); 
      System.out.println(new String(q)); 
     } catch (InvalidKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidKeySpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (InvalidParameterSpecException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IllegalBlockSizeException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (BadPaddingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnsupportedEncodingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
     SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); 
     // NOTE: last argument is the key length, and it is 256 
     KeySpec spec = new PBEKeySpec(password, salt, 1024, 256); 
     SecretKey tmp = factory.generateSecret(spec); 
     SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
     return(secret); 
    } 


    public static byte[] encrypt(char[] password, byte[] salt, String text) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, InvalidParameterSpecException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{ 
     SecretKey secret = getSecretKey(password, salt); 

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

     // NOTE: This is where the Exception is being thrown 
     cipher.init(Cipher.ENCRYPT_MODE, secret); 
     byte[] ciphertext = cipher.doFinal(text.getBytes("UTF-8")); 
     return(ciphertext); 
    } 
} 

nunca fue capaz de recrear la excepción de que tenías. Estoy ejecutando J2SE 1.6 y desarrollando en Eclipse.

¿Podría ser que su contraseña no tenga 16 bytes de longitud?

+0

Una contraseña no es una clave. El usuario estaba utilizando correctamente una función de derivación de clave basada en contraseña (PBKDF). Has eliminado esa protección requerida. Sugerencia: existe tal cosa como 'GeneralSecurityException' y normalmente lo arroja en su método o crea una excepción de tiempo de ejecución (por ejemplo, una 'IllegalStateException' si el algoritmo no se puede encontrar) fuera de ella. –

+0

No he eliminado ninguna protección. El método encrypt() llama a getSecretKey() que llama a PBEKeySpec() del mismo modo que OP en su código original. – Chopstick

2

Puede instalar los frascos JCE Unlimited Strength, como se sugiere en otras preguntas similares, o simplemente intente incluir este código en su función principal o controlador.

try { 
    java.lang.reflect.Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted"); 
    field.setAccessible(true); 
    field.set(null, java.lang.Boolean.FALSE); 
} catch (Exception ex) { 
    ex.printStackTrace(); 
} 
+0

no funciona en java 8 –

2

El problema aquí es la falta de coincidencia entre los tamaños de las teclas para la función de derivación de las teclas y las cifras dadas. El PBKDF que utiliza es "PBEWithMD5AndDES" y en esta cadena la parte DES indica el tipo de salida. Como único DES, como se lo conoce, solo se utilizan claves de 8 bytes (64 bits, 56 tamaños de bits efectivos con bits de paridad). Las claves AES deben ser 128, 192 y 256 bits y no deben incluir bits de paridad.

Para crear tamaños de clave AES, al menos debe usar PBKDF2 en lugar de PBKDF1, preferiblemente con SHA-256 o SHA-512 para tamaños de clave más altos. Para las claves de 128 bits, sin embargo, debería estar bien con SHA-1. Entonces, use la compilación en "PBKDF2WithHmacSHA1"SecretKeyFactory. Tenga en cuenta que PBKDF2/SHA1 con claves de más de 160 bits dará como resultado una operación subóptima. Es posible que desee utilizar una función de derivación de clave basada en una tecla simple (KBKDF) sobre la salida si desea crear más datos (como un IV por separado).

Como han indicado otros, si utiliza claves de más de 128 bits necesitará los archivos ilimitados de la jurisdicción crypto.


Notas sobre el siguiente código:

  • Sin protección de la integridad, que es posible que tenga incluso para el mantenimiento de la confidencialidad
  • CBC utilizando un cero IV, esto puede ser bien, pero sólo si la sal es completamente aleatorio (almacenar la sal con el texto cifrado)
  • 1024 es un número relativamente bajo de iteraciones para el PBKDF2
  • PBKDF2 es incompatible con PBKDF1 que estuviera usando
public static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException{ 
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 
    // NOTE: last argument is the key length, and it is 128 
    KeySpec spec = new PBEKeySpec(password, salt, 1024, 128); 
    SecretKey tmp = factory.generateSecret(spec); 
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); 
    return(secret); 
} 

public static byte[] encrypt(char[] password, byte[] salt, String text) throws GeneralSecurityException { 
    SecretKey secret = getSecretKey(password, salt); 
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(new byte[cipher.getBlockSize()])); 
    byte[] ciphertext = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8)); 
    return(ciphertext); 
} 
Cuestiones relacionadas