Is there any good example of how to encrypt and decrypt image and other files with AES on Android?
-
7Encryption on Android is not fundamentally different than on any other Java SE platform. And as all the answers below are insecure, for either you have to understand cryptography before you start implementing or borrowing cryptography examples. – Maarten Bodewes Jun 10 '14 at 20:47
-
4You should try this https://github.com/facebook/conceal. – Nhat Dinh Jul 31 '15 at 04:06
10 Answers
Warning: This answer contains code you should not use as it is insecure (using SHA1PRNG for key derivation and using AES in ECB mode)
Instead (as of 2016), use PBKDF2WithHmacSHA1 for key derivation and AES in CBC or GCM mode (GCM provides both privacy and integrity)
You could use functions like these:
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
And invoke them like this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos); // bm is the bitmap object
byte[] b = baos.toByteArray();
byte[] keyStart = "this is a key".getBytes();
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();
// encrypt
byte[] encryptedData = encrypt(key,b);
// decrypt
byte[] decryptedData = decrypt(key,encryptedData);
This should work, I use similar code in a project right now.
-
Thanks, your code is perfect for my purposes. Tidy and Clear. Does it exist a Input/OutputStream version of these cipher.doFinal ? Does single/multipart way of doing is the only way ? I swear that i should implement a Stream to Multipart cyphering method. – Emmanuel Devaux Sep 12 '11 at 20:07
-
9Hey this not works for me, I am getting Badpadding exception while decrypting the same. – Sanat Pandey Nov 18 '11 at 13:40
-
this is taking a lot of time as the file size increase . Did you use it for file encryption or only string encryption – png May 20 '12 at 08:47
-
I used it for json files about 400-500k and didn't noticed a significative amount of time for encryption/decryption. – Nacho L. May 20 '12 at 09:53
-
This code worked on an android emulator. But once I tested this on my Nexus 5 phone I got a bad padding exception. Currently investigating to see what the cause is. – IcedDante Mar 24 '14 at 03:03
-
36***WARNING*** This code is using known bad code from Android snippets for key derivation. Don't use it unless you want to loose your data. A seeded RNG is *not* a good Key Derivation Function (KDF). – Maarten Bodewes Jun 09 '14 at 16:42
-
2@IcedDante Please view [this question](http://stackoverflow.com/q/24124091/589259). – Maarten Bodewes Jun 09 '14 at 17:44
-
37***WARNING*** This code may defaults to ECB mode encryption on most platforms. Using ECB mode encryption is not safe for most data, let alone pictures. [Find the penguin](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29)! – Maarten Bodewes Jun 10 '14 at 19:55
-
1
-
@SweetWisherツ Restrictions in the Oracle JRE. You'd generally need the [unlimited crypto files from the JRE / JDK download page](http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html) and install them manually. – Maarten Bodewes Apr 27 '16 at 21:54
-
-
2WARNING: "in Android N we are deprecating the implementation of the SHA1PRNG algorithm and the Crypto provider altogether" Please follow the link for further information;https://android-developers.googleblog.com/2016/06/security-crypto-provider-deprecated-in.html – mavixce Jan 30 '17 at 13:02
-
1I am getting "javax.crypto.BadPaddingException: pad block corrupted" when I try this code. Have any idea? – Alvin Varghese Feb 28 '17 at 04:37
-
@AlvinVarghese Generally, when something cannot be decrypted you'd get `BadPaddingException`. I did warn you about this code, right? – Maarten Bodewes Oct 13 '17 at 08:08
-
1What's the point of an answer showing the incorrect way of solving problem? Maybe fix the code instead of writing in bold print that there is some code below but we cannot use it. @hardartcore, please mark some other question as correct. – Piotrek Feb 15 '18 at 11:27
-
13@Maarten Bodewes I see your warnings all over the place, under manyt posts. Could you please provide a good solution instead? – Yar Mar 30 '18 at 12:27
-
@Yar I'm doing that for many questions. However, basically this is asking how to perform file encryption in Java. There should be plenty examples on the internet, I think the question is too broad. No use cases or threat model is given. So you get all kinds of code, which will then be copied willy-nilly into projects by idiots that think copy / paste is a good idea for security relevant code that runs *even if not secure*. So for these kind of questions I should restrain myself and not answer, just warn. Check my profile, I have more answers than the next 10 *together* on the encryption tag. – Maarten Bodewes Mar 30 '18 at 12:35
-
simply use this to force it to set AES and not ECB: `Cipher.getInstance("AES/GCM/NOPADDING");` – Odaym Jul 28 '18 at 17:31
-
@Odaym GCM is not secure if the key is not secure, or if no unique nonce is provided. **Just** replacing ECB by GCM is therefore not a solution as you suggest. – Maarten Bodewes Nov 17 '19 at 00:13
-
I now used this option, it seems good: https://mkyong.com/java/java-aes-encryption-and-decryption/ – Boommeister Dec 13 '20 at 00:24
As mentioned by Nacho.L PBKDF2WithHmacSHA1 derivation is used as it is more secured.
import android.util.Base64;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class AESEncyption {
private static final int pswdIterations = 10;
private static final int keySize = 128;
private static final String cypherInstance = "AES/CBC/PKCS5Padding";
private static final String secretKeyInstance = "PBKDF2WithHmacSHA1";
private static final String plainText = "sampleText";
private static final String AESSalt = "exampleSalt";
private static final String initializationVector = "8119745113154120";
public static String encrypt(String textToEncrypt) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
Cipher cipher = Cipher.getInstance(cypherInstance);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
byte[] encrypted = cipher.doFinal(textToEncrypt.getBytes());
return Base64.encodeToString(encrypted, Base64.DEFAULT);
}
public static String decrypt(String textToDecrypt) throws Exception {
byte[] encryted_bytes = Base64.decode(textToDecrypt, Base64.DEFAULT);
SecretKeySpec skeySpec = new SecretKeySpec(getRaw(plainText, AESSalt), "AES");
Cipher cipher = Cipher.getInstance(cypherInstance);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(initializationVector.getBytes()));
byte[] decrypted = cipher.doFinal(encryted_bytes);
return new String(decrypted, "UTF-8");
}
private static byte[] getRaw(String plainText, String salt) {
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(secretKeyInstance);
KeySpec spec = new PBEKeySpec(plainText.toCharArray(), salt.getBytes(), pswdIterations, keySize);
return factory.generateSecret(spec).getEncoded();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return new byte[0];
}
}

