AES encryption on android - android

I have to encrypt and decrypt text on android devices. I have found some solution, but when I encrypt the text again, the result is different. Can anyone tell me why?
Here is my code:
public class AESDemo {
private static final String password = "test";
private static String salt;
private static int pswdIterations = 65536;
private static int keySize = 256;
private byte[] ivBytes;
public String encrypt(String plainText) throws Exception {
//get salt
salt = generateSalt();
byte[] saltBytes = salt.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
//null,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
//return new Base64().encodeAsString(encryptedTextBytes);
return Base64.encodeToString(encryptedTextBytes, Base64.DEFAULT);
}
#SuppressWarnings("static-access")
public String decrypt(String encryptedText) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8");
//byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
byte[] encryptedTextBytes= Base64.decode(encryptedText, Base64.DEFAULT);
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Decrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try {
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return new String(decryptedTextBytes);
}
public String generateSalt() {
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
String ss = "";
random.nextBytes(bytes);
String s = new String(bytes);
return "sare";
}
}
I've hardcoded the salt to be the same, but the result is different every time. Can anyone tell me why?

Your IV handling puzzles me. You call getIV() but where do you actually set the IV for the encryption? It seems to me you are using a random IV which might explain why you get a different encrypted data each time.
I would suggest to try create a dynamic IvParameterSpec class and fill it with a preset IV.

Related

Android javax.crypto.BadPaddingException

