I am playing around with saving/loading a text file in Android, works fine. Next step is to encrypt and decrypt with AES.
I can call the encrypt() method within the writetofile method,a dn that works fine. If i call the readfromfile method, I can see the ciphertext is retrieved, great.
But decryption isnt working for me - I have called simplecrypo in a few places - on stringBuffer.toString(), and within the StringBuffer's append() method - but both crash the application.
So does anybody know where I am supposed to decrypt the string within the file?
package com.example.filesdemo;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText etInput;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = (EditText) findViewById(R.id.etInput);
}
public void writeToFile(View v) throws Exception {
try {
String inputStr = etInput.getText().toString();
//encrypt the string - works!
String encrypted = SimpleCrypto.encrypt("testkey", inputStr);
FileOutputStream fos = openFileOutput("myfile.txt", MODE_PRIVATE);
fos.write(encrypted.getBytes());
fos.flush();
fos.close();
Toast.makeText(this, "File saved!", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFromFile(View v) throws Exception{
try {
FileInputStream fis = openFileInput("myfile.txt");
StringBuffer stringBuffer = new StringBuffer();
BufferedReader bReader = new BufferedReader(new InputStreamReader(
fis));
String strLine = null;
while ((strLine = bReader.readLine()) != null) {
stringBuffer.append(strLine + "\n");
}
bReader.close();
fis.close();
Toast.makeText(this, "File content: \n" +stringBuffer.toString(),
Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
And the encryption class is publically available here - decrypt class, but i dont think thats the issue.
Thanks!
From the look of things, you are writing the encrypted bytes to the file, and then trying to read them back as text into a Scanner. That won't work, as you have found.
If you want your file to be text, then you need to convert the bytes to Base64 and write as text. On reading the Base64 text, convert back to bytes and decypher. Java 8 has the Base64 class, I an not sure about Android.
If you want the file as raw bytes, then you need to read it as bytes, not as text. Once read as bytes it can be decyphered directly.
Related
I try to output the content of a text file. But I don't know how to work with the RandomAccessFile. I haven't found good examples at google. I hope for some help.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class ReadTextFile {
public static void main(String[] args) throws IOException {
File src = new File ("C:/Users/hansbaum/Documents/Ascii.txt");
cat(src);
}
public static void cat(File quelle){
try (RandomAccessFile datei = new RandomAccessFile(quelle, "r")){
// while(datei.length() != -1){
// datei.seek(0); //
// }
} catch (FileNotFoundException fnfe) {
System.out.println("Datei nicht gefunden!");
} catch (IOException ioe) {
System.err.println(ioe);
}
}
}
related from doc
try (RandomAccessFile datei = new RandomAccessFile(quelle, "r")){
String line;
while ( (line = datei.readLine()) != null ) {
System.out.println(line);
}
System.out.println();
} catch (FileNotFoundException fnfe) {
} catch (IOException ioe) {
System.err.println(ioe);
}
What makes you think you need a RandomAccessFile? The easiest way is probably to use nio's convenience methods. With those, reading a file is as close to a one-liner as it gets in Java.
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.io.IOException;
class Test {
public static void main(String[] args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("./Test.java"), StandardCharsets.UTF_8);
for (String l: lines)
System.out.println(l);
}
}
Be aware however that this is not a good idea if you happen to work with very large files as they might not fit into memory.
Try to create Stream from FileChannel to read and write in another file out.txt like this:
try (RandomAccessFile datei = new RandomAccessFile(quelle, "r").getChannel();){
// Construct a stream that reads bytes from the given channel.
InputStream is = Channels.newInputStream(rChannel);
File outFile = new File("out.txt");
// Create a writable file channel
WritableByteChannel wChannel = new RandomAccessFile(outFile,"w").getChannel();
// Construct a stream that writes bytes to the given channel.
OutputStream os = Channels.newOutputStream(wChannel);
// close the channels
is.close();
os.close();
How can I edit the content of a file located on the internal storage in my Android app.
I want to erase the whole content and then write to the file again, instead of appending data to the current content.
Here's my code to read and write:
package com.example.cargom;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
public class FileManager {
FileOutputStream outputStream;
FileInputStream inputStream;
public void writeToFile(Context context, String fileName, String data) {
try {
outputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
outputStream.write(data.getBytes());
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readFromFile(Context context, String fileName) {
String data = "";
int c;
try {
inputStream = context.openFileInput(fileName);
while ((c = inputStream.read()) != -1) {
data = data + Character.toString((char) c);
}
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
}
Your class is already doing what you rquire. It first erases the contents of the file and then writes on it. For further understanding,
When you initiate your stream with MODE_PRIVATE, the second time when you try to write the file, the contents that are already in the file gets erased and the new contents are written.
outputStream = context.openFileOutput(fileName, Context.MODE_PRIVATE);
When you use MODE_APPEND, the contents that are already there stays and the new contents will be appended to the file.
outputStream = context.openFileOutput(fileName, Context.MODE_APPEND);
For more reference and detailed knowledge on dealing with files in Internal storage, I recommend you to watch the below three short videos which gives you detailed description with demo.
http://www.youtube.com/watch?v=Jswr6tkv8ro&index=4&list=PLonJJ3BVjZW5JdoFT0Rlt3ry5Mjp7s8cT
http://www.youtube.com/watch?v=cGxHphBjTBk&index=5&list=PLonJJ3BVjZW5JdoFT0Rlt3ry5Mjp7s8cT
http://www.youtube.com/watch?v=mMcrj_To18k&index=6&list=PLonJJ3BVjZW5JdoFT0Rlt3ry5Mjp7s8cT
Hope it helps! Any more questions, please comment below.
You can just delete the file first with:
File f = new File(filename);
if(f.exists()){
f.delete();
}
And then create a new one with same path/name and write to it.
I'm assuming that your filename is the path to the file on the device.
But probably I'm not getting your real problem?
As a school project, I'm trying to achieve the following:
-List all files (pictures) in a folder.
Go through every picture one by one and password encrypt them using AES.
This is meant as an application to safely encrypt pictures, making only You able to decrypt and view them - provided you have the right password.
So far I am able to get all file names in the folder/directory, and encrypt only one specified file. The problem is, that I don't know how to go through the list, and encrypt all the files to the end.
Here is the code I am currently using:
package com.example.secretpictures;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
public class EncryptService extends Service {
private static final String TAG = EncryptService.class.getSimpleName();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(TAG, "OnCreate");
}
#SuppressLint("SdCardPath")
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d(TAG, "OnStart");
File file[] = Environment.getExternalStorageDirectory().listFiles();
recursiveFileFind(file);
try {
FileInputStream fis = new FileInputStream("/mnt/sdcard/secretpictures/yolo.png");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("/mnt/sdcard/secretpictures/yolo2.enc");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(TAG, "OnDestroy");
}
public void recursiveFileFind(File[] file1){
int i = 0;
String filePath="";
if(file1!=null){
while(i!=file1.length){
filePath = file1[i].getAbsolutePath();
if(file1[i].isDirectory()){
File file[] = file1[i].listFiles();
recursiveFileFind(file);
}
i++;
Log.d(i+"", filePath);
}
}
}
}
As you see, it's very ugly coded, but get's the job done for now.
This service is called when the mainactivity is created.
This line specifies the file to be encrypted: FileInputStream fis = new FileInputStream("/mnt/sdcard/secretpictures/yolo.png");
How would one approach getting the inputstream to go through File file[] = file1[i].listFiles(); to encrypt every and all of the files?
Once you have a File object as shown in your code that finds files you can obtain a FileInputStream for that file using the constructor FileInputStream(File).
Some notes on your crypto system. It isn't very secure. In no particular order
You use a UTF-8 bytes directly without a salt for you key material. Use a key stretching
algorithm like PBKDF2 and feed the password bytes to it with a salt. You can store the salt as plaintext with the encrypted image.
You're using the default cipher spec for AES. This expands to AES/ECB/PKCS5Padding. ECB is not a secure mode for your encrypting more than 1 block of plaintext (16 bytes for AES). ECB fails to hide patterns in the plaintext due to the fact that the same input plaintext results in the same output ciphertext. Images are particularly vulnerable to this due to repeating patterns. See this Wikipedia article for more info on ECB, it also gives an encrypted image as an example. Most other modes you can use (CBC, CTR, etc) required an IV, the IV should be randomly generated and you can store it in the clear with the encrypted image.
I want to be able to copy an excel file from my android app res\raw folder to the client phone's internal storage, and be able to retrieve the data from the excel file and update the excel file in the internal storage as needed. So far all I have is this:
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
--- write files to internal storage and
http://www.vogella.com/articles/JavaExcel/article.html
--- using jexcel to retrieve data from and edit an excel file
I can't seem to be able to link the two. How do I go on implementing this app?
Thanks
For Read and Write To use Apache POI library
To some sample example is there for android through read and write excel sheet
1) Creating/Reading an Excel file in Android
2) Android Read Write EXCEL file using Apache POI
For Assets to SDcard Follow this link Or use this code.
package com.paresh.copyfileassetstoAssets;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
public class CopyFileAssetsToSDCardActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CopyAssets();
}
private void CopyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("Files");
} catch (IOException e) {
Log.e("tag", e.getMessage());
}
for(String filename : files) {
System.out.println("File name => "+filename);
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open("Files/"+filename); // if files resides inside the "Files" directory itself
out = new FileOutputStream(Environment.getExternalStorageDirectory().toString() +"/" + filename);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(Exception e) {
Log.e("tag", e.getMessage());
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
}
Sorry to trouble you, as I am new to Android programming, and i have face the following problem while trying retrieve my send and receive a response from my local host server.
The program seem to auto close when i try to launch it at first. But after implementing
StrictMode.ThreadPolicy policy = new StrictMode.
ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
The program is able to run, however, the data is not parse across.
I have allowed the Internet permission in my android Manifest script.
My Android Codes
package kx.practice;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.widget.TextView;
public class JsonHttpPractice2Activity extends Activity {
TextView tv;
String text;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
StrictMode.ThreadPolicy policy = new StrictMode.
ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
tv = (TextView)findViewById(R.id.textView1);
text = "";
try {
postData();
} catch (JSONException e) {
// TODO Auto-generated catch block
System.out.println("Error in JSON Exception 1");
e.printStackTrace();
}
}
public void postData() throws JSONException{
// Create a new HttpClient and Post Header
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/phpWebservice/AndroidTest.php");
JSONObject json = new JSONObject();
try {
// JSON data:
json.put("name", "Fahmi Rahman");
json.put("position", "sysdev");
JSONArray postjson=new JSONArray();
postjson.put(json);
// Post the data:
httppost.setHeader("json",json.toString());
httppost.getParams().setParameter("jsonpost",postjson);
// Execute HTTP Post Request
System.out.print(json);
HttpResponse response = httpclient.execute(httppost);
// for JSON:
if(response != null)
{
InputStream is = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
text = sb.toString();
System.out.println("This is my text" +text);
}
tv.setText(text);
}catch (ClientProtocolException e) {
System.out.println("Error in JSON Exception 2");
// TODO Auto-generated catch block
} catch (IOException e) {
System.out.println("Error in JSON Exception 3");
// TODO Auto-generated catch block
}
}
}
And lastly, my PHP codes
<?php
$json = $_SERVER['HTTP_JSON'];
echo "JSON: \n";
echo "--------------\n";
var_dump($json);
echo "\n\n";
$data = json_decode($json);
echo "Array: \n";
echo "--------------\n";
var_dump($data);
echo "\n\n";
$name = $data->name;
$pos = $data->position;
echo "Result: \n";
echo "--------------\n";
echo "Name : ".$name."\n Position : ".$pos;
?>
By the way, I got these codes from an online website. However, if these codes are able to work, i should be able to implement it into my project.
You are trying to access the network on the main thread. This is a very bad idea. You need to do the network access in a separate thread instead. The linked article provides several guidelines for doing this.
If you still have problems after moving the network access to a different thread, then feel free to come back and ask more questions.
(The reason your app was killed is because the Android system noticed it hadn't responded for a while, since it was waiting for network traffic.)