I know that when you first look on the title you said that it had been asked a hundred time before.
But no this is different, at least the way I coded this.
I used this code to encrypt/decrypt my data.
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESHelper {
public static String encrypt(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
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;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static 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 static 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 static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
Actually, Encryption goes so fine. My problem goes with the decryption that returns BadPaddingException: pad block corrupted.
I am so new to this whole security thing and I really hope you could help.
Thanks :)
Your error is something I faced, that had brought me here. However after going through the comment section and no probable solution that suit what I was having and which was same as yours but from dart/flutter. I went back to my code, debugging and I later noticed that the argument supplied to both functions are different. This is what is throwing the error "pad lock corrupted".
so inspect the argument in encrypt(String seed, String cleartext) & decrypt(String seed, String encrypted) and ensure that are case-sensitive and of same length.
Thanks.
Related
I am using Volley to send data to my server and I am putting all the necessary data in the header and in the body of the stringRequest.
After I send the request, I can capture the packages using WireShark and I am able to see all the data that has been sent, from the token in the header to all of the fields in the body (userId, etc).
How is encryption used in network connections using Volley?
Is it any way to encrypt the data in the header and the body of the request?
you can use AES algorithm
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESEncryptionDecryption {
private static final byte[] keyValue =
new byte[]{'c', 'o', 'd', 'i', 'n', 'g', 'a', 'f', 'f', 'a', 'i', 'r', 's', 'c', 'o', 'm'};
public static String encrypt(String cleartext)
throws Exception {
byte[] rawKey = getRawKey();
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String encrypted)
throws Exception {
byte[] enc = toByte(encrypted);
byte[] result = decrypt(enc);
return new String(result);
}
private static byte[] getRawKey() throws Exception {
SecretKey key = new SecretKeySpec(keyValue, "AES");
byte[] raw = key.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKey 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[] encrypted)
throws Exception {
SecretKey skeySpec = new SecretKeySpec(keyValue, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static 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 static 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 static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
for encryption use this method
String encrypted = "";
try {
encrypted = AESEncryptionDecryption.encrypt(plain_text);
Log.d(Constants.firebase_app, "encrypted:" + encrypted);
} catch (Exception e) {
e.printStackTrace();
}
for decryption use this method
String decrypted = "";
try {
decrypted = AESEncryptionDecryption.decrypt(encrypted);
Log.d(Constants.firebase_app, "decrypted:" + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
I recently purchased and HTC One and test ran some code on it that is working fine on my old Moto Razr. I am getting a BadPaddingException, pad block corrupted. Encryption is needed just to hide a pass phrase in the preferences.. it's not critical. I'm just trying to obscure it a little. Here is the exception and below is the Class that I found on a forum. Encryption is my weak point. I am just not advanced enough yet to really grasp what is going on. Any help would be greatly appreciated.
10-28 15:51:26.754: W/System.err(30090): javax.crypto.BadPaddingException: pad block corrupted
10-28 15:51:26.764: W/System.err(30090): at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineDoFinal(BaseBlockCipher.java:709)
10-28 15:51:26.764: W/System.err(30090): at javax.crypto.Cipher.doFinal(Cipher.java:1111)
10-28 15:51:26.764: W/System.err(30090): at com.seine.trophy.main.SimpleCrypto.decrypt(SimpleCrypto.java:63)
10-28 15:51:26.764: W/System.err(30090): at com.seine.trophy.main.SimpleCrypto.decrypt(SimpleCrypto.java:36)
Java source code:
/**
* Usage:
*
* <pre>
* String crypto = SimpleCrypto.encrypt(masterpassword, cleartext)
* ...
* String cleartext = SimpleCrypto.decrypt(masterpassword, crypto)
* </pre>
*
* #author ferenc.hechler
*/
public class SimpleCrypto {
private final static String HEX = "0123456789ABCDEF";
public static String encrypt(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
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;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static 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 static 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 static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
Thanks for any help!
I am ecrypting the data in java(Java project using AES) and want to decrypt the data in android but I am getting bad pad corrupt error.If same is run on java project its woking.Java project and android code is below:
Java Side code(Java Project):
enter code here
public static void main(String[] args) {
//Same password used in android
String masterpassword ="test";
String crypto = encrypt(masterpassword, "XYZ");
}
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
System.out.println(rawKey);
byte[] result = encrypt(rawKey, cleartext.getBytes());
return Base64.encode(result);
// return toHex(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
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;
}
Android Side Code:
*
public void onDecrypt(View view){
System.out.println("onDecrypt ");
String param = "w7ayjByx5I0yrX2tT8gj4w==";//Encrypted data
String masterpassword ="test";
try {
String res = decrypt(masterpassword, param);
}
}
*
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
System.out.println(rawKey);
// byte[] enc = toByte(encrypted);
byte[] enc = Base64.decode(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, 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");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
Pls help.
Here is one mistake. In these lines ...
Java (encrypt side)
byte[] result = encrypt(rawKey, cleartext.getBytes());
Android(decrypt side):
return new String(result);
... you are using the default platform character set encoding. Never do that, always explicitly specify the charset encoding. Just use "UTF-8" which is universal and, except perhaps for some Asian languages, optimally space efficient. So, use the correct getBytes() method and String constructor.
I also notice you are using a SecureRandom instance to expand a seed. This is a pretty non-standard way of doing this. It might work but it is a bad idea.
I have searched lot before posting this question. Earlier the code was working in non android 4.2/2.1 devices. Then i googled and introduced the below lines of code. That solved it partially,ie it's now working on 4.2 devices but not on Froyo.
if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
The below given is the class I use for encryption
public class Encryption {
private final static String HEX = "0123456789ABCDEF";
private final static int JELLY_BEAN_4_2 = 17;
private final static byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0 };
public static String encrypt(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
String fromHex = toHex(result);
return fromHex;
}
public static String decrypt(String seed, String encrypted)
throws Exception {
byte[] seedByte = seed.getBytes();
System.arraycopy(seedByte, 0, Constants.SEED, 0,
((seedByte.length < 16) ? seedByte.length : 16));
String base64 = new String(Base64.decode(encrypted, 0));
byte[] rawKey = getRawKey(seedByte);
byte[] enc = toByte(base64);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
public static byte[] encryptBytes(String seed, byte[] cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext);
return result;
}
public static byte[] decryptBytes(String seed, byte[] encrypted)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = decrypt(rawKey, encrypted);
return result;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
try {
kgen.init(256, sr);
} catch (Exception e) {
// "This device doesn't suppor 256bits, trying 192bits.");
try {
kgen.init(192, sr);
} catch (Exception e1) {
Log.w(LOG,
"This device doesn't suppor 192bits, trying 128bits.");
kgen.init(128, sr);
}
}
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
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;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static 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 static 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 static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
The code is working properly on non-froyo devices. But on froyo the encryption is giving different result than on non-froyo devices.
You are misusing a pseudo random number generator and it's seed as a key derivation function - this is really really bad style. The pseudo random number generator "SHA1PRNG" is not a standard like AES - therefore you never know what implementation you get.
See also Is there a SHA1PRNG standard?
It makes me no wonder that you get different results. Getting a deterministic result based on a given seed is not a property you can expect from a pseudo random number function.
If you want to derive a cryptographic key from a password please use a Key Derivation Function like PKCS #5 / PBKDF2.
An implementation of PBKDF2 is AFAIR included in Bouncy Castle.
It's my first time asking for help in here, my department (a Government), have published some app on the market (Google Play), and the encryption and description was working really well up to yesterday when I got the Jelly Bean 4.2 on my Nexus.
The encrypt works fine, it's in fact encrypt the information to be stored. Though when decrypt it, I'm getting an exception exactly like this : pad block corrupted.
I've checked the string and it's consistent with it on others devices (using the same key for test purposes), meaning it's exactly the same.
The problem is that we need keep the back compatibility with previous versions, meaning that if I change something in the code, it's should be able to read the old encrypted information. The encrypted information it's stored on SQLite, due that I need encode it to Base64. The exception happen on this line byte[] decrypted = cipher.doFinal(encrypted);
Here is my class:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class EncodeDecodeAES {
private final static String HEX = "0123456789ABCDEF";
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
String fromHex = toHex(result);
String base64 = new String(Base64.encodeToString(fromHex.getBytes(), 0));
return base64;
}
public static String decrypt(String seed, String encrypted) throws Exception {
String base64 = new String(Base64.decode(encrypted, 0));
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(base64);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
public static byte[] encryptBytes(String seed, byte[] cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext);
return result;
}
public static byte[] decryptBytes(String seed, byte[] encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = decrypt(rawKey, encrypted);
return result;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
try {
kgen.init(256, sr);
} catch (Exception e) {
// Log.w(LOG, "This device doesn't suppor 256bits, trying 192bits.");
try {
kgen.init(192, sr);
} catch (Exception e1) {
// Log.w(LOG, "This device doesn't suppor 192bits, trying 128bits.");
kgen.init(128, sr);
}
}
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
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;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static 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 static 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 static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
I would like to know (if somebody help me), what 'm I doing wrong with this code, or if it's a issue with Android 4.2 and if it's a issue with 4.2 if has any workaround?
Thank you
WARNING This answer uses SecureRandom for key derivation, which is contrary to its purpose. SecureRandom is a random number generator and is not guaranteed to produce consistent output between platforms (which is what caused the problem in the question). The proper mechanism for key derivation is SecretKeyFactory. This nelenkov's blog post has a good write-up on this issue. This answer provides a solution for cases when you are constrained by backwards compatibility requirement; however, you should migrate to a correct implementation as soon as possible.
Ok, today with a little more time to do some research (and remove my old post, that actually wasn't work, sorry) I got one answer that's working fine, I actually did test it on Android 2.3.6, 2.3.7 (that's basically the same), 4.0.4 and 4.2 and it has worked.
I did some research on those links :
Encryption error on Android 4.2,
BouncyCastle AES error when upgrading to 1.45,
http://en.wikipedia.org/wiki/Padding_(cryptography)
Then I got in this solution thanks to the content on those links above.
Here is my class (and now working fine):
package au.gov.dhsJobSeeker.main.readwriteprefssettings.util;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import android.util.Base64;
public class EncodeDecodeAES {
private final static String HEX = "0123456789ABCDEF";
private final static int JELLY_BEAN_4_2 = 17;
private final static byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// static {
// Security.addProvider(new BouncyCastleProvider());
// }
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
String fromHex = toHex(result);
String base64 = new String(Base64.encodeToString(fromHex.getBytes(), 0));
return base64;
}
public static String decrypt(String seed, String encrypted) throws Exception {
byte[] seedByte = seed.getBytes();
System.arraycopy(seedByte, 0, key, 0, ((seedByte.length < 16) ? seedByte.length : 16));
String base64 = new String(Base64.decode(encrypted, 0));
byte[] rawKey = getRawKey(seedByte);
byte[] enc = toByte(base64);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
public static byte[] encryptBytes(String seed, byte[] cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext);
return result;
}
public static byte[] decryptBytes(String seed, byte[] encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = decrypt(rawKey, encrypted);
return result;
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES"); // , "SC");
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
try {
kgen.init(256, sr);
// kgen.init(128, sr);
} catch (Exception e) {
// Log.w(LOG, "This device doesn't suppor 256bits, trying 192bits.");
try {
kgen.init(192, sr);
} catch (Exception e1) {
// Log.w(LOG, "This device doesn't suppor 192bits, trying 128bits.");
kgen.init(128, sr);
}
}
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES"); // /ECB/PKCS7Padding", "SC");
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"); // /ECB/PKCS7Padding", "SC");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static String toHex(String txt) {
return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
return new String(toByte(hex));
}
public static 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 static 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 static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
However the PBrando answer(above, also works, due that I marked it as solution.), though as I was looking for a way to keep a similar app file size with it's now, I've opted to use this approach. Because I don't need to import external Jars.
I did put the entire class for just in case any of you is having the same issue, and want to just copy ans paste it.
You could try to use the SpongyCastle library.
It is the BouncyCastle patched to compile on Android.
Since it is compatible with BouncyCastle (only the package name and the service provider are different, "SC" instead of "BC"), and Android uses a subset of BouncyCastle, integrating SpongyCastle in your code should be a trivial task.
You can find SpongyCastle here: http://rtyley.github.com/spongycastle/
Take care of registering SpongyCastle as explained in their website:
static {
Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
}
When you get instances of crypto objects, specify also the provider ("SC").