I am implementing encryption/decryption to my files. code is given below. I can't find out the problem.
Am I missing anything? I need to implement 128 bit AES Encryption.
Is there anything wrong?
It end up with error
"javax.crypto.BadPaddingException: error:1e06b065:Cipher functions:EVP_DecryptFinal_ex:BAD_DECRYPT"
Please help me.
private static byte[] encodeFile(byte[] yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
SecretKeySpec skeySpec = new SecretKeySpec(yourKey, 0, yourKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
encrypted = cipher.doFinal(fileData);
return encrypted;
}
private static byte[] generateKey() throws NoSuchAlgorithmException {
byte[] keyStart = "This is my key".getBytes();
String id = "dummypass";
int iterationCount = 1000;
int saltLength = 32;
int keyLength = 128;
SecureRandom random = new SecureRandom();
byte[] salt = Arrays.copyOf(keyStart,saltLength);
random.nextBytes(salt);
KeySpec keySpec = new PBEKeySpec(id.toCharArray(), salt,
iterationCount, keyLength);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = new byte[0];
try {
keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
SecretKey key = new SecretKeySpec(keyBytes, "AES");
return key.getEncoded();
}
private static byte[] decodeFile(byte[] yourKey, byte[] encryptedData)
throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(yourKey, 0, yourKey.length,
"AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encryptedData);
return decrypted;
}
public static void Encrypt(byte[] bytesToEncrypt, File target) {
try {
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(target));
byte[] key = generateKey();
byte[] encryptedBytes = encodeFile(key, bytesToEncrypt);
bos.write(encryptedBytes);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] DecryptFile(byte[] bytesToDecrypt) {
byte[] decodedData = new byte[0];
try {
byte[] key = generateKey();
decodedData = decodeFile(key, bytesToDecrypt);
} catch (Exception e) {
e.printStackTrace();
}
return decodedData;
}
Verify that key is the same in both Encrypt and DecryptFile.
Since both call generateKey and generateKey calls SecureRandom nextBytes the keys are going to be different.
You need to save the encryption key for use during decryption.

Cipher decode returns me an empty Array in Android

I want to encode and decode a File in Android but when i try to decrypt some File it returns an empty array of bytes.
The class I use to encrypt the File and decrypt:
public class CrytedClass {
public static byte[] generateKey(String pass) throws Exception{
byte [] start = pass.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(start);
kgen.init(128,sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
public static byte[] encodedFile(byte[] key, byte[] fileData)throws Exception{
SecretKeySpec skeySpec = new SecretKeySpec(key,"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,skeySpec);
byte [] encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(byte[] key, byte[] fileData) throws Exception{
SecretKeySpec skeySpec = new SecretKeySpec(key,"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,skeySpec);
byte [] decrypted = cipher.doFinal(fileData);
return decrypted;
}
public static String generatePass(){
return new BigInteger(130, new SecureRandom()).toString(32);
}
public static byte[] createHas(byte[] ficheroEncrip){
MessageDigest msd = null;
try{
msd = MessageDigest.getInstance("SHA-1");
}catch (Exception e){
return null;
}
msd.update(ficheroEncrip);
return msd.digest();
}
}
The test code i use.
try {
String id1 = CrytedClass.generatePass();
byte[] secure = CrytedClass.generateKey(id1);
byte[] FileEncoded = CrytedClass.encodedFile(secure, ous.toByteArray());
byte[] decoded = CrytedClass.decodeFile(secure, FileEncoded);
File decodedFile = new File(Environment.getExternalStorageDirectory()+"/decoded.pdf");
FileOutputStream pdfFile = new FileOutputStream(decodedFile);
pdfFile.write(decoded);
System.out.println("Final del test");
Boolean r = pdfFile.equals(original);
}catch(Exception e){
}
Thanks for your help

FBEncrypter library compatibility with Android

I have already use below library for encryption and decryption in iOS.
https://github.com/dev5tec/FBEncryptor
Now I want same functionality in Android. Is there any support for Android also? If not then how can I use this library to fulfil my need in Android also or please suggest another other encryption library that work same as FBEncryptor.
I have implemented the following code.
public class AESHelper {
private final Cipher cipher;
private final SecretKeySpec key;
private AlgorithmParameterSpec spec;
private static final String KEY = "VHJFTFRGJHGHJDhkhjhd/dhfdh=";
public AESHelper() throws Exception {
byte[] keyBytes = KEY.getBytes("UTF-8");
Arrays.fill(keyBytes, (byte) 0x00);
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
key = new SecretKeySpec(keyBytes, "AES");
spec = getIV();
}
public AlgorithmParameterSpec getIV() {
final byte[] iv = new byte[16];
Arrays.fill(iv, (byte) 0x00);
return new IvParameterSpec(iv);
}
public String encrypt(String plainText) throws Exception {
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
String encryptedText = new String(Base64.encode(encrypted, Base64.DEFAULT), "UTF-8");
return encryptedText;
}
public String decrypt(String cryptedText) throws Exception {
cipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] bytes = Base64.decode(cryptedText, Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(bytes);
String decryptedText = new String(decrypted, "UTF-8");
return decryptedText;
}
}
But it throw javax.crypto.BadPaddingException: Pad Block Corrupted
finally i have found solution for my own question.
For encryption in android you can use https://gist.github.com/m1entus/f70d4d1465b90d9ee024.
This class work same as like https://github.com/dev5tec/FBEncryptor in ios.

Android AES encryption - The constructor Base64() is not visible

I have found 2 AES encryption/decryption functions and I want to use them inside my app, but I get an error.
The functions are:
private static final String password = "test";
private static String salt;
private static int pswdIterations = 65536 ;
private static int keySize = 256;
private byte[] ivBytes;
////////////////
//encrypt AES///
////////////////
public String encrypt(String plainText) throws Exception {
//get salt
salt = generateSalt();
byte[] saltBytes = salt.getBytes("UTF-8");
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
//encrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
ivBytes = params.getParameterSpec(IvParameterSpec.class).getIV();
byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
return new Base64().encodeAsString(encryptedTextBytes);
}
#SuppressWarnings("static-access")
public String decrypt(String encryptedText) throws Exception {
byte[] saltBytes = salt.getBytes("UTF-8");
byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
// Derive the key
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
saltBytes,
pswdIterations,
keySize
);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
// Decrypt the message
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes));
byte[] decryptedTextBytes = null;
try {
decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return new String(decryptedTextBytes);
}
public String generateSalt() {
SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
String s = new String(bytes);
return s;
}
My error is at line:
return new Base64().encodeAsString(encryptedTextBytes);
and
byte[] encryptedTextBytes = new Base64().decodeBase64(encryptedText);
The error msg is : The constructor Base64() is not visible
Any idea why this happens?

Cannot Decrypt AES on Android?

I'm a newbie to android dev, right now I implemented an AES on Android and it could encrypt strings with user input passwords. The encryption seems fine and it could omit Base64/Hex encoded strings.
But When I try to decrypt it, the problem comes: With the decryption, the omission always showing me a load of messy characters.
In order to get rid of it, I've tried debugging it by define a charset (Like UTF-8) while casting from string to byte[], but no hit, and also tried to encode the omit with base 64 or Hex, but both of them failed.
I've also tried to define AES/CBC/PKCS5Padding or just AES while using cipher.getInstance method, but still no go.
It is quite irritating, could you guys help me please?
Forgot to mention that I once asked a similar question https://stackoverflow.com/questions/6727255/aes-decryption-on-android-not-correct , the grammer problem there have been corrected.
And Here's the code:
For Encryption
public String AESEncrypt(String sKey, String PlainMsg)
throws Exception {
//Try use some Android based alert dialog to catch this exception.
if (sKey == null) {
Log.e("SecureChat", "IllegalArgumentException Catched");
throw new IllegalArgumentException ("NULL Secret NOT ALLOWED!");
}
/*Old Method
//byte[] rawKey = getRawKey(sKey.getBytes("UTF-8"));
byte[] rawKey = getRawKey(sKey.getBytes());
//Encrypt start
SecretKeySpec keySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
//byte[] cipherText = cipher.doFinal(PlainMsg.getBytes("UTF-8"));
byte[] cipherText = cipher.doFinal(PlainMsg.getBytes());
return Base64Encoded(cipherText);
*/
//New Method
byte[] salt = getSalt();
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
KeySpec spec = new PBEKeySpec(sKey.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
//Encryption Process
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] cipherText = cipher.doFinal(PlainMsg.getBytes());
//return Base64Encoded(cipherText);
//Hex
return toHex(cipherText);
}
For Decryption
public String AESDecrypt(String sKey, String EncryptMsg)
throws Exception {
/*Old Method
//byte[] rawKey = getRawKey(sKey.getBytes("UTF-8"));
byte[] rawKey = getRawKey(sKey.getBytes());
SecretKeySpec keySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec);
//byte[] plainText = Base64Decoded(EncryptMsg.getBytes("UTF-8"));
byte[] plainText = Base64Decoded(EncryptMsg);
cipher.doFinal(plainText);
return new String(plainText, "UTF-8");
*/
//New Method
byte[] salt = getSalt();
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHSHA256AND256BITAES-CBC-BC");
KeySpec spec = new PBEKeySpec(sKey.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
//byte[] bCipherText = Base64Decoded(EncryptMsg);
//Hex
byte[] bCipherText = toByte(EncryptMsg);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
cipher.doFinal(bCipherText);
return new String(bCipherText);
}
private byte[] getSalt() throws NoSuchAlgorithmException {
/*Mark for old key method
//Initialize the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
//Init for 256bit AES key
kgen.init(Constants.AES_KEY_SIZE, sr);;
SecretKey secret = kgen.generateKey();
//Get secret raw key
byte[] rawKey = secret.getEncoded();
return rawKey;
*/
//New key method with some salt
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
byte[] ransalt = new byte[20];
random.nextBytes(ransalt);
return ransalt;
}
#Override
public byte[] getRawKey(byte[] seed) throws Exception {
/*Old Method
//Initialize the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
//Init for 256bit AES key
kgen.init(Constants.AES_KEY_SIZE, sr);
SecretKey secret = kgen.generateKey();
//Get secret raw key
byte[] rawKey = secret.getEncoded();
return rawKey;
*/
return null;
}
/**
*
* #param toBeDecoded
* #return
*/
public byte[] Base64Decoded(String toBeDecoded) {
byte[] decoded = Base64.decode(toBeDecoded, 0);
return decoded;
}
//Hex Mode
public String toHex(String txt) {
return toHex(txt.getBytes());
}
public String fromHex(String hex) {
return new String(toByte(hex));
}
public byte[] toByte(String hexString) {
int len = hexString.length()/2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
return result;
}
public String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2*buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final String HEX = "0123456789ABCDEF";
private void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
}
I've referenced/compared with these code on Stackoverflow:
Android aes encryption pad block corrupted
and
incorrect decryption using AES/CBC/PKCS5Padding in Android
Seems that my problem lies on the charset encoding, but I cannot find out where the problem is.
Any comments/answers are very appreciated!
Thank you for helping me!
This code I wrote works flawlessly. Look at this link below:
http://pocket-for-android.1047292.n5.nabble.com/Encryption-method-and-reading-the-Dropbox-backup-td4344194.html#a4454327
Without looking too carefully at your code I would suggest you should specify the encoding here though I'm not sure if this is the cause of your problems:
byte[] cipherText = cipher.doFinal(PlainMsg.getBytes());
and here:
return new String(bCipherText);

Categories

Resources