- 507
- 4
- 18
-
4True this derivation is much better. But now you're using a static IV, a static salt and a way too low iteration count. So withou warnings the result is still insecure. Crypto is a pain to get right... – Maarten Bodewes Mar 30 '18 at 13:00
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
class SecurityUtils {
private static final byte[] salt = { (byte) 0xA4, (byte) 0x0B, (byte) 0xC8,
(byte) 0x34, (byte) 0xD6, (byte) 0x95, (byte) 0xF3, (byte) 0x13 };
private static int BLOCKS = 128;
public static byte[] encryptAES(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(cleartext.getBytes("UTF8"));
}
public static byte[] decryptAES(String seed, byte[] data) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes("UTF8"));
SecretKeySpec skeySpec = new SecretKeySpec(rawKey, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(data);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(BLOCKS, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] pad(byte[] seed) {
byte[] nseed = new byte[BLOCKS / 8];
for (int i = 0; i < BLOCKS / 8; i++)
nseed[i] = 0;
for (int i = 0; i < seed.length; i++)
nseed[i] = seed[i];
return nseed;
}
public static byte[] encryptPBE(String password, String cleartext)
throws Exception {
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 1024, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
return cipher.doFinal(cleartext.getBytes("UTF-8"));
}
public static String decryptPBE(SecretKey secret, String ciphertext,
byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
return new String(cipher.doFinal(ciphertext.getBytes()), "UTF-8");
}
}

- 28,384
- 14
- 74
- 132

