Android AES in LibGDX - java

I am trying to encrypt something using AES and then save. The problem is that its working on my computer, but not on android. What is the problem?
This is main AES class:
public class AESUtils {
public static byte[] encrypt(SecretKeySpec skeySpec, byte[] clear) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
public static byte[] decrypt(SecretKeySpec skeySpec, byte[] encrypted) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static SecretKeySpec getKey(String key) throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, sr);
return new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
}
}
FileSaveClass:
public class FileUtils {
public static void save(FileHandle file, byte[] bytes) {
file.writeBytes(bytes, false);
}
public static byte[] load(FileHandle file) {
return file.readBytes();
}
}
And it's that i am trying to do:
SecretKeySpec skeySpec = AESUtils.getKey("Any key");
// if file not exist - create new, else open it, add any symbol and save it again
if (!fileHandle.exists()) {
byte[] encodedBytes = AESUtils.encrypt(skeySpec, text.getBytes());
SaveUtils.save(fileHandle, encodedBytes);
} else {
byte[] clearBytes = AESUtils.decrypt(skeySpec, SaveUtils.load(fileHandle));
text = new String(clearBytes);
text += "1";
byte[] encodedBytes = AESUtils.encrypt(skeySpec, text.getBytes());
SaveUtils.save(fileHandle, encodedBytes);
System.out.println(text);
}

Your device may have an API version greater than or equal to 17 (Jelly Bean). Changing the static method getKey(String key) to the following code may solve the problem:
public static SecretKeySpec getKey(String key) throws NoSuchAlgorithmException {
KeyGenerator kg = KeyGenerator.getInstance("AES");
final int JELLY_BEAN_4_2 = 17;
SecureRandom sr = null;
if (Gdx.app.getType() == ApplicationType.Android) {
if (Gdx.app.getVersion() >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
} else if (Gdx.app.getType() == ApplicationType.iOS) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(key.getBytes());
kg.init(128, sr);
return new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
}

Related

javax.crypto.BadPaddingException: Decryption error and also Message larger than modulus

Below I try to send message in multicast socket through group and to provide encryption:
Encrypt the data with the symmetric key
Encrypt the symmetric key with rsa
send the encrypted key and the data
Decrypt the encrypted symmetric key with rsa
decrypt the data with the symmetric key
But I am getting this error
javax.crypto.BadPaddingException: Decryption error at java.base/sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:378) at java.base/sun.security.rsa.RSAPadding.unpad(RSAPadding.java:290) at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:366) at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208) at Security.RSADecryption(Symmetra.java:63) at ReadThread.run(Symmetra.java:202) at java.base/java.lang.Thread.run(Thread.java:835)
I think I did not understood encryption decryption properly.
See below for the code:
class Security
{
public static SecretKey createAESKey() throws Exception
{
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
SecretKey key = generator.generateKey();
return key;
}
public static KeyPair generateRSAkeyPair() throws Exception
{
//SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//KeyGenerator keyGenerator = KeyGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
KeyPair pair = keyPairGenerator.generateKeyPair();
return pair;
}
public static byte[] AESEncryption(String plaintext, SecretKey secKey) throws Exception
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,secKey);
byte[] cipherText = cipher.doFinal(plaintext.getBytes());
return cipherText;
}
public static byte[] RSAEncryption(PublicKey publicKey, SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//cipher.update(plaintext.getBytes());
byte [] encryptedKey = cipher.doFinal(key.getEncoded());
System.out.println(encryptedKey.length);
return encryptedKey;
}
public static byte[] RSADecryption(byte[] encryptedKey, PrivateKey privateKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte check[] = cipher.doFinal(encryptedKey);
return cipher.doFinal(encryptedKey);
}
public static String AESDecryption(byte[] decryptedKey, byte[] text) throws Exception
{
SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, originalKey);
byte[] plaintext = cipher.doFinal(text);
return new String(plaintext);
}
public static KeyPair generate() throws Exception
{
KeyPair keyPair = generateRSAkeyPair();
return keyPair;
}
}
public class TestDemo extends Security
{
public static void main(String args[])
{
KeyPair keyPair = generate();
SecretKey key = createAESKey();
byte[] cipherText = AESEncryption(message,key);
byte[] encryptedKey = RSAEncryption(keyPair.getPublic(), key);
DatagramPacket datagram = new
DatagramPacket(cipherText,cipherText.length,group,port); // It carries encrpyted message
// It carries symmetric key encrypted by RSA
DatagramPacket datagram2 = new
DatagramPacket(encryptedKey,encryptedKey.length,group,port);
socket.send(datagram);
socket.send(datagram2);
}
}
class ReadThread extends Security
{
KeyPair keyPair;
SecretKey key;
try
{
keyPair = generate();
key = createAESKey();
byte[] buffer = new byte[ReadThread.MAX_LEN];
DatagramPacket datagram = new DatagramPacket(buffer,buffer.length,group,port);
byte[] keyBuffer = new byte[512];
DatagramPacket datagram2 = new
DatagramPacket(keyBuffer,keyBuffer.length,group,port);
String message;
try
{
socket.receive(datagram);
socket.receive(datagram2);
byte[] decryptKey = RSADecryption(keyBuffer,keyPair.getPrivate());
String decryptText = AESDecryption(decryptKey, buffer);
message = decryptText;
if(!message.startsWith(Symmetra.name))
System.out.println(message);
}
catch(IOException e)
{
System.out.println("Socket closed!");
}
}
}

