I am working on a text encryption and decryption project (following Struts 2)
Whenever I enter the password and the plain text I get a Invalid AES Key Length error.
The Service Class
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();
}
}
And this is the error
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)
This question is related to
java
encryption
aes
SecretKeySpec
expects a key, not a password. See belowThe problem is number 1: you are passing the password instead of the key.
AES only supports key sizes of 16, 24 or 32 bytes. You either need to provide exactly that amount or you derive the key from what you type in.
There are different ways to derive the key from a passphrase. Java provides a PBKDF2 implementation for such a purpose.
I used erickson's answer to paint a complete picture (only encryption, since the decryption is similar, but includes splitting the ciphertext):
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;
Other things to keep in mind:
AES
is not appropriate in such a case, because different JVMs/JCE providers may use different defaults for mode of operation and padding. Use AES/CBC/PKCS5Padding
. Don't use ECB mode, because it is not semantically secure.cipherInstance.getIV()
.You can use this code, this code is for AES-256-CBC or you can use it for other AES encryption. Key length error mainly comes in 256-bit encryption.
This error comes due to the encoding or charset name we pass in the SecretKeySpec. Suppose, in my case, I have a key length of 44, but I am not able to encrypt my text using this long key; Java throws me an error of invalid key length. Therefore I pass my key as a BASE64 in the function, and it converts my 44 length key in the 32 bytes, which is must for the 256-bit encryption.
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.Security;
import java.util.Base64;
public class Encrypt {
static byte [] arr = {1,2,3,4,5,6,7,8,9};
// static byte [] arr = new byte[16];
public static void main(String...args) {
try {
// System.out.println(Cipher.getMaxAllowedKeyLength("AES"));
Base64.Decoder decoder = Base64.getDecoder();
// static byte [] arr = new byte[16];
Security.setProperty("crypto.policy", "unlimited");
String key = "Your key";
// System.out.println("-------" + key);
String value = "Hey, i am adnan";
String IV = "0123456789abcdef";
// System.out.println(value);
// log.info(value);
IvParameterSpec iv = new IvParameterSpec(IV.getBytes());
// IvParameterSpec iv = new IvParameterSpec(arr);
// System.out.println(key);
SecretKeySpec skeySpec = new SecretKeySpec(decoder.decode(key), "AES");
// System.out.println(skeySpec);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// System.out.println("ddddddddd"+IV);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
// System.out.println(cipher.getIV());
byte[] encrypted = cipher.doFinal(value.getBytes());
String encryptedString = Base64.getEncoder().encodeToString(encrypted);
System.out.println("encrypted string,,,,,,,,,,,,,,,,,,,: " + encryptedString);
// vars.put("input-1",encryptedString);
// log.info("beanshell");
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
I was facing the same issue then i made my key 16 byte and it's working properly now. Create your key exactly 16 byte. It will surely work.
You can verify the key length limit:
int maxKeyLen = Cipher.getMaxAllowedKeyLength("AES");
System.out.println("MaxAllowedKeyLength=[" + maxKeyLen + "].");
Source: Stackoverflow.com