- 1,124
- 13
- 31
-
4
-
1@BrijeshThakur - read [this](http://stackoverflow.com/questions/13383006/encryption-error-on-android-4-2) – t0mm13b Apr 05 '13 at 12:57
-
@BrijeshThakur it is because it is converting it into string was having same problem just save it as bytes and it will work – Amit Hooda Apr 24 '13 at 14:30
-
14***WARNING*** This code is using known bad code from Android Snippets for key derivation. Don't use it unless you want to loose your data. A seeded RNG is *not* a good Key Derivation Function (KDF). – Maarten Bodewes Jun 09 '14 at 16:42
-
3More information [here](http://stackoverflow.com/q/24124091/589259) – Maarten Bodewes Jun 09 '14 at 17:45
-
10***WARNING*** This code may defaults to ECB mode encryption on most platforms. Using ECB mode encryption is not safe for most data, let alone pictures. [Find the penguin](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_.28ECB.29)! – Maarten Bodewes Jun 10 '14 at 19:56
-
1WARNING: "in Android N we are deprecating the implementation of the SHA1PRNG algorithm and the Crypto provider altogether" Please follow the link for further information;https://android-developers.googleblog.com/2016/06/security-crypto-provider-deprecated-in.html – mavixce Jan 30 '17 at 13:06
For AES/CBC/PKCS7 encryption/decryption, Just Copy and paste the following code and replace SecretKey
and IV
with your own.
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class CryptoHandler {
String SecretKey = "xxxxxxxxxxxxxxxxxxxx";
String IV = "xxxxxxxxxxxxxxxx";
private static CryptoHandler instance = null;
public static CryptoHandler getInstance() {
if (instance == null) {
instance = new CryptoHandler();
}
return instance;
}
public String encrypt(String message) throws NoSuchAlgorithmException,
NoSuchPaddingException, IllegalBlockSizeException,
BadPaddingException, InvalidKeyException,
UnsupportedEncodingException, InvalidAlgorithmParameterException {
byte[] srcBuff = message.getBytes("UTF8");
//here using substring because AES takes only 16 or 24 or 32 byte of key
SecretKeySpec skeySpec = new
SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivSpec);
byte[] dstBuff = ecipher.doFinal(srcBuff);
String base64 = Base64.encodeToString(dstBuff, Base64.DEFAULT);
return base64;
}
public String decrypt(String encrypted) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException {
SecretKeySpec skeySpec = new
SecretKeySpec(SecretKey.substring(0,32).getBytes(), "AES");
IvParameterSpec ivSpec = new
IvParameterSpec(IV.substring(0,16).getBytes());
Cipher ecipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
ecipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] raw = Base64.decode(encrypted, Base64.DEFAULT);
byte[] originalBytes = ecipher.doFinal(raw);
String original = new String(originalBytes, "UTF8");
return original;
}
}

- 90,524
- 13
- 150
- 263

- 558
- 8
- 13
-
Would you add function which can encode file? Return type will be byte[] – Paritosh Oct 02 '19 at 16:07
-
1You just need to call these functions by class name. eg. CryptoHandler.encrypt("YOUR STRING That you want to encrypt") and the same as this one you can call decrypt() also. And both functions return String. – Sujeet Oct 03 '19 at 09:07
-
3**Warning** A key is not a string, a key and IV should not "picked" by a user. An IV should be unpredictable (indistinguishable from random) to an adversary for CBC to be secure. Another failed attempt, you're over #10 to not get cryptography and still are willing to provide "an example". This is a code only answer as well, it doesn't explain what kind of security it provides. – Maarten Bodewes Nov 17 '19 at 00:18
Old question but I upgrade the answers supporting Android prior and post 4.2 and considering all recent changes according to Android developers blog
Plus I leave a working example on my github repo.
import java.nio.charset.Charset;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will Google be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, as long as the origin is not misrepresented.
*
* @author: Ricardo Champa
*
*/
public class MyCipher {
private final static String ALGORITHM = "AES";
private String mySecret;
public MyCipher(String mySecret){
this.mySecret = mySecret;
}
public MyCipherData encryptUTF8(String data){
try{
byte[] bytes = data.toString().getBytes("utf-8");
byte[] bytesBase64 = Base64.encodeBase64(bytes);
return encrypt(bytesBase64);
}
catch(Exception e){
MyLogs.show(e.getMessage());
return null;
}
}
public String decryptUTF8(byte[] encryptedData, IvParameterSpec iv){
try {
byte[] decryptedData = decrypt(encryptedData, iv);
byte[] decodedBytes = Base64.decodeBase64(decryptedData);
String restored_data = new String(decodedBytes, Charset.forName("UTF8"));
return restored_data;
} catch (Exception e) {
MyLogs.show(e.getMessage());;
return null;
}
}
//AES
private MyCipherData encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
//solved using PRNGFixes class
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] data = cipher.doFinal(clear);
AlgorithmParameters params = cipher.getParameters();
byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
return new MyCipherData(data, iv);
}
private byte[] decrypt(byte[] raw, byte[] encrypted, IvParameterSpec iv) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, ALGORITHM);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
private byte[] getKey() throws Exception{
byte[] keyStart = this.mySecret.getBytes("utf-8");
KeyGenerator kgen = KeyGenerator.getInstance(ALGORITHM);
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
// if (android.os.Build.VERSION.SDK_INT >= 17) {
// sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
// } else {
// sr = SecureRandom.getInstance("SHA1PRNG");
// }
sr.setSeed(keyStart);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] key = skey.getEncoded();
return key;
}
////////////////////////////////////////////////////////////
private MyCipherData encrypt(byte[] data) throws Exception{
return encrypt(getKey(),data);
}
private byte[] decrypt(byte[] encryptedData, IvParameterSpec iv) throws Exception{
return decrypt(getKey(),encryptedData, iv);
}
}

