]> source.dussan.org Git - nextcloud-server.git/commitdiff
Made proxy class reuse existing keyfiles not gen new ones;
authorSam Tuke <samtuke@owncloud.com>
Wed, 27 Feb 2013 18:46:44 +0000 (18:46 +0000)
committerSam Tuke <samtuke@owncloud.com>
Wed, 27 Feb 2013 18:46:44 +0000 (18:46 +0000)
Added notes about reusing shareKeys

apps/files_encryption/lib/keymanager.php
apps/files_encryption/lib/proxy.php
apps/files_encryption/lib/util.php

index 62bb12bf90da75003c50bfe06068b30a573b399b..0c2db2be32904a0291e37c850e812dcdfe5ccf2d 100755 (executable)
@@ -368,8 +368,6 @@ class Keymanager {
                        \r
                } else {\r
                        \r
-                       trigger_error("Could not delete shareKey; does not exist: $shareKeyPath");\r
-                       \r
                        \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR );\r
                        \r
                        $result = false;\r
index 92a70499367d167abc8532c3dad66eef0a82163b..c5b1c8154c4aecefe6c929cccf0a25c09108b662 100644 (file)
@@ -93,16 +93,17 @@ class Proxy extends \OC_FileProxy {
        
        public function preFile_put_contents( $path, &$data ) { 
                
-               // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc.
                if ( self::shouldEncrypt( $path ) ) {
                
                        // Stream put contents should have been converted to fopen
                        if ( !is_resource( $data ) ) {
                        
-                               // TODO check who is the owner of the file in case of shared folders
                                $userId = \OCP\USER::getUser();
                                $rootView = new \OC_FilesystemView( '/' );
                                $util = new Util( $rootView, $userId );
+                               $session = new Session();
+                               $fileOwner = \OC\Files\Filesystem::getOwner( $path );
+                               $privateKey = $session->getPrivateKey();
                                $filePath = $util->stripUserFilesPath( $path );
                                // Set the filesize for userland, before encrypting
                                $size = strlen( $data );
@@ -110,45 +111,62 @@ class Proxy extends \OC_FileProxy {
                                // Disable encryption proxy to prevent recursive calls
                                \OC_FileProxy::$enabled = false;
                                
+                               // Check if there is an existing key we can reuse
+                               if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) {
+                               
+                                       $keyPreExists = true;
+                               
+                                       // Decrypt the keyfile
+                                       $plainKey = $util->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey );
+                               
+                               } else {
+                               
+                                       $keyPreExists = false;
+                               
+                                       // Make a new key
+                                       $plainKey = Crypt::generateKey();
+                               
+                               }
+                               
                                // Encrypt data
-                               $encData = Crypt::symmetricEncryptFileContentKeyfile( $data );
+                               $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
                                
                                // Check if the keyfile needs to be shared
-                               if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) {
-                                       
-//                                     $fileOwner = \OC\Files\Filesystem::getOwner( $path );
+                               if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) {
                                        
                                        $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds );
                                        
                                        \OC_FileProxy::$enabled = false;
                                        
                                        // Encrypt plain keyfile to multiple sharefiles
-                                       $multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys );
+                                       $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
                                        
                                        // Save sharekeys to user folders
+                                       // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones
                                        Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
                                        
                                        // Set encrypted keyfile as common varname
                                        $encKey = $multiEncrypted['encrypted'];
-                                       
-                                       
                                
                                } else {
                                
                                        $publicKey = Keymanager::getPublicKey( $rootView, $userId );
                                
                                        // Encrypt plain data to a single user
-                                       $encKey = Crypt::keyEncrypt( $encData['key'], $publicKey );
+                                       $encKey = Crypt::keyEncrypt( $plainKey, $publicKey );
                                
                                }
                                
-                               // TODO: Replace userID with ownerId so keyfile is saved centrally
+                               // Save the key if its new
+                               if ( ! $keyPreExists ) {
                                
-                               // Save keyfile for newly encrypted file in parallel directory tree
-                               Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey );
+                                       // Save keyfile for newly encrypted file in parallel directory tree
+                                       Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey );
+                                       
+                               }
                                
                                // Replace plain content with encrypted content by reference
-                               $data = $encData['encrypted'];
+                               $data = $encData;
                                
                                // Update the file cache with file info
                                \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
index 31ce3a413cc469e712b69ed2a0f3eb3b0ee8df4a..cd223bd70291c6640aef2e1d788211a337bf5338 100644 (file)
@@ -626,25 +626,15 @@ class Util {
        }
        
        /**
-        * @brief Encrypt keyfile to multiple users
-        * @param array $users list of users which should be able to access the file
-        * @param string $filePath path of the file to be shared
+        * @brief Decrypt a keyfile without knowing how it was encrypted
+        * @param string $filePath
+        * @param string $fileOwner
+        * @param string $privateKey
+        * @note Checks whether file was encrypted with openssl_seal or 
+        *       openssl_encrypt, and decrypts accrdingly
         */
-       public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) {
-       
-               // Make sure users are capable of sharing
-               $filteredUids = $this->filterShareReadyUsers( $users );
-               
-               // Get public keys for each user, ready for generating sharekeys
-               $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key
+       public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) {
 
-               \OC_FileProxy::$enabled = false;
-
-               // Get the current users's private key for decrypting existing keyfile
-               $privateKey = $session->getPrivateKey();
-               
-               $fileOwner = \OC\Files\Filesystem::getOwner( $filePath );
-               
                // Get the encrypted keyfile
                // NOTE: the keyfile format depends on how it was encrypted! At
                // this stage we don't know how it was encrypted
@@ -671,6 +661,32 @@ class Util {
                        
                }
                
+               return $plainKeyfile;
+
+       }
+       
+       /**
+        * @brief Encrypt keyfile to multiple users
+        * @param array $users list of users which should be able to access the file
+        * @param string $filePath path of the file to be shared
+        */
+       public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) {
+       
+               // Make sure users are capable of sharing
+               $filteredUids = $this->filterShareReadyUsers( $users );
+               
+               // Get public keys for each user, ready for generating sharekeys
+               $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key
+
+               \OC_FileProxy::$enabled = false;
+
+               // Get the current users's private key for decrypting existing keyfile
+               $privateKey = $session->getPrivateKey();
+               
+               $fileOwner = \OC\Files\Filesystem::getOwner( $filePath );
+               
+               $plainKeyfile = $this->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey );
+               
                // Re-enc keyfile to (additional) sharekeys
                $multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys );