Je travaille sur un projet cryptage et décryptage de texte (suite à Struts 2)
Chaque fois que je saisis le mot de passe et le texte brut, une erreur de longueur de clé AES non valide apparaît.
La classe de service
package com.anoncrypt.services;
import Java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import Sun.misc.BASE64Decoder;
import Sun.misc.BASE64Encoder;
public class SymAES
{
private static final String ALGORITHM = "AES";
private static byte[] keyValue= new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };
public String encode(String valueToEnc) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
String encryptedValue = new BASE64Encoder().encode(encValue);
return encryptedValue;
}
public String decode(String encryptedValue) throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
public void start(String passcode)throws Exception
{
keyValue = passcode.getBytes();
}
}
Et c'est l'erreur
Java.security.InvalidKeyException: Invalid AES key length: 6 bytes
com.Sun.crypto.provider.AESCrypt.init(AESCrypt.Java:87)
com.Sun.crypto.provider.ElectronicCodeBook.init(ElectronicCodeBook.Java:93)
com.Sun.crypto.provider.CipherCore.init(CipherCore.Java:582)
com.Sun.crypto.provider.CipherCore.init(CipherCore.Java:458)
com.Sun.crypto.provider.AESCipher.engineInit(AESCipher.Java:307)
javax.crypto.Cipher.implInit(Cipher.Java:797)
javax.crypto.Cipher.chooseProvider(Cipher.Java:859)
javax.crypto.Cipher.init(Cipher.Java:1229)
javax.crypto.Cipher.init(Cipher.Java:1166)
com.anoncrypt.services.SymAES.encode(SymAES.Java:35)
com.anoncrypt.actions.SymEncrypt.execute(SymEncrypt.Java:24)
SecretKeySpec
attend une clé, pas un mot de passe. Voir ci-dessousLe problème est le numéro 1: vous passez le mot de passe au lieu de la clé.
AES prend uniquement en charge les tailles de clé de 16, 24 ou 32 octets. Soit vous devez fournir exactement ce montant, soit vous extrayez la clé de votre saisie.
Il existe différentes manières de dériver la clé d'une phrase secrète. Java fournit une implémentation PBKDF2 à cette fin.
J'ai utilisé erickson answer pour dessiner une image complète (cryptage uniquement, car le décryptage est similaire, mais inclut le fractionnement du texte crypté):
SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 65536, 256); // AES-256
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] key = f.generateSecret(spec).getEncoded();
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
byte[] ivBytes = new byte[16];
random.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] encValue = c.doFinal(valueToEnc.getBytes());
byte[] finalCiphertext = new byte[encValue.length+2*16];
System.arraycopy(ivBytes, 0, finalCiphertext, 0, 16);
System.arraycopy(salt, 0, finalCiphertext, 16, 16);
System.arraycopy(encValue, 0, finalCiphertext, 32, encValue.length);
return finalCiphertext;
Autres choses à garder à l'esprit:
AES
n'est pas approprié dans ce cas, car différents fournisseurs JVM/JCE peuvent utiliser des valeurs par défaut différentes pour le mode d'opération et le remplissage. Utilisez AES/CBC/PKCS5Padding
. N'utilisez pas le mode ECB, car il n'est pas sécurisé sur le plan sémantique.cipherInstance.getIV()
.Vous pouvez vérifier la limite de longueur de clé:
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("MaxAllowedKeyLength=[" + maxKeyLen + "].");
Je faisais face à la même chose alors j'ai fait ma clé 16 octets et cela fonctionne correctement maintenant. Créez votre clé exactement 16 octets. Cela fonctionnera sûrement.