I have created an app whereby the user can save, edit and delete notes and it would be stored in the applications private storage area. the data that is being stored needs to be encrypted however I am new to programming and do not know much about how to do this so if anyone can advise please? I will put the code below for the method that is used to save the notes but for security reasons, encryption is required, what would be the easiest method to use for a beginner?
public class Utilities {
public static final String FILE_EXTENSION = ".bin";
public static boolean saveNote(Context context, Notes notes){
String fileName = String.valueOf(notes.getDateTime()) + FILE_EXTENSION;
FileOutputStream fos;
ObjectOutputStream oos;
try {
fos = context.openFileOutput(fileName, context.MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(notes);
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false; //tell the user something went wrong
}
return true;
}
public static ArrayList<Notes> getSavedNotes(Context context) {
ArrayList<Notes> notes = new ArrayList<>();
File filesDir = context.getFilesDir();
filesDir.getAbsolutePath();
ArrayList<String> noteFiles = new ArrayList<>();
for(String file : filesDir.list()) {
if(file.endsWith(FILE_EXTENSION)) {
noteFiles.add(file);
}
}
FileInputStream fis;
ObjectInputStream ois;
for(int i = 0; i < noteFiles.size(); i++) {
try{
fis = context.openFileInput(noteFiles.get(i));
ois = new ObjectInputStream(fis);
notes.add((Notes)ois.readObject());
fis.close();
ois.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
return notes;
}
public static Notes getNoteByName(Context context, String fileName) {
File file = new File(context.getFilesDir(), fileName);
Notes notes;
if(file.exists()) {
FileInputStream fis;
ObjectInputStream ois;
try {
fis = context.openFileInput(fileName);
ois = new ObjectInputStream(fis);
notes = (Notes) ois.readObject();
fis.close();
ois.close();
} catch(IOException | ClassNotFoundException e){
e.printStackTrace();
return null;
}
return notes;
}
return null;
}
public static void deleteNote(Context context, String fileName) {
File Dir = context.getFilesDir();
File file = new File(Dir, fileName);
if (file.exists()) file.delete();
}
public static void main(String[] args) {
try {
String key = "squirrel123"; // needs to be at least 8 characters for DES
FileInputStream fis = new FileInputStream("original.txt");
FileOutputStream fos = new FileOutputStream("encrypted.txt");
encrypt(key, fis, fos);
FileInputStream fis2 = new FileInputStream("encrypted.txt");
FileOutputStream fos2 = new FileOutputStream("decrypted.txt");
decrypt(key, fis2, fos2);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.ENCRYPT_MODE, is, os);
}
public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable {
encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os);
}
public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable {
DESKeySpec dks = new DESKeySpec(key.getBytes());
SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
SecretKey desKey = skf.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES"); // DES/ECB/PKCS5Padding for SunJCE
if (mode == Cipher.ENCRYPT_MODE) {
cipher.init(Cipher.ENCRYPT_MODE, desKey);
CipherInputStream cis = new CipherInputStream(is, cipher);
doCopy(cis, os);
} else if (mode == Cipher.DECRYPT_MODE) {
cipher.init(Cipher.DECRYPT_MODE, desKey);
CipherOutputStream cos = new CipherOutputStream(os, cipher);
doCopy(is, cos);
}
}
public static void doCopy(InputStream is, OutputStream os) throws IOException {
byte[] bytes = new byte[64];
int numBytes;
while ((numBytes = is.read(bytes)) != -1) {
os.write(bytes, 0, numBytes);
}
os.flush();
os.close();
is.close();
}
}
Edit:
I have now added an example des encryption below the existing code it now looks like this, also how would I know the data is actually encrypted?
public class Utilities {
public static final String FILE_EXTENSION = ".bin";
public static boolean saveNote(Context context, Notes notes){
String fileName = String.valueOf(notes.getDateTime()) + FILE_EXTENSION;
FileOutputStream fos;
ObjectOutputStream oos;
try {
fos = context.openFileOutput(fileName, context.MODE_PRIVATE);
oos = new ObjectOutputStream(fos);
oos.writeObject(notes);
oos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false; //tell the user something went wrong
}
return true;
}
public static ArrayList<Notes> getSavedNotes(Context context) {
ArrayList<Notes> notes = new ArrayList<>();
File filesDir = context.getFilesDir();
filesDir.getAbsolutePath();
ArrayList<String> noteFiles = new ArrayList<>();
for(String file : filesDir.list()) {
if(file.endsWith(FILE_EXTENSION)) {
noteFiles.add(file);
}
}
FileInputStream fis;
ObjectInputStream ois;
for(int i = 0; i < noteFiles.size(); i++) {
try{
fis = context.openFileInput(noteFiles.get(i));
ois = new ObjectInputStream(fis);
notes.add((Notes)ois.readObject());
fis.close();
ois.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
return notes;
}
public static Notes getNoteByName(Context context, String fileName) {
File file = new File(context.getFilesDir(), fileName);
Notes notes;
if(file.exists()) {
FileInputStream fis;
ObjectInputStream ois;
try {
fis = context.openFileInput(fileName);
ois = new ObjectInputStream(fis);
notes = (Notes) ois.readObject();
fis.close();
ois.close();
} catch(IOException | ClassNotFoundException e){
e.printStackTrace();
return null;
}
return notes;
}
return null;
}
public static void deleteNote(Context context, String fileName) {
File Dir = context.getFilesDir();
File file = new File(Dir, fileName);
if(file.exists()) {
file.delete();
}
}
}
DES (Data Encryption Standard) is pretty common for simple tasks like yours. There are a bunch of tutorials online for how to use it. Here's one example I've used: http://www.avajava.com/tutorials/lessons/how-do-i-encrypt-and-decrypt-files-using-des.html
There was another thread where a user shared a more advanced method, Password-Based Key Derivation Function, that is also worth trying. Here's the link: How to encrypt and salt the password using BouncyCastle API in Java?
Related
So I have this code, it pretty much does what it should but my archive ends up broken and it doesn't save the files. Of course I have to achieve these without using FileSystem, no TempFiles or anything.
public static void main(String[] args) throws IOException {
// Path fileName = Paths.get(args[0]);
// String pathZip = args[1];
Path fileName = Paths.get("C:\\Users\\dell\\Desktop\\addfile.txt");
String pathZip = "C:\\Users\\dell\\Desktop\\test.zip";
Map<String, byte[]> zipEntryMap = addFilesInMap(pathZip);
zipEntryMap.forEach((zipEntryName, bytes) -> {
System.out.println(zipEntryName+" "+bytes.toString());
try {
containAndSaveSameFiles(pathZip, bytes, zipEntryName);
} catch (Exception e) {
e.printStackTrace();
}
});
// saveFileInArchive(fileName, pathZip);
}
private static Map<String, byte[]> addFilesInMap(String pathZip) throws IOException {
Map<String, byte[]> zipEntryMap = new HashMap<>();
FileInputStream fileInputStream = new FileInputStream(pathZip);
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
ZipEntry zipEntry;
while((zipEntry = zipInputStream.getNextEntry())!= null){
byte[] buffer = new byte[1024];
ByteArrayOutputStream builder = new ByteArrayOutputStream();
int end;
while((end = zipInputStream.read(buffer)) > 0){
builder.write(buffer, 0, end);
}
zipEntryMap.put(zipEntry.getName(), builder.toByteArray());
}
return zipEntryMap;
}
private static void containAndSaveSameFiles(String pathZip, byte[] bytes, String zipEntryName) throws Exception{
ByteArrayOutputStream readBytes = new ByteArrayOutputStream();
FileOutputStream fileOutputStream = new FileOutputStream(pathZip);
ZipOutputStream outputStream = new ZipOutputStream(readBytes);
ZipEntry zipEntry2 = new ZipEntry(zipEntryName);
zipEntry2.setSize(bytes.length);
outputStream.putNextEntry(new ZipEntry(zipEntryName));
outputStream.write(bytes);
}
private static void saveFileInArchive(Path fileToBeAdded, String pathToArchive) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream(pathToArchive);
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
zipOutputStream.putNextEntry(new ZipEntry("new/"+fileToBeAdded.getFileName()));
Files.copy(fileToBeAdded, zipOutputStream);
zipOutputStream.close();
fileOutputStream.close();
}
I tried a few ways, and look up on the internet but can't find any good answer.
Thank you for help.
Your code is almost correct.
Bug No:1 in containAndSaveSameFiles
Using readBytes instead of fileOutputStream.
Bug No:2 in saveFileInArchive Rewriting OutputStream by reopening it again.
Complete code after review:
public static void main(String[] args) throws IOException {
// Path fileName = Paths.get(args[0]);
// String pathZip = args[1];
Path fileName = Paths.get("C:\\Users\\dell\\Desktop\\addfile.txt");
String pathZip = "C:\\Users\\dell\\Desktop\\test.zip";
Map<String, byte[]> zipEntryMap = addFilesInMap(pathZip);
FileOutputStream fileOutputStream = new FileOutputStream(pathZip);
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
zipEntryMap.forEach((zipEntryName, bytes) -> {
System.out.println(zipEntryName+" "+bytes.toString());
try {
containAndSaveSameFiles(pathZip, bytes, zipEntryName, zipOutputStream);
} catch (Exception e) {
e.printStackTrace();
}
});
saveFileInArchive(fileName, pathZip,zipOutputStream);
zipOutputStream.close();
fileOutputStream.close();
}
private static Map<String, byte[]> addFilesInMap(String pathZip) throws IOException {
Map<String, byte[]> zipEntryMap = new HashMap<>();
FileInputStream fileInputStream = new FileInputStream(pathZip);
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
ZipEntry zipEntry;
while((zipEntry = zipInputStream.getNextEntry())!= null){
byte[] buffer = new byte[1024];
ByteArrayOutputStream builder = new ByteArrayOutputStream();
int end;
while((end = zipInputStream.read(buffer)) > 0){
builder.write(buffer, 0, end);
}
zipEntryMap.put(zipEntry.getName(), builder.toByteArray());
}
return zipEntryMap;
}
private static void containAndSaveSameFiles(String pathZip, byte[] bytes, String zipEntryName, ZipOutputStream zipOutputStream) throws Exception{
// ByteArrayOutputStream readBytes = new ByteArrayOutputStream();
ZipEntry zipEntry2 = new ZipEntry(zipEntryName);
zipEntry2.setSize(bytes.length);
zipOutputStream.putNextEntry(new ZipEntry(zipEntryName));
zipOutputStream.write(bytes);
}
private static void saveFileInArchive(Path fileToBeAdded, String pathToArchive, ZipOutputStream zipOutputStream) throws IOException, IOException {
zipOutputStream.putNextEntry(new ZipEntry("new/"+fileToBeAdded.getFileName()));
Files.copy(fileToBeAdded, zipOutputStream);
}
My use case is this: when the client clicks download on a pdf, I want to edit/write some text on to the pdf using Itext pdf editor, then zip the pdf then let it download, All during the stream. I am aware of memory issue if the pdf is large etc. which won't be an issue since its like 20-50kb. I have the zipping during the stream before downloading working using byte array, now have to make the pdfeditor method also run before zipping, add some text then let the download happen.
Here is my code so far:
public class zipfolder {
public static void main(String[] args) {
try {
System.out.println("opening connection");
URL url = new URL("http://gitlab.itextsupport.com/itext/sandbox/raw/master/resources/pdfs/form.pdf");
InputStream in = url.openStream();
// FileOutputStream fos = new FileOutputStream(new
// File("enwiki.png"));
PdfEditor writepdf = new PdfEditor();
writepdf.manipulatePdf(url, dest, "field"); /// where i belive i
/// should execute the
/// editor function ?
File f = new File("test.zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(f));
ZipEntry entry = new ZipEntry("newform.pdf");
zos.putNextEntry(entry);
System.out.println("reading from resource and writing to file...");
int length = -1;
byte[] buffer = new byte[1024];// buffer for portion of data from
// connection
while ((length = in.read(buffer)) > -1) {
zos.write(buffer, 0, length);
}
zos.close();
in.close();
System.out.println("File downloaded");
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
}
public class PdfEditor {
public String insertFields (String field, String value) {
return field + " " + value;
// System.out.println("does this work :" + field);
}
// public static final String SRC = "src/resources/source.pdf";
// public static final String DEST = "src/resources/Destination.pdf";
//
// public static void main(String[] args) throws DocumentException,
// IOException {
// File file = new File(DEST);
// file.getParentFile().mkdirs();
// }
public String manipulatePdf(URL src, String dest, String field) throws Exception {
System.out.println("test");
try {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
Item item = form.getFieldItem("Name");
PdfDictionary widget = item.getWidget(0);
PdfArray rect = widget.getAsArray(PdfName.RECT);
rect.set(2, new PdfNumber(rect.getAsNumber(2).floatValue() + 20f));
String value = field;
form.setField("Name", value);
form.setField("Company", value);
stamper.close();
} catch (Exception e) {
System.out.println("Error in manipulate");
System.out.println(e.getMessage());
throw e;
}
return field;
}
}
So playing with ByteArrayOutputStream, finally got it work. passing the input stream to 'manipulatepdf' and returning 'bytedata'.
public ByteArrayOutputStream manipulatePdf(InputStream in, String field) throws Exception {
System.out.println("pdfediter got hit");
ByteArrayOutputStream bytedata = new ByteArrayOutputStream();
try {
PdfReader reader = new PdfReader(in);
PdfStamper stamper = new PdfStamper(reader, bytedata);
AcroFields form = stamper.getAcroFields();
Item item = form.getFieldItem("Name");
PdfDictionary widget = item.getWidget(0);
PdfArray rect = widget.getAsArray(PdfName.RECT);
rect.set(2, new PdfNumber(rect.getAsNumber(2).floatValue() + 20f));
String value = field;
form.setField("Name", value);
form.setField("Company", value);
stamper.close();
} catch (Exception e) {
System.out.println("Error in manipulate");
System.out.println(e.getMessage());
throw e;
}
return bytedata;
}
public String editandzip (String data, String Link) {
try {
System.out.println("opening connection");
URL url = new URL(Link);
InputStream in = url.openStream();
System.out.println("in : "+ url);
//String data = "working ok with main";
PdfEditor writetopdf = new PdfEditor();
ByteArrayOutputStream bao = writetopdf.manipulatePdf(in, data);
byte[] ba = bao.toByteArray();
File f = new File("C:/Users/JayAcer/workspace/test/test.zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(f));
ZipEntry entry = new ZipEntry("newform.pdf");
entry.setSize(ba.length);
zos.putNextEntry(entry);
zos.write(ba);
zos.close();
in.close();
System.out.println("File downloaded");
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
return data;
}
}
public class MakeNewFile{
static HashMap<String, User> hm = new HashMap<String, User>();
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Hello!!");
try{
File inputFile = new File("C:\\apache-tomcat-7.0.34\\webapps\\products\\Details.txt");
System.out.println("Done");
boolean resut = inputFile.createNewFile();
System.out.println(resut);
System.out.println("File found");
//fileInputStream = new FileInputStream(inputFile);
FileInputStream fileInputStream = new FileInputStream(inputFile);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//out.println("hiii2");
hm= (HashMap)objectInputStream.readObject();
System.out.println("hiii" +hm);
if(hm.containsKey("username"))
{ String error_msg = "Username already exist as " + "usertype";}
else{
User user = new User("firstname", "lastname", "email", "username","password","usertype");
hm.put("username", user);
FileOutputStream fileOutputStream = new FileOutputStream("C:\\apache-tomcat-7.0.34\\webapps\\products\\Details.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(hm);
objectOutputStream.flush();
objectOutputStream.close();
fileOutputStream.close();
}
}
catch(Exception ex){
}
}
}
The file is not creating while running the code. Code is not executing of try block after FileInputStream. Where is the problem?
I tried one solution. File has been created but objectInputStream is not available.
After running the code locally, the exception thrown is an EOF exception - java.io.EOFException. A solution would be to do a check to see if the fileInputStream is available:
if (fileInputStream.available() > 0) {
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//out.println("hiii2");
hm = (HashMap) objectInputStream.readObject();
}
I have been trying to create a class called TextFileReaderWriter I want to use the getters and setters to read and write to a text file in such a way that I can call the class and the method from anywhere in the program by simply using setfileContents(somestring) and somestring = getfileContents() something like this
example:
TextFileReaderWriter trw = new TextFileReaderWriter();
trw.setfileContents(somestring); //this would write 'somestring' to the text file.
String somestring = trw.getfileContents(); //this would return 'somestring' from the text file.
Here's what I have so far but it writes nothing to the file:
public class TextFileReaderWriter extends Activity{
String fileContents;
Context context;
String TAG = "MYTAG";
public TextFileReaderWriter(String fileContents, Context context) {
this.fileContents = fileContents;
this.context = context;
}
public String getFileContents() {
return fileContents;
}
public void setFileContents(String fileContents) {
this.fileContents = fileContents;
FileOutputStream fos = null;
try {
fos = context.openFileOutput("UserInputStore", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
OutputStreamWriter osw = new OutputStreamWriter(fos);
try {
osw.write(fileContents);
Log.d(TAG, fileContents);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You don't need the OutputStreamWriter--FileOutputStreamwill do the trick just fine.
//what you had before
FileOutputStream fos = null;
try {
fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//use just the file output stream to write the data
//data here is a String
if (fos != null) {
try {
fos.write(data.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Method to save data on disk :
protected static void saveDataOnDisk(String data) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
ObjectOutput objectOutput = new ObjectOutputStream(byteArrayOutputStream);
objectOutput.writeObject(data);
byte[] buffer = byteArrayOutputStream.toByteArray();
File loginDataFile = (new File(filePath)); // file path where you want to write your data
loginDataFile.createNewFile();
FileOutputStream fileOutputStream = new FileOutputStream(loginDataFile);
fileOutputStream.write(buffer);
fileOutputStream.close();
objectOutput.flush();
objectOutput.close();
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
Log.i(“SAVE”, ”———————-DONE SAVING”);
} catch(IOException ioe) {
Log.i(“SAVE”, “———serializeObject|”+ioe);
}
}
Method to fetch data from disk:
private static Object getDataFromDisk() {
try {
FileInputStream fileInputeStream = new FileInputStream(FilePath);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputeStream);
Object data = (Object) objectInputStream.readObject();
objectInputStream.close();
fileInputeStream.close();
return dataModel;
} catch (Exception error) {
Log.i(“FETCH”, ”—-getDataFromDisk———ERROR while reading|” + error);
}
return null;
}
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 saveUserList(ArrayList<User> userList) {
if (storageAvailable()) {
try {
createFolder();
FileOutputStream userList = new FileOutputStream(
baseDir + File.separator + baseAppDir + File.separator
+ fileName);
ObjectOutputStream oos = new ObjectOutputStream(
userList);
oos.writeObject(userList);
oos.close();
} catch (Exception exc) {
exc.printStackTrace();
}
}
}
load method
public static ArrayList<User> loadUserList() {
if (storageAvailable()) {
ArrayList<User> userList = new ArrayList<User>();
try {
FileInputStream userList = new FileInputStream(baseDir
+ File.separator + baseAppDir + File.separator
+ fileName);
ObjectInputStream oos = new ObjectInputStream(
userList);
userList = (ArrayList<User>) oos.readObject();
oos.close();
} catch (Exception exc) {
exc.printStackTrace();
}
return userList;
} else {
return null;
}
}
Now I want that the method saveUserList encrypts the content of the file during the save according a specific String keyword and the method loadUserList decrypts the file with the same keyword to return the arrayList.
How could I do this?
I have given a look to CipherOutputStream but I haven't understood how should I use this.
The method proposed to use Conceal library
public static void saveUserListCrypted(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();
}
}
}
cause this error
this error java.lang.UnsupportedOperationException 02-12 21:29:05.026 2051-2051/com.myapp W/System.err﹕ at com.facebook.crypto.streams.NativeGCMCipherOutputStream.write
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
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. ;)
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!