- 7,921
- 14
- 64
- 111
-
http://codingaffairs.blogspot.com/2016/06/aes-encryption-decryption-in-android.html – Developine Jun 25 '16 at 10:17
-
-
Rather than using the Apache Commons Codec library, is there any disadvantage using `android.util.Base64.encode(bytes, Base64.DEFAULT)` and `android.util.Base64.decode(decryptedData, Base64.DEFAULT)`? – ban-geoengineering Jun 29 '16 at 15:36
-
2WARNING This code is using known bad code from Android Snippets for key derivation. Don't use it unless you want to loose your data. A seeded RNG is not a good Key Derivation Function (KDF). (sigh). – Maarten Bodewes Oct 13 '17 at 08:11
-
1
-
Use a password based key derivation function to derive the key if you want to use a password at all. – Maarten Bodewes Mar 30 '18 at 12:41
If you are encrypting a text file, then the following test/sample may be useful. It does the following:
- Create a byte stream,
- wraps that with AES encryption,
- wrap it next with text processing
and lastly buffers it
// AESdemo public class AESdemo extends Activity { boolean encryptionIsOn = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_aesdemo); // needs <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> String homeDirName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + getPackageName(); File file = new File(homeDirName, "test.txt"); byte[] keyBytes = getKey("password"); try { File dir = new File(homeDirName); if (!dir.exists()) dir.mkdirs(); if (!file.exists()) file.createNewFile(); OutputStreamWriter osw; if (encryptionIsOn) { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); FileOutputStream fos = new FileOutputStream(file); CipherOutputStream cos = new CipherOutputStream(fos, cipher); osw = new OutputStreamWriter(cos, "UTF-8"); } else // not encryptionIsOn osw = new FileWriter(file); BufferedWriter out = new BufferedWriter(osw); out.write("This is a test\n"); out.close(); } catch (Exception e) { System.out.println("Encryption Exception "+e); } /////////////////////////////////// try { InputStreamReader isr; if (encryptionIsOn) { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); FileInputStream fis = new FileInputStream(file); CipherInputStream cis = new CipherInputStream(fis, cipher); isr = new InputStreamReader(cis, "UTF-8"); } else isr = new FileReader(file); BufferedReader in = new BufferedReader(isr); String line = in.readLine(); System.out.println("Text read: <"+line+">"); in.close(); } catch (Exception e) { System.out.println("Decryption Exception "+e); } } private byte[] getKey(String password) throws UnsupportedEncodingException { String key = ""; while (key.length() < 16) key += password; return key.substring(0, 16).getBytes("UTF-8"); } }

