I save and load in sd card a file that contains an ArrayList
of serializable object with these two methods
save method
public static void sa
You could simply use AES Encoding:
private static byte[] getEncrypt(final String key, final String message) throws GeneralSecurityException {
final byte[] rawData = key.getBytes(Charset.forName("US-ASCII"));
if (rawData.length != 16) {
// If this is not 16 in length, there's a problem with the key size, nothing to do here
throw new IllegalArgumentException("You've provided an invalid key size");
}
final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES");
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.ENCRYPT_MODE, seckeySpec, new IvParameterSpec(new byte[16]));
return ciph.doFinal(message.getBytes(Charset.forName("US-ASCII")));
}
private static String getDecrypt(String key, byte[] encrypted) throws GeneralSecurityException {
final byte[] rawData = key.getBytes(Charset.forName("US-ASCII"));
if (rawData.length != 16) {
// If this is not 16 in length, there's a problem with the key size, nothing to do here
throw new IllegalArgumentException("Invalid key size.");
}
final SecretKeySpec seckeySpec = new SecretKeySpec(rawData, "AES");
final Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.DECRYPT_MODE, seckeySpec, new IvParameterSpec(new byte[16]));
final byte[] decryptedmess = ciph.doFinal(encrypted);
return new String(decryptedmess, Charset.forName("US-ASCII"));
}
Then, for trying it, this example may be valid for you:
final String encrypt = "My16inLengthKey5";
final byte[] docrypt = getEncrypt(encrypt, "This is a phrase to be encrypted!");
final String douncrypt = getDecrypt(encrypt.toString(), docrypt);
Log.d("Decryption", "Decrypted phrase: " + douncrypt);
Of course, douncrypt
must match This is a phrase to be encrypted!
I suggest taking a look at Conceal, recently released by facebook: http://facebook.github.io/conceal/
This should be a trivial modification to wrap a Conceal output stream with an ObjectOutputStream used in your current code:
public static void saveUserList(ArrayList<User> userList) {
if (storageAvailable()) {
try {
createFolder();
Crypto crypto = new Crypto(
new SharedPrefsBackedKeyChain(context),
new SystemNativeCryptoLibrary());
FileOutputStream userList = new FileOutputStream(
baseDir + File.separator + baseAppDir + File.separator
+ fileName);
OutputStream cryptedStream = crypto.getCipherOutputStream(
userList, new Entity("UserList");
ObjectOutputStream oos = new ObjectOutputStream(
cryptedStream);
oos.writeObject(userList);
oos.close();
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
I'll leave the restore as an exercise for the reader. ;)
Try (adding the appropriate checks and try blocks that I have omitted to make the code more readable) something like this to save
public static void AESObjectEncoder(Serializable object, String password, String path) {
try {
Cipher cipher = null;
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.ENCRYPT_MODE, fromStringToAESkey(password));
SealedObject sealedObject = null;
sealedObject = new SealedObject(object, cipher);
CipherOutputStream cipherOutputStream = null;
cipherOutputStream = new CipherOutputStream(new BufferedOutputStream(new FileOutputStream(path)), cipher);
ObjectOutputStream outputStream = null;
outputStream = new ObjectOutputStream(cipherOutputStream);
outputStream.writeObject(sealedObject);
outputStream.close();
}
and this to load
public static Serializable AESObjectDedcoder(String password, String path) {
Cipher cipher = null;
Serializable userList = null;
cipher = Cipher.getInstance("AES/CBC/PKCS7Pdding");
//Code to write your object to file
cipher.init(Cipher.DECRYPT_MODE, fromStringToAESkey(password));
CipherInputStream cipherInputStream = null;
cipherInputStream = new CipherInputStream(new BufferedInputStream(new FileInputStream(path)), cipher);
ObjectInputStream inputStream = null;
inputStream = new ObjectInputStream(cipherInputStream);
SealedObject sealedObject = null;
sealedObject = (SealedObject) inputStream.readObject();
userList = (Serializable) sealedObject.getObject(ciper);
return userList;
}
to create a SecretKey
from a String you can use this
public static SecretKey fromStringToAESkey(String s) {
//256bit key need 32 byte
byte[] rawKey = new byte[32];
// if you don't specify the encoding you might get weird results
byte[] keyBytes = new byte[0];
try {
keyBytes = s.getBytes("ASCII");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.arraycopy(keyBytes, 0, rawKey, 0, keyBytes.length);
SecretKey key = new SecretKeySpec(rawKey, "AES");
return key;
}
NOTE:
this code encrypts and decrypts twice to show the way of use of both sealed object and Cipher streams