I am trying to write a class that will encrypt/decrypt text using AES.
I want to generate a key, store the key in a database column and use that key to encrypt/decrypt corresponding text in the database row containing the key.
The following is the class that I wrote to generate the key and do encryption and decryption tasks.
import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; public class StringDecryptor { public static String encrypt(String text, String key) { Key aesKey = null; Cipher cipher = null; byte[] encrypted = null; try { aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, aesKey); encrypted = cipher.doFinal(text.getBytes()); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalBlockSizeException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (UnsupportedEncodingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } return new String(encrypted); } public static String decrypt(String text, String key) { Key aesKey = null; Cipher cipher; String decrypted = null; try { aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, aesKey); decrypted = new String(cipher.doFinal(text.getBytes())); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeyException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalBlockSizeException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (BadPaddingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } catch (UnsupportedEncodingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } return decrypted; } public static String generateKey() { SecretKey secretKey = null; try { secretKey = KeyGenerator.getInstance("AES").generateKey(); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } String keyString = bytesToString(secretKey.getEncoded()); return keyString; } public static String bytesToString(byte[] b) { String decoded = null; try { decoded = new String(b, "UTF-8"); } catch (UnsupportedEncodingException ex) { Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); } return decoded; } public static void main(String args[]) { String key = generateKey(); System.out.println("key: " + key); String str = "This is the original string..."; String enc = encrypt(str, key); System.out.println("enc: " + enc); String dec = decrypt(enc, key); System.out.println("dec: " + dec); } }This code is throwing the following exception.
SEVERE: null java.security.InvalidKeyException: Invalid AES key length: 26 bytes at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372) at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052) at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010) at javax.crypto.Cipher.implInit(Cipher.java:786) at javax.crypto.Cipher.chooseProvider(Cipher.java:849) at javax.crypto.Cipher.init(Cipher.java:1213) at javax.crypto.Cipher.init(Cipher.java:1153) at com.innolabmm.software.luckydraw.utils.StringDecryptor.encrypt(StringDecryptor.java:27) at com.innolabmm.software.luckydraw.utils.StringDecryptor.main(StringDecryptor.java:95) Exception in thread "main" java.lang.NullPointerException at java.lang.String.<init>(String.java:556) at com.innolabmm.software.luckydraw.utils.StringDecryptor.encrypt(StringDecryptor.java:42) at com.innolabmm.software.luckydraw.utils.StringDecryptor.main(StringDecryptor.java:95) Java Result: 1Is there any way to generate a key string that does not cause the AES key conversion to throw exceptions?
To be able to encrypt with the AES-algorithm you will need to base your key on an atleast 128bit String. (Other values are also legal, but I don't have them in my head)
To convert that into number of characters needed in your provided key-string you can take 128 divided by 8
128 / 8 = 16 alpha-numeric charactersThis should solve your problem.
EDIT:Answer on comment about BASE64: BASE64 is a different way of encoding a string. The result of a BASE64-encoding may be a 128bit string, but not by default. There is not actually a default length of the outcome of a BASE64-encoding. The result may be 8 characters or 512, or some other output that conforms with the encoding rules of BASE64, it all depends on the string you are encoding.