import java.io.FileOutputStream;\r
import java.io.IOException;\r
import java.io.InputStream;\r
+import java.io.OutputStream;\r
import java.security.DigestInputStream;\r
import java.security.InvalidAlgorithmParameterException;\r
import java.security.InvalidKeyException;\r
* \r
* @param ctx Context of activity in order to store temp file\r
* @param fileUri Uri to either a stream or a file to read from\r
+ * @param useContentProvider true for using Content Provider,\r
+ * false for creating a file without ".oisafe" extension and\r
+ * deleting the original file.\r
* @return If decryption is successful, returns Uri of a content \r
* provider to read the plaintext file. Upon failure,\r
* return null.\r
* @throws Exception\r
*/\r
public Uri decryptFileWithSessionKey(Context ctx, Uri fileUri) throws CryptoHelperException {\r
- Log.d(TAG, "decryptFileWithSessionKey");\r
- Log.d(TAG, "fileUri="+fileUri.toString());\r
- ContentResolver contentResolver = ctx.getContentResolver();\r
- status=false; // assume failure\r
- if(password == null) {\r
- String msg = "Must call setPassword before running decrypt.";\r
- throw new CryptoHelperException(msg);\r
- }\r
-\r
- String decryptSession;\r
- try {\r
- // create a random session name\r
- decryptSession=generateSalt();\r
- } catch (NoSuchAlgorithmException e1) {\r
- e1.printStackTrace();\r
- String msg = "Decrypt error: "+e1.getLocalizedMessage();\r
- throw new CryptoHelperException(msg);\r
- }\r
- String sessionFile = "";\r
- try {\r
- InputStream is;\r
+ Log.d(TAG, "fileUri="+fileUri.toString());\r
+ ContentResolver contentResolver = ctx.getContentResolver();\r
+ \r
+ String sessionFile = "";\r
+ Uri resultUri = null;\r
+ boolean result = false;\r
+ \r
+ try {\r
+ InputStream is;\r
if (fileUri.getScheme().equals("file")) {\r
is = new java.io.FileInputStream(fileUri.getPath());\r
if (debug) Log.d(TAG, "Decrypt: Input from " + fileUri.getPath());\r
is = contentResolver.openInputStream(fileUri);\r
if (debug) Log.d(TAG, "Decrypt: Input from " + fileUri.toString());\r
}\r
+ FileOutputStream os = null;\r
+ \r
+ String decryptSession;\r
+ try {\r
+ // create a random session name\r
+ decryptSession=generateSalt();\r
+ } catch (NoSuchAlgorithmException e1) {\r
+ e1.printStackTrace();\r
+ String msg = "Decrypt error: "+e1.getLocalizedMessage();\r
+ throw new CryptoHelperException(msg);\r
+ }\r
sessionFile = CryptoContentProvider.SESSION_FILE+"."+decryptSession;\r
if (debug) Log.d(TAG, "Decrypt: Output to " + sessionFile);\r
- \r
+ \r
// openFileOutput creates a file in /data/data/{packagename}/files/\r
// In our case, /data/data/org.openintents.safe/files/\r
// This file is owned and only readable by our application\r
- FileOutputStream os = ctx.openFileOutput(sessionFile,\r
- Context.MODE_PRIVATE);\r
+ os = ctx.openFileOutput(sessionFile,\r
+ Context.MODE_PRIVATE);\r
+ \r
+ // after writing the decrypted content to a temporary file,\r
+ // pass back a Uri that can be used to read back the contents\r
+ resultUri = Uri.withAppendedPath(CryptoContentProvider.CONTENT_URI, "decrypt/" + decryptSession);\r
+ \r
+ result = decryptStreamWithSessionKey(ctx, is, os);\r
\r
+ // Close the input stream\r
+ is.close();\r
+ os.close();\r
+\r
+ } catch (FileNotFoundException e) {\r
+ Log.e(TAG, "File not found", e);\r
+ } catch (IOException e) {\r
+ Log.e(TAG, "IOException", e);\r
+ }\r
+\r
+ // Securely delete the original file:\r
+ \r
+ // TODO Peli: Only delete if this is not a decryption through ContentProvider.\r
+ // SecureDelete.delete(new File(fileUri.getPath()));\r
+\r
+\r
+ if (result == false) {\r
+ resultUri = null;\r
+ \r
+ // Unsuccessful. Clean up\r
+ ctx.deleteFile(sessionFile);\r
+ }\r
+ \r
+ return resultUri;\r
+ }\r
+ \r
+ /**\r
+ * Unencrypt a file previously encrypted with\r
+ * encryptFileWithSessionKey().\r
+ * \r
+ * @author Peli\r
+ * \r
+ * @param ctx Context of activity in order to store temp file\r
+ * @param fileUri Uri to either a stream or a file to read from\r
+ * @param useContentProvider true for using Content Provider,\r
+ * false for creating a file without ".oisafe" extension and\r
+ * deleting the original file.\r
+ * @return True if successful, otherwise false.\r
+ * @throws Exception\r
+ */\r
+ public boolean decryptStreamWithSessionKey(Context ctx, InputStream is, OutputStream os) throws CryptoHelperException {\r
+ if (debug) Log.d(TAG, "decryptStreamWithSessionKey");\r
+ status=false; // assume failure\r
+ if(password == null) {\r
+ String msg = "Must call setPassword before running decrypt.";\r
+ throw new CryptoHelperException(msg);\r
+ }\r
+\r
+ try {\r
+ \r
int numReadTotal = 0;\r
int numRead = 0;\r
\r
}\r
} else {\r
Log.e(TAG, "Unknown cipher version" + cipherVersion);\r
- ctx.deleteFile(sessionFile);\r
- return null;\r
+ return false;\r
}\r
} catch (IndexOutOfBoundsException e) {\r
Log.e(TAG, "Invalid ciphertext (with session key)");\r
- ctx.deleteFile(sessionFile);\r
- return null;\r
+ return false;\r
}\r
\r
// Decrypt the session key\r
if (offset < is.available()) {\r
throw new IOException("Could not completely read file ");\r
}\r
- \r
- // Close the input stream and return bytes\r
- is.close();\r
- os.close();\r
-\r
- // Securely delete the original file:\r
- \r
- // TODO Peli: Only delete if this is not a decryption through ContentProvider.\r
- // SecureDelete.delete(new File(fileUri.getPath()));\r
-\r
status=true;\r
\r
} catch (ESJException e) {\r
Log.e(TAG, "Error decrypting file", e);\r
}\r
\r
- } catch (FileNotFoundException e) {\r
-// Log.e(TAG, "File not found", e);\r
} catch (IOException e) {\r
Log.e(TAG, "IOException", e);\r
}\r
- if (status==false) {\r
- if (sessionFile.length()!=0) {\r
- if (debug) Log.d(TAG,"status==false, deleting sessionFile:"+sessionFile);\r
- ctx.deleteFile(sessionFile);\r
- }\r
- return null;\r
- }\r
- // after writing the decrypted content to a temporary file,\r
- // pass back a Uri that can be used to read back the contents\r
- Uri uri=Uri.withAppendedPath(CryptoContentProvider.CONTENT_URI, "decrypt/" + decryptSession);\r
- return uri;\r
+ \r
+ return status;\r
}\r
}\r