How to do AES Decryption in java - java

I tried AES encryption in javaScript and trying to decrypt in java with same algorithm and secretKey please anyone suggest
javaScript encryption
const cipher = crypto.createCipher('aes192','67f969129e2f78f2ee286d16efec0dad');
var encrypted = cipher.update('Hello JavaTpoint', 'utf8', 'base64');
encrypted += cipher.final('base64');
console.log(encrypted); // VABI2hVl2Ydqednr3K5tJv0VFKKiiFK3Jn3kinGxL7U=
encrypted base64 key : VABI2hVl2Ydqednr3K5tJv0VFKKiiFK3Jn3kinGxL7U=
java decryption
public static void main(String[] args) throws IOException, GeneralSecurityException, DocumentException, Exception {
byte[] array = Base64.getDecoder().decode("VABI2hVl2Ydqednr3K5tJv0VFKKiiFK3Jn3kinGxL7U=");
byte[] dec = decrypt(array, "67f969129e2f78f2ee286d16efec0dad");
System.out.println("content is :: dec " + new String(dec));
}
public static byte[] decrypt(byte[] input, String key) {
byte[] decrypted = null;
try {
System.out.println(new String(decodeHexString(key)));
SecretKeySpec skey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skey);
decrypted = cipher.doFinal(input);
} catch (Exception e) {
e.printStackTrace();
}
return decrypted;
}
getting error in java :
javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:991)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:847)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at com.sd.lambda.Decryption.decrypt(Decryption.java:84)
at com.sd.lambda.Decryption.main(Decryption.java:47)
Exception in thread "main" java.lang.NullPointerException
at java.lang.String.<init>(String.java:566)
at com.sd.lambda.Decryption.main(Decryption.java:50)
it should be decrypt and print "Hello JavaTpoint" in java console like this:
content is :: dec Hello JavaTpoint

When you are calling cipher.init() in the decrypt method, the IV is a necessary third parameter. Depending on how the original string is being encrypted will determine how you go about obtaining this value.
Here's a link to the init() method you'll want to use when setting up your decryption cipher:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/crypto/Cipher.html#init(int,java.security.Key,java.security.SecureRandom)

Related

javax.crypto.BadPaddingException: Decryption error : while doing only Decrypt to an already encypted string from DB

This error is already discussed in several links.
I got the similar kind of errors, But my scenario is little different than others.
I need
only Decryption. not Encryption.
In my case, an encrypted message is already stored in the DB. I got that as String and now need to only decrypt it to get the original String.
Any suggestions will be very helpful.
My piece of code is as follows:
String encodedStr = "c2J7RiP1CY++gfdE7Ke/xD1fSOOdO7DvprdZZUDws9Yl8DmYJV64zGV9vvK/TMEfALqSPH8KcZik8XvmLowpjJWzYY2Of1aytHaya0ULwmopklRWlkaS5sjL80jjyhaRN2O+zQNarbAQy8g3VtXX643T2AhDTsT+NKFsCcpH4xbqmViwD1GXQQLsLwuKZx1POAtyC0UaMjQ2SrzR+eVEiSgKPDABDKIRbOyBEXRcJMK/t/P7uIk9tJ/p1X2JqQOO7GMO/1x7rvF6Pb1Fik2tmQv5qL1W6/kV97/VT5Hpi9uh6zdCFO7sstYvgkxxbs3gTyJ5raWlATVU6a/0B/Q50w==";
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair pair = keyGen.generateKeyPair();
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
Cipher cipher = Cipher.getInstance("RSA");
// Encryption is not required.
//cipher.init(Cipher.ENCRYPT_MODE, privateKey);
//String ss =Base64.encodeBase64String(cipher.doFinal(encodedStr.getBytes("UTF-8")));
//System.out.println(ss);
// Only decryption is required.
cipher.init(Cipher.DECRYPT_MODE, publicKey);
String sss = new String(cipher.doFinal(Base64.decodeBase64(encodedStr)), "UTF-8");
System.out.println(sss);
And I'm getting below exception everytime at the line cipher.doFinal(Base64.decodeBase64(encodedStr) :
Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:383)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:294)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2164)
at com.sprint.neo.bc4j.util.TestMain.main(TestMain.java:20)
Though I don't require encryption, the Cipher.ENCRYPT_MODE is working fine.
But incase of Cipher.DECRYPT_MODE , it's throwing exception.
Please suggest me, how can I only decrypt an already existing encrypted String from DB, to get the original String value.
Here is the piece of code which works:
public static void main(String[] args) {
byte[] txt = "message".getBytes();
byte[] encText;
try{
// Load the keystore
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = "keystorePassword".toCharArray();
Key rsakey = ks.getKey("mykeyalias", password);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// Encrypt
Certificate cert = ks.getCertificate("mykeyalias");
try
{
cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey());
encText = cipher.doFinal(txt);
System.out.println(encText.toString());
}
catch (Throwable e)
{
e.printStackTrace();
return;
}
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, rsakey);
String decrypted = new String(cipher.doFinal(encText));
System.out.println(decrypted);
} catch (Exception e) {
System.out.println("error" + e);
}
}
Your publicKey generated will be different each time and hence the encrypted String will be different. The string generated will no longer be valid for decryption.
Try to read key secret from a file and use same encrypted string to decrypt.

javax.crypto.IllegalBlockSizeException upon decryption

