2010-04-02 4 views
9

Je suis en train de créer une méthode de cryptage AES, mais pour une raison que je continue à obtenirAES Java non valide Longueur de la clé

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

Voici le code:

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); 
} 

Quelqu'un peut-il voir ce que je fais mal? Je pense qu'il peut avoir quelque chose à voir avec l'algorithme de SecretKeyFactory, mais c'est le seul que je peux trouver qui est pris en charge sur le système final que je développe. Toute aide serait appréciée. Merci.

+1

Pouvez-vous s'il vous plaît coller l'exception? –

+0

Il y a une réponse dans un article précédent à [ce lien] (http://stackoverflow.com/questions/992019/java-256bit-aes-encryption/992413#992413). J'espère que cela t'aides! –

+0

donc, il semble que l'instance java ne supporte pas ce dont j'ai besoin: 'Une java.security.InvalidKeyException avec le message "Taille de clé illégale ou paramètres par défaut"' – wuntee

Répondre

-1

en utilisant des mécanismes de remplissage pour remplir les bits vides

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

oups, désolé ce remplissage pour la saisie pas pour la clé –

8

Pour un cryptage de force clé plus forte vous devez télécharger Java Cryptography Extension (JCE) Politique de Compétence Force illimitée des fichiers.

http://java.sun.com/javase/downloads/index.jsp (Vérifier Autres téléchargements).

+0

J'ai téléchargé les jars supplémentaires, les ai ajoutés au projet, mais je reçois toujours l'exception ... – wuntee

+0

Vous ne les ajoutez pas au projet, ce sont des bibliothèques d'exécution . Le fichier README.txt indique que vous devez les installer dans votre dossier de sécurité d'exécution (écraser les fichiers) Si vous utilisez JDK alors:/chemin/vers/jdk/jre/libs/security/ Si vous utilisez JRE à la place :/chemin/vers/jre/libs/security/ –

+0

Cela a-t-il résolu votre question? –

-1

Quand je place le code suivant et l'exécuter, je ne reçois aucune exception:

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); 
    } 
} 

Je n'ai jamais pu recréer l'exception que vous aviez. Je cours J2SE 1.6 et développe sur Eclipse.

Se pourrait-il que votre mot de passe ne soit pas long de 16 octets?

+0

Un mot de passe n'est pas une clé. L'utilisateur utilisait correctement une fonction de dérivation de clé basée sur un mot de passe (PBKDF). Vous avez supprimé la protection requise. Astuce: il existe une exception générale: GeneralSecurityException, et normalement vous la lancez dans votre méthode ou vous créez une exception d'exécution (par exemple, une exception IllegalStateException si l'algorithme est introuvable). –

+0

Je n'ai retiré aucune protection. La méthode encrypt() appelle getSecretKey() qui appelle PBEKeySpec() tout comme l'OP dans son code d'origine. – Chopstick

2

Vous pouvez installer les jarres JCE Unlimited Strength, comme cela est suggéré pour plusieurs autres questions similaires, ou essayez simplement d'inclure ce code dans votre fonction ou pilote principal.

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

ne fonctionne pas dans Java 8 –

2

Le problème ici est la discordance entre les tailles de clé pour votre fonction de dérivation de clé et les chiffres donnés. Le PBKDF que vous utilisez est "PBEWithMD5AndDES" et dans cette chaîne, la partie DES indique le type de sortie. Comme simple DES comme il est connu utilise seulement 8 clés octets (64 bits, 56 bits de taille effective avec bits de parité). Les clés AES doivent être 128, 192 et 256 bits et ne doivent pas inclure de bits de parité.

Pour créer des tailles de clé de force AES, vous devez au moins utiliser PBKDF2 au lieu de PBKDF1, de préférence avec SHA-256 ou SHA-512 pour les tailles de clé plus élevées. Pour les clés de 128 bits, vous devez toutefois être en accord avec SHA-1. Donc, utilisez la construction dans "PBKDF2WithHmacSHA1"SecretKeyFactory à la place. Notez que PBKDF2/SHA1 avec des clés de plus de 160 bits entraînera un fonctionnement sous-optimal. Vous pouvez utiliser une fonction de dérivation de clé basée sur une clé simple (KBKDF) sur la sortie si vous souhaitez créer plus de données (par exemple une IV séparée).

Comme d'autres l'ont indiqué, si vous utilisez des clés de plus de 128 bits, vous aurez besoin des fichiers de juridiction crypto illimités.


Notes sur le code suivant:

  • Pas de protection de l'intégrité, que vous devrez peut-être même pour maintenir la confidentialité
  • CBC en utilisant un zéro IV, cela peut être OK, mais seulement si le sel est entièrement aléatoire (stocker le sel avec le texte chiffré)
  • 1024 est un nombre relativement faible d'itérations pour le PBKDF2
  • PBKDF2 est incompatible avec PBKDF1 que vous utilisiez
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); 
} 
Questions connexes