- 1,484
- 20
- 17
-
8***WARNING*** This code is using a key derivation mechanism that uses the default character decoding. Don't use this unless you want to have problems decrypting your data. – Maarten Bodewes Jun 09 '14 at 16:44
-
3@owlstead, good observation, it would have been nice if you had suggested the fix. The example above has now been updated to specify a character encoding in getKey(). Further corrections are welcome... – SoloPilot Jun 10 '14 at 19:43
-
9Sorry, I was mainly burning answers here, because they used `SecureRandom` for key derivation. If you want to know how to instantiate a cipher, check ericksons's answer [here](http://stackoverflow.com/a/992413/589259). Don't use a static IV (for the same key), and use PBKDF2 for password -> key conversion. Note that a non-authenticated cipher only provides confidentiality, and only if it is not used in a transport protocol. If you want to help, you can burn the other answers too (and vote up my comments there) :) – Maarten Bodewes Jun 10 '14 at 19:51
-
@MaartenBodewes you "burned" many answer, but you dont propose an answer. If you have correct answer, why dont you write one here? – Dika Apr 25 '19 at 04:23
-
@Dika I think I pointed an answer out above. Please do keep in mind that I'm with [a very large margin](https://stackoverflow.com/tags/encryption/topusers) the guy that posts the most answers on both cryptography and encryption. Also keep in mind that I'm rather opposed against generic wrapper libraries that simply lead people to copy code rather than write code themselves for a specific use case. The Java crypto API is rather well thought out, if a bit cumbersome. Use that! There is nothing special about image encryption; it's basic file encryption. – Maarten Bodewes Apr 25 '19 at 10:50
AES encrypt/decrypt in android
String encData= encrypt("keykey".getBytes("UTF-16LE"), ("0123000000000215").getBytes("UTF-16LE"));
String decData= decrypt("keykey",Base64.decode(encData.getBytes("UTF-16LE"), Base64.DEFAULT));
encrypt function
private static String encrypt(byte[] key, byte[] clear) throws Exception
{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] digestOfPassword = md.digest(key);
SecretKeySpec skeySpec = new SecretKeySpec(digestOfPassword, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return Base64.encodeToString(encrypted,Base64.DEFAULT);
}
decrypt function
private static String decrypt(String key, byte[] encrypted) throws Exception
{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] digestOfPassword = md.digest(key.getBytes("UTF-16LE"));
SecretKeySpec skeySpec = new SecretKeySpec(digestOfPassword, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, "UTF-16LE");
}
AES encrypt/decrypt in c#
static void Main(string[] args)
{
string enc = encryptAES("0123000000000215", "keykey");
string dec = decryptAES(enc, "keykey");
Console.ReadKey();
}
encrypt function
public static string encryptAES(string input, string key)
{
var plain = Encoding.Unicode.GetBytes(input);
// 128 bits
AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
provider.KeySize = 128;
provider.Mode = CipherMode.ECB;
provider.Padding = PaddingMode.PKCS7;
provider.Key = CalculateMD5Hash(key);
var enc = provider.CreateEncryptor().TransformFinalBlock(plain, 0, plain.Length);
return Convert.ToBase64String(enc);
}
decrypt function
public static string decryptAES(string encryptText, string key)
{
byte[] enc = Convert.FromBase64String(encryptText);
// 128 bits
AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
provider.KeySize = 128;
provider.Mode = CipherMode.ECB;
provider.Padding = PaddingMode.PKCS7;
provider.Key = CalculateMD5Hash(key);
var dec = provider.CreateDecryptor().TransformFinalBlock(enc, 0, enc.Length);
return Encoding.Unicode.GetString(dec);
}
create md5
public static byte[] CalculateMD5Hash(string input)
{
MD5 md5 = MD5.Create();
byte[] inputBytes = Encoding.Unicode.GetBytes(input);
return md5.ComputeHash(inputBytes);
}

- 1,019
- 12
- 19
-
1MD5 is not a password hash or Password Based Key Derivation Function. If you use a password, use it correctly. – Maarten Bodewes Mar 30 '18 at 12:56
Simple API to perform AES encryption on Android. This is the Android counterpart to the AESCrypt library Ruby and Obj-C (with the same defaults):

- 12,018
- 6
- 44
- 65

