So I'm using a simple Blowfish encryption/decryption for an application I'm making. It works sometimes but isn't reliable.
Form template being encrypted:
email#gmail.com
message
END
It works perfectly when I use an email like test1#gmail.com or test2#gmail.com.
When I use my personal email: tywemc#gmail.com, the form is encrypted but when it's decrypted, it returns î/ÅÝ®Îmail.comÄþ4œ’>L/ND
So it seems like it decrypts part of the form but not the whole thing and I can't figure out why. It seems to decrypts other forms partially with different real emails but still not completely. I'm using a static key within the Crypto.java class for simplicity.
I've tried to make sure the longer emails were causing it to not work because of a block size or string length issue but I don't think that's the problem.
Crypto.java
package core;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private static String key = "key12345";
public static String encrypt(String strClearText,String strKey) {
String strData = "";
try {
SecretKeySpec skeyspec = new SecretKeySpec(key.getBytes(), "Blowfish");
System.out.println("Ëncryption keyspec: " + skeyspec.toString());
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 decrypt(String strEncrypted,String strKey) {
String strData = "";
try {
SecretKeySpec skeyspec = new SecretKeySpec(key.getBytes(),"Blowfish");
System.out.println("Decryption keyspec: " + skeyspec.toString());
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeyspec);
byte[] decrypted = cipher.doFinal(strEncrypted.getBytes());
strData = new String(decrypted);
} catch (Exception e) {
e.printStackTrace();
}
return strData;
}
}
Should I use a different encryption type/method or is there something I'm doing wrong? Thanks in advance!
Updated Code:
package core;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Crypto {
private static String key = "key12345";
public static byte[] encrypt(String strClearText, String strKey) {
byte[] encrypted = null;
try {
SecretKeySpec skeyspec = new SecretKeySpec(key.getBytes(), "Blowfish");
System.out.println("Ëncryption keyspec: " + skeyspec.toString());
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, skeyspec);
encrypted = cipher.doFinal(strClearText.getBytes());
// strData = new String(encrypted);
} catch (Exception e) {
e.printStackTrace();
}
return encrypted;
}
public static String decrypt(byte[] strEncrypted, String strKey) {
String strData = "";
try {
SecretKeySpec skeyspec = new SecretKeySpec(key.getBytes(),"Blowfish");
System.out.println("Decryption keyspec: " + skeyspec.toString());
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, skeyspec);
byte[] decrypted = cipher.doFinal(strEncrypted);
strData = new String(decrypted);
} catch (Exception e) {
e.printStackTrace();
}
return strData;
}
}
[B#164b077d is what is passed in as strEncrypted.
Error
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher
Related
I'm trying to decrypt data that is encrypted with AES/SIC/PKCS7Padding. I'm making use of BouncyCastleProvider to achieve this, but on decryption BadPaddingException is thrown.
Here's the code i'm using to decrypt, am i doing something wrong? Any help is appreciated, thanks!
public class AesEncryption {
public static String decrypt(String aesKey, String cipherText) {
try {
Security.addProvider(new BouncyCastleProvider());
Cipher dcipher;
SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
dcipher = Cipher.getInstance("AES/SIC/PKCS7Padding", "BC");
dcipher.init(Cipher.DECRYPT_MODE, key, generateIv());
byte[] dec = Base64.getDecoder().decode(cipherText);
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
}
I try to use java7 to achieve AES-256-GCM decoding
I encountered a mac check failure response in GCM
Please help me out, thank you all.
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public static void main(String[] args) throws Exception {
String iv = "35d117c42d1c1835420b6b9942dd4f1b"; // utf-8
String key = "3a7bd3e2360a3d29eea436fcfb7e44c7"; // utf-8
String hexCipherString = "07a604fc0c143a6e"; // hex
String hexAuthTagString = "984e81176ff260717beb184db3d73753"; //hex
byte[] decodedCipherHexBtye = Hex.decodeHex(hexCipherString.toCharArray());
byte[] base64Cipher = Base64.decodeBase64(decodedCipherHexBtye);
byte[] decodedAuthTagHex = Hex.decodeHex(hexAuthTagString.toCharArray());
byte[] base64AuthTag = Base64.decodeBase64(decodedAuthTagHex);
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
byte[] gcmIv = iv.getBytes("UTF-8");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec params = new GCMParameterSpec(base64AuthTag.length * Byte.SIZE, gcmIv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, params);
cipher.updateAAD(base64AuthTag);
byte[] result = cipher.doFinal(base64Cipher);
System.out.println(Base64.encodeBase64(result));
}
I am looking forward to the expected result of Base64Encode: dGVzdA==
How to address the Security warning comment to implement safe code.
The core issue in the warning is the need for a randomly generated IV (a set of truly random bytes) for each encryption
when you make a Cypher here is a concrete example using Java 8 Oracle SE
val cipher = Cipher.getInstance("some scheme", "some provider");
then when we use the the Cypher safely we need a true random initialization vector IV to correctly resolve the issue this warning is directing us too,
turns out at least in Oracle Java 8 this is easy,
with the above cypher
cipher.getIV()
the instance method for the cipher object is safe see
generally use with IvParameterSpec
ivParams = IvParameterSpec( cipher.getIV())
cipher.init(Cipher.ENCRYPT_MODE, key, ivParams);
I found a solution and modified the code as follows:
public static void main(String[] args) throws Exception {
String iv = "35d117c42d1c1835420b6b9942dd4f1b"; // utf-8
String key = "3a7bd3e2360a3d29eea436fcfb7e44c7"; // utf-8
String hexCipherString = "07a604fc0c143a6e"; // hex
String hexAuthTagString = "984e81176ff260717beb184db3d73753"; //hex
byte[] decodedCipherHexBtye = Hex.decodeHex(hexCipherString.toCharArray());
byte[] decodedAuthTagHex = Hex.decodeHex(hexAuthTagString.toCharArray());
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
byte[] gcmIv = iv.getBytes("UTF-8");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
GCMParameterSpec params = new GCMParameterSpec(decodedAuthTagHex.length * Byte.SIZE, gcmIv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, params);
cipher.update(decodedCipherHexBtye);
byte[] result = cipher.doFinal(decodedAuthTagHex);
System.out.println(new String(result));
}
Refer to this article
Tag mismatch error in AES-256-GCM Decryption using Java
This is the easiest way to encryption and decryption using AES-256.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
String decryptedData = AESUtils.decrypt("Your Encrypted Data");
System.out.println(decryptedData);
}
public class AESUtils {
private static final String ENCRYPTION_KEY = "RwcmlVpg";
private static final String ENCRYPTION_IV = "5183666c72eec9e4";
#RequiresApi(api = Build.VERSION_CODES.O)
public static String encrypt(String src) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, makeKey(), makeIv());
byte[] origignal= Base64.encode(cipher.doFinal(src.getBytes()),Base64.DEFAULT);
return new String(origignal);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
public static String decrypt(String src) {
String decrypted = "";
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, makeKey(), makeIv());
byte[] decode = Base64.decode(src, Base64.NO_WRAP);
decrypted= new String(cipher.doFinal(decode), "UTF-8");
} catch (Exception e) {
Log.v("AES Exception", String.valueOf(e));
throw new RuntimeException(e);
}
return decrypted;
}
static AlgorithmParameterSpec makeIv() {
try {
return new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
static Key makeKey() {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] key = md.digest(ENCRYPTION_KEY.getBytes("UTF-8"));
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
In JDK 1_7, I am trying to decrypt the encrypted password.From the result set (rs2),encrypted password is passed to a string variable and later on calling the decrypt method and passed the string 'p_password' and key.While decrypting the password system throws "javax.crypto.BadPaddingException: Given final block not properly padded"
Can someone please advise on how to resolve this problem?
// Encrypted password retrieving from result set
String key = "Blowfish";
String p_password = rs2.getString("USER_PASSWORD");
EncryptDecrypt encryptdecrypt = new EncryptDecrypt();
String p_decryptedPassword = encryptdecrypt.decrypt(p_password, key);
//EncryptDecrypt class
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptDecrypt {
public static String encrypt(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();
throw new Exception(e);
}
return strData;
}
public static String decrypt(String strEncrypted,String strKey) throws Exception{
String strData=null;
try {
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
SecretKeySpec skeyspec=new SecretKeySpec(strKey.getBytes(),"Blowfish");
Cipher cipher=Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeyspec, ivspec);
byte[] decrypted=cipher.doFinal(strEncrypted.getBytes());
strData= new String(decrypted);
} catch (Exception e) {
e.printStackTrace();
throw new Exception(e);
}
return strData;
}
}
I have a problem with encoded string. I have a string that returns from soap request in my android app. This string is crypted by AES with key and ivs. The problem is that char "à" is shown as "?". This is the code:
SoapPrimitive response = (SoapPrimitive) envelope.getResponse();
String xmlCryptResponse = response.toString();
String decrypt = AES64.decrypt(key, ivs, xmlCryptResponse );
and this is the class AES64:
public class AES64 {
public static String encrypt(String key, String ivs, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(ivs.getBytes("ISO-8859-1"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"),
"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes("ISO-8859-1"));
String r = Base64.encodeToString(encrypted, Base64.DEFAULT);
return r;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String ivs, String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(ivs.getBytes("ISO-8859-1"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"),
"AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decode(encrypted.getBytes("ISO-8859-1"), Base64.DEFAULT));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
return ex.toString();
}
}
}
I used the same string response in java console application and it works fine, the char "à" is recognized, tha class AES64 is similar, only difference is that in java application i use java.util.Base64 not android.util.Base64.
I don't understand why in android, ISO-8859-1 returs wrong char.
Can you help me please?? I spent a few days to resolve this problem but nothing.
PS: This is the start of the xml decrypted from the string response:
<?xml version="1.0" encoding="iso-8859-1"?>
Thank you guys
Hello I build this 2 Methods the Encryption works fine but the Decryption get an error because
cipher wants a byte and i want to encrypt from a String
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Test {
private byte[] encrypted;
private String encryptedtext;
private String decrypted;
public String Encrypt (String pInput) {
try {
String Input = pInput;
String key = "Bar12345Bar12345Bar12345Bar12345";
// Erstelle key and cipher
SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
// Verschlüsselung
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(Input.getBytes());
encryptedtext = new String(encrypted);
System.err.println("encrypted:" + encryptedtext);
}catch(Exception e) {
e.printStackTrace();
}
return encrypted;
}
public String Decrypt (String pInput) {
try {
String Input = pInput;
String key = "Bar12345Bar12345Bar12345Bar12345";
// Erstelle key and cipher
SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
// Entschlüsselung
cipher.init(Cipher.DECRYPT_MODE, aesKey);
decrypted = new String(cipher.doFinal(encryptedtext)); // HERE IS THE PROBLEM IT WANT BYTE BUT I WANT TO ENCRYPT FROM A STRING
System.err.println("decrypted: " + decrypted);
}catch(Exception e) {
e.printStackTrace();
}
return pInput;
}
}
Byte array cannot directly convert to string, and neither do the reverse direction.
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
public class stackoverflow_test {
private byte[] encrypted;
private String encryptedtext;
private String decrypted;
public String Encrypt(String pInput) {
try {
String Input = pInput;
String key = "Bar12345Bar12345Bar12345Bar12345";
SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(Input.getBytes());
//encryptedtext = new String(encrypted);
encryptedtext = DatatypeConverter.printBase64Binary(encrypted);
System.err.println("encrypted:" + encryptedtext);
} catch (Exception e) {
e.printStackTrace();
}
return encryptedtext;
}
public String Decrypt(String pInput) {
try {
String Input = pInput;
String key = "Bar12345Bar12345Bar12345Bar12345";
SecretKeySpec aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, aesKey);
encrypted = DatatypeConverter.parseBase64Binary(encryptedtext);
decrypted = new String(cipher.doFinal(encrypted));
System.err.println("decrypted: " + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
return pInput;
}
public static void main(String[] ag){
stackoverflow_test test = new stackoverflow_test();
String a = test.Encrypt("Byte cannot directly convert to string");
String b = test.Decrypt(a);
}
}
Result
encrypted:UmH+3eUagjrRDblxSStArnaktoxTLX+7qvPdwiTO7VggYmYtuXu/Ygww8ZG5SrDz
decrypted: Byte cannot directly convert to string
You can use Cipher to encrypt and decrypt a String.
public class CryptUtil {
private static final String ALGORITHM = "Blowfish";
private static final String MODE = "Blowfish/CBC/PKCS5Padding";
private static final String IV = "abcdefgh";
public static String encrypt(String secretKey, String value ) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(IV.getBytes()));
byte[] values = cipher.doFinal(value.getBytes());
return Base64.encodeToString(values, Base64.DEFAULT);
}
public static String decrypt(String secretKey, String value) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
byte[] values = Base64.decode(value, Base64.DEFAULT);
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), ALGORITHM);
Cipher cipher = Cipher.getInstance(MODE);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(IV.getBytes()));
return new String(cipher.doFinal(values));
}
}