Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Exception java.security.InvalidKeyException: Invalid AES key length: 29 bytes?

When running below programme i am getting this exception. Not able to figure out what the issue as AES allows the 128 -256 bit key?

 Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 29 bytes
at com.sun.crypto.provider.AESCipher.engineGetKeySize(DashoA13*..)
at javax.crypto.Cipher.b(DashoA13*..)

Getting exception at line 20

Here is the programme

 import java.security.Key;

 import javax.crypto.Cipher;
 import javax.crypto.spec.SecretKeySpec;

 import sun.misc.BASE64Decoder;
 import sun.misc.BASE64Encoder;

 public class AESEncryptionDecryptionTest {

   private static final String ALGORITHM       = "AES";
   private static final String myEncryptionKey = "ThisIsSecurityKey";
   private static final String UNICODE_FORMAT  = "UTF8";

   public static String encrypt(String valueToEnc) throws Exception {
 Key key = generateKey();
 Cipher c = Cipher.getInstance(ALGORITHM);
 c.init(Cipher.ENCRYPT_MODE, key);  //////////LINE 20
 byte[] encValue = c.doFinal(valueToEnc.getBytes());
 String encryptedValue = new BASE64Encoder().encode(encValue);
 return encryptedValue;
   }

public static String decrypt(String encryptedValue) throws Exception {
Key key = generateKey();
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;
}

private static Key generateKey() throws Exception {
byte[] keyAsBytes;
keyAsBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
Key key = new SecretKeySpec(keyAsBytes, ALGORITHM);
return key;
}

public static void main(String[] args) throws Exception {

String value = "password1";
String valueEnc = AESEncryptionDecryptionTest.encrypt(value);
String valueDec = AESEncryptionDecryptionTest.decrypt(valueEnc);

System.out.println("Plain Text : " + value);
System.out.println("Encrypted : " + valueEnc);
System.out.println("Decrypted : " + valueDec);
}

}
like image 498
M Sach Avatar asked May 31 '12 10:05

M Sach


People also ask

What is valid AES key length?

Advanced Encryption Standard (AES) keys are symmetric keys that can be three different key lengths (128, 192, or 256 bits). AES is the encryption standard that is recognized and recommended by the US government. The 256-bit keys are the longest allowed by AES.

What key length does AES not support?

Although AES key lengths – 128, 192, and 256 bits – may change, the block size of the data encrypted with AES is always 128 bits in size. Out of 128-bit, 192-bit, and 256-bit AES encryption, which progressively use more rounds of encryption for improved security, 128-bit AES encryption is technically the least secure.

What is InvalidKeyException in Java?

public class InvalidKeyException extends KeyException. This is the exception for invalid Keys (invalid encoding, wrong length, uninitialized, etc).

Does Java support AES 256?

Here padding is required and Java provides 3 alternatives. For encoding, the AES algorithm is repetitive in nature and supports 128, 192, and 256 bits.


2 Answers

AES allows 128, 192 or 256 bit key length. That is 16, 24 or 32 byte. Try taking just the first 16 bytes of your mEncryptionKey as the keyAsBytes.

Edit:
An after though occurred to me. A habit I have formed, and one which I recommend, is to take a SHA hash of a password/passphrase, and use that as the source bytes of your key. Taking a hash guarantees the key data will be the correct size, irrespective of the length of the password/passphrase. Your current implementation of using the String bytes has two problems;

  • It will break your key generation if someone uses a short password.
  • Two different passwords for which the first 16 bytes are the same will create the same key.

Both of these problems are eliminated by using a hash.

Take a look at the buildKey() method in this class; https://github.com/qwerky/DataVault/blob/master/src/qwerky/tools/datavault/DataVault.java

like image 127
Qwerky Avatar answered Sep 24 '22 14:09

Qwerky


The key uses randomness as input, but there are stiill requirements for how it is composed. The SecretKeySpec constructor you used is for loading an already generated key into memory. Instead, use KeyGenerator.

KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
kg.init(128);
SecretKey k = kg.generateKey();

Also note that AES-128 is now actually thought to be weaker than AES-256. It probably isn't drastically different but the benefit from the longer key size may be outweighed by simplifications elsewhere (fewer rounds).

like image 37
John Watts Avatar answered Sep 23 '22 14:09

John Watts