Decrypting returns, javax.crypto.BadPaddingException: Given final block not properly padded

Im trying to decrypt the encrypted xml file. Im getting it as a inputstream as follows.I have the correct encrypt key. but each time my program returns empty string. Every time i enter the correct key. but each time it returns Badpadding Exception.
try{
InputStream is = new ByteArrayInputStream(decryption.getFileData().getBytes());
String xmlEncryptedStr = getStringFromInputStream(is);
String xmlStr = CipherUtils.decrypt(xmlEncryptedStr, new Long(key));
.......
here is my CipherUtils.java class
.........
public static String decrypt(String strToDecrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("decrypt keyString :"+keyString);
return decrypt(strToDecrypt, keyString.getBytes());
}
public static String decrypt(String strToDecrypt,byte[] key)
{
if(strToDecrypt==null)
return strToDecrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
System.out.println("CipherUtils.decryptedString :"+decryptedString);
return decryptedString;
}
catch (Exception e)
{
log.error("Ops!", e);
}
return null;
}
.......
For more information here is my encrypting code
public static String encrypt(String strToEncrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("encrypt keyString :"+keyString);
return encrypt(strToEncrypt,keyString.getBytes());
}
public static String encrypt(String strToEncrypt,byte[] key)
{
if(strToEncrypt==null)
return strToEncrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
// System.out.println("CipherUtils.encrypt :"+encryptedString);
return encryptedString;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
I am sorry I couldn't comment so I am writing in answers section.
I faced this issue when I was using different keys though I was passing the same but i used CBC methodology.
Just to note that have you checked that encryption is also done by the AES/ECB/PKCS5Padding and not other format like AES/CBC/PKCS5Padding
Also check if key format for encryption is also having the same format like %016d of your keyValue. Also the key is 16 char long.
I created a simple AES and DESede encryption utility and it worked fine.
private static final byte[] keyValue = new String(
"CjxI&S#V&#DSA_S0dA-SDSA$").getBytes();
public static void main(String[] args) throws Exception {
Client cli = new Client();
System.out.println(cli.encrypt("your password for encryption"));
Client cli1 = new Client();
System.out.println(cli1.decrypt("fTsgVQtXvv49GynHazT4OGZ4Va1H57d+6AM+44Ex040="));
}
public String encrypt(String Data) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
// String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public String decrypt(String encryptedData) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = DatatypeConverter
.parseBase64Binary(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}

How to encrypt a stringbuilder message using AES algorithm in java

I have a stringBuilder message appended with "||" symbol.(Ex: Hi||How||are||26 04 2016||finish) i have to encrypt the message and send it to the server using AES and decrypt the same at the server side. Can anyone help me out in solving this?
You can encrypt and decrypt like this:
public class AES {
public static byte[] encrypt(String key, String initVector, String value) {
try {
IvParameterSpec vector = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, vector);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string: "+ Base64.encodeBase64(encrypted));
return Base64.encodeBase64(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String key, String initVector, byte[] encrypted) {
try {
IvParameterSpec vector = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, secretKey, vector);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String key = "Foo12345Bar67890"; // 128 bit key
String initVector = "RandomInitVector"; // 16 bytes IV
StringBuilder sb = new StringBuilder("Hi||How||are||26 04 2016||finish"); //Your Text here
byte[] encryptedBytes = encrypt(key, initVector, sb.toString());
System.out.println(decrypt(key, initVector,encryptedBytes));
}
}

Decryption error on Android 4.4

I have algorithm of encryption\ decryption files:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = new SecureRandom();
sr.setSeed(seed);
kgen.init(sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
It works great, but on Android 4.4 (api 19) I have strangely exception
javax.crypto.BadPaddingException: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
What is it?
Here what I got: http://www.logikdev.com/2010/11/01/encrypt-with-php-decrypt-with-java/
public class AES2 {
private static final String TRANSFORMATION = "AES/CFB8/NoPadding";
private static final String ALGO_MD5 = "MD5";
private static final String ALGO_AES = "AES";
/**
* See http://www.logikdev.com/2012/12/12/md5-generates-31-bytes-instead-of-32/ form more detail.
*
* #param input
* #return
* #throws NoSuchAlgorithmException
*/
private static String md5(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance(ALGO_MD5);
byte[] messageDigest = md.digest(input.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
return String.format("%032x", number);
}
public static String decrypt(String encryptedData, String initialVectorString, String secretKey) {
String decryptedData = null;
try {
String md5Key = md5(secretKey);
SecretKeySpec skeySpec = new SecretKeySpec(md5Key.getBytes(), ALGO_AES);
IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
byte[] encryptedByteArray = Base64.decode(encryptedData.getBytes(), Base64.DEFAULT);
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
decryptedData = new String(decryptedByteArray);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptedData;
}
}
So you have to create a initialVectorString (example: "fedcba9876543210"). Hope this help.

How to resolve "javax.crypto.IllegalBlockSizeException: last block incomplete in decryption" in this code

I read a lot of stuff explaining how to resolve this kind of exception but i am still unable to resolve this.
My target is :
1. Encrypt String data using SecretKey and store it into SQLite database.
2. read data from SQLite database and decrypt it using the same SecretKey.
This is my class to encrypt and decrypt data in android application (implementation of target 1 & 2). This code is giving exception -- javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
How can i solve this error ? Any sugestion will be appreciated.. Thanks
public class Cryptography {
private String encryptedFileName = "Enc_File2.txt";
private static String algorithm = "AES";
private static final int outputKeyLength = 256;
static SecretKey yourKey = null;
SQLiteDatabase database;
DBHelper helper;
Context context;
//saveFile("Hello From CoderzHeaven testing :: Gaurav Wable");
//decodeFile();
public Cryptography (Context context) {
this.context = context;
helper = new DBHelper(context);
database = helper.getWritableDatabase();
}
public String encryptString(String data) {
char[] p = { 'p', 'a', 's', 's' };
//SecretKey yourKey = null;
byte[] keyBytes = null;
byte[] filesBytes = null;
try {
if(this.yourKey == null) {
Log.d("key", "instance null");
Cursor cursor = database.query("assmain", new String[]{"keyAvailability"}, null, null, null, null, null);
cursor.moveToFirst();
if(cursor.getInt(cursor.getColumnIndex("keyAvailability")) == 1) {
Log.d("key", "exists in DB");
keyBytes = cursor.getBlob(cursor.getColumnIndex("key"));
cursor.close();
filesBytes = encodeFile(keyBytes, data.getBytes());
} else {
Log.d("key", "generating");
this.yourKey = generateKey(p, generateSalt().toString().getBytes());
filesBytes = encodeFile(this.yourKey, data.getBytes());
}
} else {
Log.d("key", "instance exists");
//yourKey = this.yourKey;
filesBytes = encodeFile(yourKey, data.getBytes());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new String(filesBytes);
}
public String decryptString(String data) {
String str = null;
byte[] decodedData = null;
try {
Log.d("To decrypt", data);
if(this.yourKey == null) {
Log.d("key", "null");
Cursor cursor = database.query("assmain", new String[]{"keyAvailability"}, null, null, null, null, null);
cursor.moveToFirst();
if(cursor.getInt(cursor.getColumnIndex("keyAvailability")) == 1) {
Log.d("key", "exists in DB");
byte[] keyBytes = cursor.getBlob(cursor.getColumnIndex("key"));
cursor.close();
decodedData = decodeFile(keyBytes, data.getBytes());
} else {
Log.d("key", "Unavailable");
Toast.makeText(context, "Key Unavailable", Toast.LENGTH_SHORT).show();
}
} else {
Log.d("key", "instance exists");
decodedData = decodeFile(this.yourKey, data.getBytes());
}
decodedData = decodeFile(yourKey, data.getBytes());
str = new String(decodedData);
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;
// Generate a 256-bit key
//final int outputKeyLength = 256;
SecretKeyFactory secretKeyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations,
outputKeyLength);
yourKey = secretKeyFactory.generateSecret(keySpec);
return yourKey;
}
public static SecretKey generateSalt() throws NoSuchAlgorithmException {
// Generate a 256-bit key
//final int outputKeyLength = 256;
SecureRandom secureRandom = new SecureRandom();
// Do *not* seed secureRandom! Automatically seeded from system entropy.
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
SecretKey key = keyGenerator.generateKey();
return key;
}
public static byte[] encodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] encodeFile(byte[] data, byte[] fileData)
throws Exception {
//byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
//Cipher cipher = Cipher.getInstance(algorithm);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
public static byte[] decodeFile(byte[] data, byte[] fileData)
throws Exception {
//byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length,
algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(fileData);
return decrypted;
}
}
This is error snippet
07-01 14:50:48.230: W/System.err(11715): javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
07-01 14:50:48.230: W/System.err(11715): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:705)
07-01 14:50:48.230: W/System.err(11715): at javax.crypto.Cipher.doFinal(Cipher.java:1111)
07-01 14:50:48.230: W/System.err(11715): at com.cdac.authenticationl3.Cryptography.decodeFile(Cryptography.java:170)
07-01 14:50:48.230: W/System.err(11715): at com.cdac.authenticationl3.Cryptography.decryptString(Cryptography.java:95)
You are using AES/ECB/PKCS5Padding for decrypting the file but not while encrypting the file.
Add AES/ECB/PKCS5Padding for the encryption process as well. So it should be
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
Hope this helps

Categories

Resources