the current decryption algorithm I wrote goes as follows,
public String decrypt(String enc) throws Exception
{
Key key = k;
Cipher crypt = Cipher.getInstance("AES");
crypt.init(Cipher.DECRYPT_MODE,key);
byte[] decrypt = crypt.doFinal(enc.getBytes());
return new String(decrypt);
}
The error that I get is at the line
byte[] decrypt = crypt.doFinal(enc.getBytes());
I have seen similar questions as this posted, but I am using a 128 bit key, so I am pretty certain there is no padding.
This is how I generate the key
public static SecretKey getKey() throws Exception
{
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
return keyGen.generateKey();
}
Additionally, decoding using base64 gives the same exact error
public String decrypt(String enc) throws Exception
{
Key key = k;
Cipher crypt = Cipher.getInstance("AES");
crypt.init(Cipher.DECRYPT_MODE,key);
byte[] decrypt = crypt.doFinal(Base64.getMimeDecoder().decode(enc));
return new String(decrypt);
}
public String decrypt(String enc)
The problem has already happened by the time you get here. The problem is that you are passing around ciphertext in a String. String isn't a container for binary data. Use a byte[].

Java AES Decryption: random chars & message at the end

I have a problem with decrypting a message using AES. At the end when I expect a message, e.g.
ala123
Instead of that I receive sth like:
...6�b}\7�k�8�vFP�8~%��_zժF��FW��O_e���ó������������ala123
The message I pass to encryption is built as:
cipher key is SHA-256 from AES_TOKEN
cipher IV is some characters, which are then stored in the message (at the beginnig)
decrypted message is wrapped up into Base64
The question is why at the end I eventually receive my expected message, but with a lot of rubbish chars at the beggining?
My encryption code is:
private static final String AES_TOKEN = "my_very_secret_token";
// encrypted is base64 string
public String decrypt(String encrypted) throws Exception {
byte[] decrypted = Base64.getDecoder().decode(encrypted);
return new String(aesDecrypt(decrypted), "UTF-8");
}
private byte[] aesDecrypt(byte[] message) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] token = MessageDigest.getInstance("SHA-256").digest(AES_TOKEN.getBytes());
SecretKeySpec secretKey = new SecretKeySpec(token, "AES");
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOf(message, 16));
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
return cipher.doFinal(message);
}
It looks like you aren't removing the IV from the beginning of message after reading it in to iv. That would explain the garbage being at the start of the decrypted message.

JAVA: AES Decryption

I'm currently running into problems decrypting my data. The base64 of the encoded string is being stored in the database. So, I'm printing out the encoded string and then trying to run it back through with "DECRYPT" instead of "ENCRYPT". However, I never get a value that the Decrypter method likes, it always gives me an error about parameters or the value not being 16 bytes.
public class crypto {
public static void main(String [] args) {
String s = args[0];
String s1 = args[1];
String ivkey = "thisisasecretkey";
byte[] ivraw = ivkey.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(ivraw, "AES");
if (s.equalsIgnoreCase("ENCRYPT")) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(s1.getBytes());
System.out.println(new String(Base64.encodeBase64(encrypted)));
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(s1.getBytes());
System.out.println(new String(Base64.decodeBase64(encrypted)));
} catch (Exception e) {
e.printStackTrace();
}
}
return;
};
}
command:crypto "ENCRYPT" "password"
output: 5eQvSzPG1TE2AybgCmeV6A==
command:crytpo "DECRYPT" "5eQvSzPG1TE2AybgCmeV6A=="
output: java.security.InvalidKeyException: Parameters missing
I'm aware of the security flaws, that's not what I'm asking about and I would prefer answers/comments not get cluttered with best practices.
You should do base 64 decoding, and you should do that before decrypting.
You are not including the initialization vector (IV).
AES in CBC mode has both a 16 byte IV and the 16 byte symmetric key.
String IV = "AAAAAAAAAAAAAAAA"; // generate this randomly
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(IV.getBytes()));
byte[] encrypted = cipher.doFinal(s.getBytes());
Edit: as it turns out, encryption does not require a IV to be provided (as owlstead pointed out), but decryption does. The best bet would be to be explicit and use IV in both encryption and decryption. Change your decryption function to include the IV, and you will run into the other error in your code that owlstead pointed out.

Convertion of PHP encryption and decryption methods into java

I tried to convert the encrypt and decrypt functions to use in Java for the below PHP. But received illegal key size error. Suggest me to do 256bit AES decryption in java.
PHP Code
<?php
function encrypt ($data,$salt) {
$hash = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($salt), $data, MCRYPT_MODE_CBC, md5(md5($salt))));
return $hash;
}
function decrypt ($encdata,$salt) {
$string = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($salt), base64_decode($encdata), MCRYPT_MODE_CBC, md5(md5($salt)));
return $string;
}
?>
Converted Java Code:
//The below code found in http://www.logikdev.com/2010/11/01/encrypt-with-php-decrypt-with-java/
public static String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
return number.toString(16);
}
public String decrypt(String encryptedData) {
String decryptedData = null;
try {
SecretKeySpec skeySpec = new SecretKeySpec(md5("5A17K3Y").getBytes(), "AES");
String initialVectorString=md5(md5("5A17K3Y"));
IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding","SunJCE");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
encryptedData=encryptedData.replace('-','+').replace('_','/').replace(',','=');
byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode((encryptedData.getBytes()));
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
decryptedData = new String(decryptedByteArray, "UTF8");
} catch (Exception e) {
System.out.println("Error. Problem decrypting the data: " + e);
}
}
Problem decrypting the data: java.security.InvalidKeyException: Illegal key size
You receive an illegal key size error when you've not installed the unlimited strength jurisdiction files. These files permit Java to use stronger key lengths (for example 256-bit AES).
Go to the Oracle download site and hunt for the files that match your Java version. If it is legal in your country to do so, install these files and enjoy stronger crypto.
(Side note: did you research this at all? The first upteem results would have answered your issue).

Categories

Resources