]> hydra-www.ietfng.org Git - android-vcpass-oisafe/commitdiff
OI Safe: Refactor decryption routine to work with arbitrary streams.
authorpeli0101 <peli0101@72b678ce-9140-0410-bee8-679b907dd61a>
Mon, 27 Apr 2009 19:33:28 +0000 (19:33 +0000)
committerpeli0101 <peli0101@72b678ce-9140-0410-bee8-679b907dd61a>
Mon, 27 Apr 2009 19:33:28 +0000 (19:33 +0000)
git-svn-id: http://openintents.googlecode.com/svn/trunk/Safe@2052 72b678ce-9140-0410-bee8-679b907dd61a

src/org/openintents/safe/CryptoHelper.java

index 24c52d921d499c18e63e1590405dfef90d79df3a..5c3313421cb038363a9b1a8e937ff932e4983904 100644 (file)
@@ -22,6 +22,7 @@ import java.io.FileNotFoundException;
 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
@@ -731,33 +732,24 @@ public class CryptoHelper {
      * \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
@@ -765,15 +757,82 @@ public class CryptoHelper {
                                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
@@ -805,13 +864,11 @@ public class CryptoHelper {
                                        }\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
@@ -857,37 +914,16 @@ public class CryptoHelper {
                                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