There are a lot of threads on stack overflow with this topic, and always the same solutions, but these doesn't work for me. I am looking for a way to decrypt the value byte[] encrypted and return byte[] decodedBytes.
With the method AESCrypt. I use compile 'com.scottyab:aescrypt:0.0.1'
private void testAES() {
try {
final byte[] encrypted = Base64.decode("R3JhbmRlIFZpY3RvaXJlICE=", Base64.NO_WRAP);
byte[] keyBytes = Base64.decode("L/91ZYrliXvmhYt9FKEkkDDni+PzcnOuV9cikm188+4=", Base64.NO_WRAP);
final byte[] ivBytes = Base64.decode("gqjFHI+YQiP7XYEfcIEJHw==".getBytes(), Base64.NO_WRAP);
final SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
byte[] decodedBytes = AESCrypt.decrypt(keySpec, ivBytes, encrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
With the value Cipher, i use it like that.
private static byte[] testCipher() {
try {
final byte[] encrypted = Base64.decode("R3JhbmRlIFZpY3RvaXJlICE=", Base64.NO_WRAP);
byte[] keyBytes = Base64.decode("L/91ZYrliXvmhYt9FKEkkDDni+PzcnOuV9cikm188+4=", Base64.NO_WRAP);
byte[] ivBytes = Base64.decode("gqjFHI+YQiP7XYEfcIEJHw==".getBytes(), Base64.NO_WRAP);
final IvParameterSpec ivSpecForData = new IvParameterSpec(ivBytes);
SecretKeySpec decodedKeySpec = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, decodedKeySpec, ivSpecForData);
byte[] decodedBytes = cipher.doFinal(encrypted); // I have the error here //
return decodedBytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Whatever i do, i allways have the same error :
error:1e06b07b:Cipher functions:EVP_DecryptFinal_ex:WRONG_FINAL_BLOCK_LENGTH
I try to put in Cipher.getInstance (AES/CBC/NoPadding, AES/CBC/PKCS5Padding, AES/CBC/PKCS7Padding) but nothing change.
Do you have any idea to help me ?
"R3JhbmRlIFZpY3RvaXJlICE=" decoded to 17 hex bytes 4772616E646520566963746F6972652021 which is the ASCII text: "Grande Victoire !".
17 bytes is not a valid size for AES which is a block cipher that requires encrypted data to be a multiple of the block size of 16-bytes.
There is no encryption just Base64 encoding.
Related
I have a c# code which does the encryption and a java code which decrypt, but in Java I get
"Given final block not properly padded. Such issues can arise if a bad key is used during decryption".
But if I encrypt in JAVA and decrypt in JAVA , it works fine. Please help I am stuck since a week.
I read PKCS5Padding and PKCS7Padding both are same in JAVA, is it true?
to try with PKCS7Padding in Java, I used bouncy Castle but that gave below error
" BadPaddingException: pad block corrupted"
C# Encryption Logic:
string Encrypt(string textToEncrypt, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
return Convert.ToBase64String(transform.TransformFinalBlock(plainText, 0, plainText.Length));
}
Java Decryption Logic
public String decryptInputData(String encryptedRequest, String key1) {
byte[] cipherData = Base64.getDecoder().decode(encryptedRequest);
byte[] keyByte = key1.getBytes(StandardCharsets.UTF_8);
byte[] IV=new byte[16];
SecretKeySpec key = new SecretKeySpec(keyByte, "AES");
IvParameterSpec iv = new IvParameterSpec(IV);
Cipher aesCBC;
try {
aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding");
aesCBC.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decryptedData = aesCBC.doFinal(cipherData);
return new String(decryptedData, StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException | NoSuchPaddingException |InvalidKeyException | InvalidAlgorithmParameterException |IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
Test Data:
arxtiUWLzv5W74mDyRDxIWGM5C40kTiHocBYD9xfpvqYi7bkWIfO7jba1PdRaSCN31CwD18UGVRa2WVGDlt9LCkFuU2ErWFrboKC11OHFuozznF8ZAm1e6kSiSR/QfH1bhLONkClWruzDcTONA7BobZQd86LuPJe5BlAqYcaZq2DTXRmP11IZFzZP7+3cnk+oxF/H15hz+ypw7u0JMHQirg5C8aGD5DjmuLcsGcMjHNoaQ9cOrzjCOK8zpgGGDo9T5libP1h1GsaBYmdNp21auwLbebO8BzwFJGzD2fiybT5MswZpdtxE4Hh9OtgjZwSRFeBW10e2v/EQR6Qeffumgp93u109gOtYdc+HmAjFeu645JsNHON2EpqBJ/I8tfcdYWpJMVkS8h0nEd5QbWMN1/B+Rk42UmAAFoeyo2YgVHJLDNAe2HnjiQv/RKuL/zjJEtTOdZZKIdHduPT32GtZGHzqCK3Gy/MlTd37zgSeUahE6pe3Zp0Cu+pinQgOY9oCaTdhVmH8xiYv33plcbsElXDW4zTusj68jkeCBpPFeW9DRxWLngooPqszCKrZ6EJFgdbpCdEanU79mJCflg8d7uqwntwTw6gGgOLNqK+OpvVTtvoZ9oBeIBOjB0NroP9edQkSbJw7vSdGMMiQODOqIosgXrecdmvpja3hoZ3RuHGkkieIwNm4CSoSrDQdDwSIMW5CXY9r5UZ8+Pf5KHx2UYU7RqcZa44Z32mP7n10g6gjCHYTi0FCf0HpFx7ykFHC8qEEptI+ywRm6Y+WR6NEO284UILOvwmJb7iyB3N8i32jYq+CIH7h8jYePHkX+eVdfiaC6JGWC5nrM+6pUB2tOMN4LIu+4Lvy9OIPCFAw/U+ze2B23t/SfUae7peKu3SeczQrP7BGAk4s5PYAh1gncZmNhmhVviqN8KkO44bH7eqGXpnIUqeswYRu4pJYFhfNkqtaSSWSD4q/slycVORyMjPKSDDp5shm1qIdui6lGI=
Key:TL3U2HAQJZ79F8O5X4CNW6S10IEKGPYB
PlainText:
Salutation=MRS|Customer_Name=ITMSYAR EBMEEN|Address=ABCD EFG~WERT|City=GHTTG|Pin_Code=310012|State=WERY|DOB=1900-02-19|Gender=F|Mobile_Number=010007000007|Nationality=IN|Email_Address=ABCDEFG#GMAIL.COM|Marital_Status=Y|Occupation_Type=Housewife|PAN_Number=AOIPM1619P|Nominee_Name=|Nominee_DOB=|Relationship_of_Nominee=|Timestamp=7/26/2022 11:06:16 AM|Website_Ref_No=1zEeSs97MAao5UIi|CRM_Lead_Id=9121421421|Source_Id=MB_LoggedIn|Referral_Code=123456|utm_source=|utm_medium=|utm_campaign=|Product_Name=Group Active Health Plan|Partner_Name=ABCD|SP_Code=|LG_SOL_ID=002|Producer_Code=202324134|EBCC_Flag=N|Scheme_Code=FSGSW|CKYC_NO=|Acc_No=1234567889|Acc_Type=Main|
I am developing an application, where I am encrypting and decrypting a text entered by the user.
But, I am getting the following error:
javax.crypto.IllegalBlockSizeException: last block incomplete in
decryption
below is my code for encryption and decryption. Encryption works perfectly, while I am getting this error while decrypting. Please refer the code below:
public static String fncEncrypt(String strClearText, String strKey) throws Exception{
String strData = "";
try {
SecretKeySpec sKeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
byte[] encrypted = cipher.doFinal(strClearText.getBytes());
strData = new String(encrypted);
}catch (Exception e){
e.printStackTrace();
}
return strData;
}
public static String fncDecrypt(String strEecrypted, String strKey) throws Exception {
String strData = "";
try {
SecretKeySpec skeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(strEecrypted.getBytes());
strData = new String(decrypted);
}catch (Exception e){
e.printStackTrace();
}
return strData;
}
Please respond if you have a solution for this.
You should decode the string instead of encoding the platform specific representation of the string, right at the start of your method.
byte[] base64TextToDecrypt = Base64.decodeBase64(textToDecrypt);
or more precisely:
byte[] bytesToDecrypt = Base64(base64TextToDecrypt);
if you name your variables correctly.
In general, each time you (feel like you have to) use the String.getBytes(): byte[] method or the String(byte[]) constructor you are likely doing something wrong. You should first think about what you are trying to do, and specify a character-encoding if you do need to use it.
In your case, the output in the converted variable is probably character-encoded. So you you could use the following fragment:
String plainText = new String(converted, Charset.forName("UTF8"));
System.out.println(plainText);
instead of what you have now.
Reference : https://stackoverflow.com/a/13274072/8416317
String class method getBytes() or new String(byte bytes[]) encode / decode with Charset.defaultCharset().name(), and some encrypted data would be ignored by encoding with special charset.
you could directly return byte[] by fncEncrypt and input byte[] to fncDecrypt. or encode result with BASE64.
public static byte[] fncEncrypt(String strClearText, String strKey) throws Exception{
byte[] encrypted = null;
try {
SecretKeySpec sKeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
encrypted = cipher.doFinal(strClearText.getBytes());
} catch (Exception e){
e.printStackTrace();
}
return encrypted;
}
public static String fncDecrypt(byte[] ecrypted, String strKey) throws Exception {
String strData = "";
try {
SecretKeySpec skeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(ecrypted);
strData = new String(decrypted);
}catch (Exception e){
e.printStackTrace();
}
return strData;
}
The reason is when you use new String(encrypted) it will not fully encode the bytes to string. Try the code below
public static byte[] fncEncrypt(String strClearText, String strKey) throws Exception{
SecretKeySpec sKeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
byte[] encrypted = cipher.doFinal(strClearText.getBytes());
return encrypted;
}
public static String fncDecrypt(byte[] encrypted, String strKey) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(strKey.getBytes(), "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted);
}
You can encrypt and decrypt using the code below
String message = "Hello!";
byte[] encrypted = fncEncrypt(message, "key");
String decrypted = fncDecrypt(encrypted, "key");
System.out.println(decrypted);
I am using the below code to create a 128 bit AES cipher,
String initializer = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
byte[] initializer2 = new BigInteger(initializer, 2).toByteArray();
String encrypt = encrypt(binary_string_firsthalf, initializer2);
public static String encrypt(String plainText, byte[] key) {
try {
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] cipherText = cipher.doFinal(plainText.getBytes("UTF8"));
String encryptedString = new String(Base64.encode(cipherText));
return encryptedString;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
But the code is returning a exception saying invalid AES key length.
How to create a cipher using 128 0's.
byte[] initializer2 = new byte[16];
is all you need to initialize a byte array with the default value of 0x00.
Don't use a static predictable key such as all 0x00 bytes for actual encryption.
I'm trying to do encryption-decryption of a String using AES/CBC/PKCS5Padding
I'm getting this Exception: javax.crypto.BadPaddingException: Given final block not properly padded
the string i'm trying to encrypt: ftp.clarapoint.com
Here is my encryption code:
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] data = cipher.doFinal(stringDec.getBytes());
byte[] iv = cipher.getIV();
I'm transfering the decryption method the following: aesKey, data and iv
the decryption code:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
AlgorithmParameters.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(iv));
byte[] decrypted = cipher.doFinal(data);
Thanks!
You are not transfering either the key or the cipher text correctly, as this code does run:
private static void testCode() {
try {
String stringDec = "Hi there";
SecretKey aesKey = new SecretKeySpec(new byte[16], "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
// no encoding given, don't use getBytes() without a Charset.forName("UTF-8")
byte[] data = cipher.doFinal(stringDec.getBytes());
byte[] iv = cipher.getIV();
// doesn't do anything
AlgorithmParameters.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey, new IvParameterSpec(iv));
byte[] decrypted = cipher.doFinal(data);
System.out.println(new String(decrypted));
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
}
}
This is the code for encrypting and decrypting a string in java using AES algorithm. Its throwing illegalblocksize exception while decrypting.
I know it is occuring because length of input string to the decryption method isn't matching with the padding. I don't have an idea of how to solve this.
I am a new bie to the encryption decryption. Plz help me....
StackTrace:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
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 test.AES.AESdecryptalgo(AES.java:76)
at test.AES.main(AES.java:95)
Code:
package test;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.security.*;
public class AES
{
public byte[] encrypted;
public byte[] original;
public String originalString;
Cipher cipher;
SecretKeySpec skeySpec;
IvParameterSpec spec;
byte [] iv;
/*public static String asHex (byte buf[])
{
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}*/
public AES()
{
try
{
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
skeySpec = new SecretKeySpec(raw, "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
}
catch(Exception ex)
{ex.printStackTrace();}
}
public String AESencryptalgo(byte[] text)
{
String newtext="";
try
{
// byte[] raw = skey.getEncoded();
//SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
AlgorithmParameters param = cipher.getParameters();
IvParameterSpec ivspec=param.getParameterSpec(IvParameterSpec.class);
iv=ivspec.getIV();
spec=new IvParameterSpec(iv);
//AlgorithmParameters params = cipher.getParameters();
//iv = params.getParameterSpec(IvParameterSpec.class).getIV();
encrypted = cipher.doFinal(text);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
newtext=new String(encrypted);
//System.out.println("ENCRYPTED "+newtext);
return newtext;
}
}
public String AESdecryptalgo(byte[] text)
{
try
{
cipher.init(Cipher.DECRYPT_MODE, skeySpec,spec);
original = cipher.doFinal(text); //Exception occurs here
originalString = new String(original);
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
return originalString;
}
}
public static void main(String[] args)
{
AES a=new AES();
String encrypt=a.AESencryptalgo("hello".getBytes());
System.out.println(encrypt);
String decrypt=a.AESdecryptalgo(encrypt.getBytes());
System.out.println(decrypt);
}
}`
You have to provide an initialization vector when using CBC mode.
When encrypting, let the provider choose the IV for you:
…
cipher.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
…
Later, when decrypting, use the same IV to initialize the cipher:
…
IvParameterSpec spec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
…
You must change AESencryptalgo to return byte[] rather than a String. This is where the trouble begins:
newtext = new String(encrypted);
// System.out.println("ENCRYPTED "+newtext);
return newtext;
After changing the return type of the method, you should make the following change:
//newtext = new String(encrypted);
// System.out.println("ENCRYPTED "+newtext);
//return newtext;
return encrypted;
The problem is that a String is a sequence of characters, whereas the encrypted text is a sequence of bytes (for a good summary of this difference, see The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)).
When you try to construct a String from a byte array, Java tries its best to convert those bytes into characters, using the system's default character set. Unfortunately, this mapping doesn't always work successfully (typically when the encrypted bytes fall outside the ASCII character set). You will only ever notice the problem when it comes time to decrypt your new String (which will fail to properly convert the sequence of characters back into the original sequence of bytes).