- 360
- 3
- 9
-
7Could you expand a bit how this library can be used to solve the problem ? Just copying the GitHub description and adding a link to it is not all that helpful, and your answer could be a lot better with some explanation. – Jonas Czech Mar 29 '16 at 17:36
Here is simple code snippet working for AES Encryption and Decryption.
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class AESEncryptionClass {
private static String INIT_VECTOR_PARAM = "#####";
private static String PASSWORD = "#####";
private static String SALT_KEY = "#####";
private static SecretKeySpec generateAESKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
// Prepare password and salt key.
char[] password = new String(Base64.decode(PASSWORD, Base64.DEFAULT)).toCharArray();
byte[] salt = new String(Base64.decode(SALT_KEY, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);
// Create object of [Password Based Encryption Key Specification] with required iteration count and key length.
KeySpec spec = new PBEKeySpec(password, salt, 64, 256);
// Now create AES Key using required hashing algorithm.
SecretKey key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1").generateSecret(spec);
// Get encoded bytes of secret key.
byte[] bytesSecretKey = key.getEncoded();
// Create specification for AES Key.
SecretKeySpec secretKeySpec = new SecretKeySpec(bytesSecretKey, "AES");
return secretKeySpec;
}
/**
* Call this method to encrypt the readable plain text and get Base64 of encrypted bytes.
*/
public static String encryptMessage(String message) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {
byte[] initVectorParamBytes = new String(Base64.decode(INIT_VECTOR_PARAM, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);
Cipher encryptionCipherBlock = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptionCipherBlock.init(Cipher.ENCRYPT_MODE, generateAESKey(), new IvParameterSpec(initVectorParamBytes));
byte[] messageBytes = message.getBytes();
byte[] cipherTextBytes = encryptionCipherBlock.doFinal(messageBytes);
String encryptedText = Base64.encodeToString(cipherTextBytes, Base64.DEFAULT);
return encryptedText;
}
/**
* Call this method to decrypt the Base64 of encrypted message and get readable plain text.
*/
public static String decryptMessage(String base64Cipher) throws BadPaddingException, IllegalBlockSizeException, NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {
byte[] initVectorParamBytes = new String(Base64.decode(INIT_VECTOR_PARAM, Base64.DEFAULT)).getBytes(StandardCharsets.UTF_8);
Cipher decryptionCipherBlock = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptionCipherBlock.init(Cipher.DECRYPT_MODE, generateAESKey(), new IvParameterSpec(initVectorParamBytes));
byte[] cipherBytes = Base64.decode(base64Cipher, Base64.DEFAULT);
byte[] messageBytes = decryptionCipherBlock.doFinal(cipherBytes);
String plainText = new String(messageBytes);
return plainText;
}
}
Now, call
encryptMessage()
ordecryptMessage()
for desiredAES
Operation with required parameters.Also, handle the exceptions during
AES
operations.
Hope it helped...

- 3,322
- 25
- 30
To add bouncy castle to Android project: https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16/1.45
Add this line in your Main Activity:
static {
Security.addProvider(new BouncyCastleProvider());
}
public class AESHelper {
private static final String TAG = "AESHelper";
public static byte[] encrypt(byte[] data, String initVector, String key) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec k = new SecretKeySpec(Base64.decode(key, Base64.DEFAULT), "AES");
c.init(Cipher.ENCRYPT_MODE, k, iv);
return c.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] data, String initVector, String key) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
Cipher c = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec k = new SecretKeySpec(Base64.decode(key, Base64.DEFAULT), "AES");
c.init(Cipher.DECRYPT_MODE, k, iv);
return c.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String keyGenerator() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(192);
return Base64.encodeToString(keyGenerator.generateKey().getEncoded(),
Base64.DEFAULT);
}
}

- 339
- 3
- 10
-
http://blog.dealforest.net/2012/03/ios-android-per-aes-crypt-connection/ – FlipNovid Apr 17 '17 at 18:54
-
I don't think you need Bouncy for this; it will only make sure that you cannot use hardware acceleration and kill performance for large files (such as images). Encoding the key in base 64 is bad idea; storing it in a key store is much better. – Maarten Bodewes Mar 30 '18 at 13:03