I would like to encrypt and decrypt a password using 128 bit AES encryption with 16 byte key. I am getting javax.crypto.BadPaddingException
error while decrypting the value. Am I missing anything while decrypting?
public static void main(String args[]) {
Test t = new Test();
String encrypt = new String(t.encrypt("mypassword"));
System.out.println("decrypted value:" + t.decrypt("ThisIsASecretKey", encrypt));
}
public String encrypt(String value) {
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + (new String(encrypted)));
return new String(skeySpec.getEncoded());
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(skeySpec.getEncoded(), "AES"));
//getting error here
byte[] original = cipher.doFinal(encrypted.getBytes());
return new String(original);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Error message
encrypted string:?Bj?.?Ntk?F?`?
encrypted key:ThisIsASecretKey
decrypted value:null
May 25, 2012 12:54:02 PM bean.Test decrypt
SEVERE: null
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at bean.Test.decrypt(Test.java:55)
at bean.Test.main(Test.java:24)
Finally I am using following Solution based on @QuantumMechanic answer
public class Test {
public String encryptionKey;
public static void main(String args[]) {
Test t = new Test();
String encrypt = t.encrypt("mypassword");
System.out.println("decrypted value:" + t.decrypt(t.encryptionKey, encrypt));
}
public String encrypt(String value) {
try {
// Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(256);
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
String key = new Base64().encodeAsString(raw);
this.encryptionKey = key;
System.out.println("------------------Key------------------");
System.out.println(key);
System.out.println("--------------End of Key---------------");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
String encrypt = (new Base64()).encodeAsString(cipher.doFinal(value.getBytes()));
System.out.println("encrypted string:" + encrypt);
return encrypt;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
Key k = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, k);
byte[] decodedValue = Base64.getDecoder().decode(encrypted);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
This question is related to
java
aes
encryption
Here is the implementation that was mentioned above:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
try
{
String passEncrypt = "my password";
byte[] saltEncrypt = "choose a better salt".getBytes();
int iterationsEncrypt = 10000;
SecretKeyFactory factoryKeyEncrypt = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
SecretKey tmp = factoryKeyEncrypt.generateSecret(new PBEKeySpec(
passEncrypt.toCharArray(), saltEncrypt, iterationsEncrypt,
128));
SecretKeySpec encryptKey = new SecretKeySpec(tmp.getEncoded(),
"AES");
Cipher aesCipherEncrypt = Cipher
.getInstance("AES/ECB/PKCS5Padding");
aesCipherEncrypt.init(Cipher.ENCRYPT_MODE, encryptKey);
// get the bytes
byte[] bytes = StringUtils.getBytesUtf8(toEncodeEncryptString);
// encrypt the bytes
byte[] encryptBytes = aesCipherEncrypt.doFinal(bytes);
// encode 64 the encrypted bytes
String encoded = Base64.encodeBase64URLSafeString(encryptBytes);
System.out.println("e: " + encoded);
// assume some transport happens here
// create a new string, to make sure we are not pointing to the same
// string as the one above
String encodedEncrypted = new String(encoded);
//we recreate the same salt/encrypt as if its a separate system
String passDecrypt = "my password";
byte[] saltDecrypt = "choose a better salt".getBytes();
int iterationsDecrypt = 10000;
SecretKeyFactory factoryKeyDecrypt = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
SecretKey tmp2 = factoryKeyDecrypt.generateSecret(new PBEKeySpec(passDecrypt
.toCharArray(), saltDecrypt, iterationsDecrypt, 128));
SecretKeySpec decryptKey = new SecretKeySpec(tmp2.getEncoded(), "AES");
Cipher aesCipherDecrypt = Cipher.getInstance("AES/ECB/PKCS5Padding");
aesCipherDecrypt.init(Cipher.DECRYPT_MODE, decryptKey);
//basically we reverse the process we did earlier
// get the bytes from encodedEncrypted string
byte[] e64bytes = StringUtils.getBytesUtf8(encodedEncrypted);
// decode 64, now the bytes should be encrypted
byte[] eBytes = Base64.decodeBase64(e64bytes);
// decrypt the bytes
byte[] cipherDecode = aesCipherDecrypt.doFinal(eBytes);
// to string
String decoded = StringUtils.newStringUtf8(cipherDecode);
System.out.println("d: " + decoded);
}
catch (Exception e)
{
e.printStackTrace();
}
Complete example of encrypting/Decrypting a huge video without throwing Java OutOfMemoryException
and using Java SecureRandom
for Initialization Vector generation. Also depicted storing key bytes to database and then reconstructing same key from those bytes.
Try this, a simpler solution.
byte[] salt = "ThisIsASecretKey".getBytes(); Key key = new SecretKeySpec(salt, 0, 16, "AES"); Cipher cipher = Cipher.getInstance("AES");
import javax.crypto.*;
import java.security.*;
public class Java {
private static SecretKey key = null;
private static Cipher cipher = null;
public static void main(String[] args) throws Exception
{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
KeyGenerator keyGenerator =
KeyGenerator.getInstance("DESede");
keyGenerator.init(168);
SecretKey secretKey = keyGenerator.generateKey();
cipher = Cipher.getInstance("DESede");
String clearText = "I am an Employee";
byte[] clearTextBytes = clearText.getBytes("UTF8");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherBytes = cipher.doFinal(clearTextBytes);
String cipherText = new String(cipherBytes, "UTF8");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedBytes = cipher.doFinal(cipherBytes);
String decryptedText = new String(decryptedBytes, "UTF8");
System.out.println("Before encryption: " + clearText);
System.out.println("After encryption: " + cipherText);
System.out.println("After decryption: " + decryptedText);
}
}
// Output
/*
Before encryption: I am an Employee
After encryption: }????j6??m??Zyc????*????l#l??dV
After decryption: I am an Employee
*/
You state that you want to encrypt/decrypt a password. I'm not sure exactly of what your specific use case is but, generally, passwords are not stored in a form where they can be decrypted. General practice is to salt the password and use suitably powerful one-way hash (such as PBKDF2).
Take a look at the following link for more information.
Source: Stackoverflow.com