diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index fa293f4512..20045f34b0 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -11,13 +11,13 @@ OC::$CLASSPATH['OCA\Encryption\Session'] = 'apps/files_encryption/lib/session.ph OC_FileProxy::register( new OCA\Encryption\Proxy() ); // User-related hooks -OCP\Util::connectHook( 'OC_User','post_login', 'OCA\Encryption\Hooks', 'login' ); -OCP\Util::connectHook( 'OC_User','post_setPassword','OCA\Encryption\Hooks' ,'setPassphrase' ); +OCP\Util::connectHook( 'OC_User', 'post_login', 'OCA\Encryption\Hooks', 'login' ); +OCP\Util::connectHook( 'OC_User', 'post_setPassword','OCA\Encryption\Hooks', 'setPassphrase' ); // Sharing-related hooks -OCP\Util::connectHook( 'OCP\Share','post_shared','OCA\Encryption\Hooks' ,'postShared' ); -OCP\Util::connectHook( 'OCP\Share','pre_unshare','OCA\Encryption\Hooks' ,'preUnshare' ); -OCP\Util::connectHook( 'OCP\Share','pre_unshareAll','OCA\Encryption\Hooks' ,'preUnshareAll' ); +OCP\Util::connectHook( 'OCP\Share', 'post_shared', 'OCA\Encryption\Hooks', 'postShared' ); +OCP\Util::connectHook( 'OCP\Share', 'pre_unshare', 'OCA\Encryption\Hooks', 'preUnshare' ); +OCP\Util::connectHook( 'OCP\Share', 'pre_unshareAll', 'OCA\Encryption\Hooks', 'preUnshareAll' ); // Webdav-related hooks OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfile' ); @@ -27,9 +27,9 @@ stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' ); $session = new OCA\Encryption\Session(); if ( -! $session->getPrivateKey( \OCP\USER::getUser() ) -&& OCP\User::isLoggedIn() -&& OCA\Encryption\Crypt::mode() == 'server' + ! $session->getPrivateKey( \OCP\USER::getUser() ) + && OCP\User::isLoggedIn() + && OCA\Encryption\Crypt::mode() == 'server' ) { // Force the user to log-in again if the encryption key isn't unlocked diff --git a/apps/files_encryption/appinfo/spec.txt b/apps/files_encryption/appinfo/spec.txt new file mode 100644 index 0000000000..ab248be64d --- /dev/null +++ b/apps/files_encryption/appinfo/spec.txt @@ -0,0 +1,7 @@ +Notes +----- + +- The user passphrase is required in order to set up or upgrade the app. New + keypair generation, and the re-encryption of legacy encrypted files requires + it. Therefore an appinfo/update.php script cannot be used, and upgrade logic + is handled in the login hook listener. \ No newline at end of file diff --git a/apps/files_encryption/appinfo/version b/apps/files_encryption/appinfo/version index 7dff5b8921..1d71ef9744 100644 --- a/apps/files_encryption/appinfo/version +++ b/apps/files_encryption/appinfo/version @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.3 \ No newline at end of file diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index ecceae352b..73d7957541 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -1,4 +1,5 @@ ready() ) { - \OC_Log::write( 'Encryption library', 'User account "' . $params['uid'] . '" is not ready for encryption; configuration started' , \OC_Log::DEBUG ); + \OC_Log::write( 'Encryption library', 'User account "' . $params['uid'] . '" is not ready for encryption; configuration started', \OC_Log::DEBUG ); return $util->setupServerSide( $params['password'] ); @@ -58,8 +58,6 @@ class Hooks { \OC_FileProxy::$enabled = true; - # TODO: dont manually encrypt the private keyfile - use the config options of openssl_pkey_export instead for better mobile compatibility - $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); $session = new Session(); @@ -71,14 +69,22 @@ class Hooks { // Set legacy encryption key if it exists, to support // depreciated encryption system if ( - $view1->file_exists( 'encryption.key' ) - && $legacyKey = $view1->file_get_contents( 'encryption.key' ) + $view1->file_exists( 'encryption.key' ) + && $encLegacyKey = $view1->file_get_contents( 'encryption.key' ) ) { - $_SESSION['legacyenckey'] = Crypt::legacyDecrypt( $legacyKey, $params['password'] ); + $plainLegacyKey = Crypt::legacyDecrypt( $encLegacyKey, $params['password'] ); + + $session->setLegacyKey( $plainLegacyKey ); } -// } + + $publicKey = Keymanager::getPublicKey( $view, $params['uid'] ); + + // Encrypt existing user files: + // This serves to upgrade old versions of the encryption + // app (see appinfo/spec.txt + $this->encryptAll( $publicKey, $this->userFilesDir, $session->getLegacyKey(), $params['password'] ); return true; @@ -104,9 +110,9 @@ class Hooks { // Save private key Keymanager::setPrivateKey( $encryptedPrivateKey ); - # NOTE: Session does not need to be updated as the - # private key has not changed, only the passphrase - # used to decrypt it has changed + // NOTE: Session does not need to be updated as the + // private key has not changed, only the passphrase + // used to decrypt it has changed } @@ -179,5 +185,3 @@ class Hooks { } } - -?> \ No newline at end of file diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 2591e90227..9d4f5a1fae 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -1,4 +1,5 @@ password change faster -// - IMPORTANT! Check if the block lenght of the encrypted data stays the same +// - Add a setting "Don´t encrypt files larger than xx because of performance" +// - Don't use a password directly as encryption key. but a key which is +// stored on the server and encrypted with the user password. -> change pass +// faster /** * Class for common cryptography functionality @@ -93,7 +92,10 @@ class Crypt { * @brief Add arbitrary padding to encrypted data * @param string $data data to be padded * @return padded data - * @note In order to end up with data exactly 8192 bytes long we must add two letters. It is impossible to achieve exactly 8192 length blocks with encryption alone, hence padding is added to achieve the required length. + * @note In order to end up with data exactly 8192 bytes long we must + * add two letters. It is impossible to achieve exactly 8192 length + * blocks with encryption alone, hence padding is added to achieve the + * required length. */ public static function addPadding( $data ) { @@ -118,7 +120,7 @@ class Crypt { } else { - # TODO: log the fact that unpadded data was submitted for removal of padding + // TODO: log the fact that unpadded data was submitted for removal of padding return false; } @@ -168,7 +170,7 @@ class Crypt { */ public static function isEncryptedMeta( $path ) { - # TODO: Use DI to get OC_FileCache_Cached out of here + // TODO: Use DI to get OC_FileCache_Cached out of here // Fetch all file metadata from DB $metadata = \OC_FileCache_Cached::get( $path, '' ); @@ -187,12 +189,14 @@ class Crypt { // Fetch all file metadata from DB $metadata = \OC_FileCache_Cached::get( $content, '' ); - // If a file is flagged with encryption in DB, but isn't a valid content + IV combination, it's probably using the legacy encryption system + // If a file is flagged with encryption in DB, but isn't a + // valid content + IV combination, it's probably using the + // legacy encryption system if ( $content and isset( $metadata['encrypted'] ) and $metadata['encrypted'] === true - and !self::isCatfile( $content ) + and ! self::isCatfile( $content ) ) { return true; @@ -217,7 +221,7 @@ class Crypt { } else { - \OC_Log::write( 'Encryption library', 'Encryption (symmetric) of content failed' , \OC_Log::ERROR ); + \OC_Log::write( 'Encryption library', 'Encryption (symmetric) of content failed', \OC_Log::ERROR ); return false; @@ -313,7 +317,7 @@ class Crypt { } else { - \OC_Log::write( 'Encryption library', 'Encryption (symmetric) of keyfile content failed' , \OC_Log::ERROR ); + \OC_Log::write( 'Encryption library', 'Encryption (symmetric) of keyfile content failed', \OC_Log::ERROR ); return false; @@ -431,7 +435,7 @@ class Crypt { } else { - \OC_Log::write( 'Encryption library', 'Decryption (asymmetric) of sealed content failed' , \OC_Log::ERROR ); + \OC_Log::write( 'Encryption library', 'Decryption (asymmetric) of sealed content failed', \OC_Log::ERROR ); return false; @@ -579,7 +583,7 @@ class Crypt { if ( !$strong ) { // If OpenSSL indicates randomness is insecure, log error - \OC_Log::write( 'Encryption library', 'Insecure symmetric key was generated using openssl_random_pseudo_bytes()' , \OC_Log::WARN ); + \OC_Log::write( 'Encryption library', 'Insecure symmetric key was generated using openssl_random_pseudo_bytes()', \OC_Log::WARN ); } @@ -623,18 +627,27 @@ class Crypt { } - public static function changekeypasscode($oldPassword, $newPassword) { + public static function changekeypasscode( $oldPassword, $newPassword ) { - if(\OCP\User::isLoggedIn()){ + if ( \OCP\User::isLoggedIn() ) { + $key = Keymanager::getPrivateKey( $user, $view ); - if ( ($key = Crypt::symmetricDecryptFileContent($key,$oldpasswd)) ) { - if ( ($key = Crypt::symmetricEncryptFileContent($key, $newpasswd)) ) { - Keymanager::setPrivateKey($key); + + if ( ( $key = Crypt::symmetricDecryptFileContent($key,$oldpasswd) ) ) { + + if ( ( $key = Crypt::symmetricEncryptFileContent( $key, $newpasswd ) ) ) { + + Keymanager::setPrivateKey( $key ); + return true; } + } + } + return false; + } /** @@ -725,10 +738,8 @@ class Crypt { */ public static function legacyRecrypt( $legacyContent, $legacyPassphrase, $newPassphrase ) { - # TODO: write me + // TODO: write me } -} - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index c6669081a2..301e5b33fd 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -1,5 +1,6 @@ unlink( $keypath . '.key' ); diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 6f00bd13b4..025af3c7f1 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -42,8 +42,8 @@ class Proxy extends \OC_FileProxy { if ( is_null( self::$enableEncryption ) ) { if ( - \OCP\Config::getAppValue( 'files_encryption', 'enable_encryption', 'true' ) == 'true' - && Crypt::mode() == 'server' + \OCP\Config::getAppValue( 'files_encryption', 'enable_encryption', 'true' ) == 'true' + && Crypt::mode() == 'server' ) { self::$enableEncryption = true; @@ -64,7 +64,7 @@ class Proxy extends \OC_FileProxy { if ( is_null(self::$blackList ) ) { - self::$blackList = explode(',', \OCP\Config::getAppValue( 'files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg' ) ); + self::$blackList = explode(',', \OCP\Config::getAppValue( 'files_encryption', 'type_blacklist', 'jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg' ) ); } @@ -74,9 +74,9 @@ class Proxy extends \OC_FileProxy { } - $extension = substr( $path, strrpos( $path,'.' ) +1 ); + $extension = substr( $path, strrpos( $path, '.' ) +1 ); - if ( array_search( $extension, self::$blackList ) === false ){ + if ( array_search( $extension, self::$blackList ) === false ) { return true; @@ -101,7 +101,7 @@ class Proxy extends \OC_FileProxy { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - # TODO: Check if file is shared, if so, use multiKeyEncrypt + // TODO: Check if file is shared, if so, use multiKeyEncrypt // Encrypt plain data and fetch key $encrypted = Crypt::keyEncryptKeyfile( $data, Keymanager::getPublicKey( $rootView, $userId ) ); @@ -115,7 +115,7 @@ class Proxy extends \OC_FileProxy { $filePath = '/' . implode( '/', $filePath ); - # TODO: make keyfile dir dynamic from app config + // TODO: make keyfile dir dynamic from app config $view = new \OC_FilesystemView( '/' ); @@ -139,15 +139,15 @@ class Proxy extends \OC_FileProxy { */ public function postFile_get_contents( $path, $data ) { - # TODO: Use dependency injection to add required args for view and user etc. to this method + // TODO: Use dependency injection to add required args for view and user etc. to this method // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; // If data is a catfile if ( - Crypt::mode() == 'server' - && Crypt::isCatfile( $data ) + Crypt::mode() == 'server' + && Crypt::isCatfile( $data ) ) { $split = explode( '/', $path ); @@ -162,7 +162,7 @@ class Proxy extends \OC_FileProxy { $userId = \OCP\USER::getUser(); - # TODO: Check if file is shared, if so, use multiKeyDecrypt + // TODO: Check if file is shared, if so, use multiKeyDecrypt $encryptedKeyfile = Keymanager::getFileKey( $view, $userId, $filePath ); @@ -215,8 +215,8 @@ class Proxy extends \OC_FileProxy { // If file is already encrypted, decrypt using crypto protocol if ( - Crypt::mode() == 'server' - && $util->isEncryptedPath( $path ) + Crypt::mode() == 'server' + && $util->isEncryptedPath( $path ) ) { // Close the original encrypted file @@ -228,9 +228,9 @@ class Proxy extends \OC_FileProxy { } elseif ( - self::shouldEncrypt( $path ) - and $meta ['mode'] != 'r' - and $meta['mode'] != 'rb' + self::shouldEncrypt( $path ) + and $meta ['mode'] != 'r' + and $meta['mode'] != 'rb' ) { // If the file is not yet encrypted, but should be // encrypted when it's saved (it's not read only) @@ -268,27 +268,43 @@ class Proxy extends \OC_FileProxy { } - public function postGetMimeType($path,$mime){ - if( Crypt::isCatfile($path)){ - $mime = \OCP\Files::getMimeType('crypt://'.$path,'w'); + public function postGetMimeType( $path, $mime ) { + + if ( Crypt::isCatfile( $path ) ) { + + $mime = \OCP\Files::getMimeType( 'crypt://' . $path, 'w' ); + } + return $mime; + } - public function postStat($path,$data){ - if( Crypt::isCatfile($path)){ - $cached= \OC_FileCache_Cached::get($path,''); - $data['size']=$cached['size']; + public function postStat( $path, $data ) { + + if ( Crypt::isCatfile( $path ) ) { + + $cached = \OC_FileCache_Cached::get( $path, '' ); + + $data['size'] = $cached['size']; + } + return $data; } - public function postFileSize($path,$size){ - if( Crypt::isCatfile($path)){ - $cached = \OC_FileCache_Cached::get($path,''); + public function postFileSize( $path, $size ) { + + if ( Crypt::isCatfile( $path ) ) { + + $cached = \OC_FileCache_Cached::get( $path, '' ); + return $cached['size']; - }else{ + + } else { + return $size; + } } } diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 85d533fde7..4abc8be689 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -29,11 +29,11 @@ namespace OCA\Encryption; class Session { /** - * @brief Sets user id for session and triggers emit + * @brief Sets user private key to session * @return bool * */ - public function setPrivateKey( $privateKey, $userId ) { + public function setPrivateKey( $privateKey ) { $_SESSION['privateKey'] = $privateKey; @@ -42,15 +42,15 @@ class Session { } /** - * @brief Gets user id for session and triggers emit + * @brief Gets user private key from session * @returns string $privateKey The user's plaintext private key * */ - public function getPrivateKey( $userId ) { + public function getPrivateKey() { if ( - isset( $_SESSION['privateKey'] ) - && !empty( $_SESSION['privateKey'] ) + isset( $_SESSION['privateKey'] ) + && !empty( $_SESSION['privateKey'] ) ) { return $_SESSION['privateKey']; @@ -62,5 +62,40 @@ class Session { } } + + /** + * @brief Sets user legacy key to session + * @return bool + * + */ + public function setLegacyKey( $legacyKey ) { + + $_SESSION['legacyKey'] = $LegacyKey; + + return true; + + } + + /** + * @brief Gets user legacy key from session + * @returns string $legacyKey The user's plaintext legacy key + * + */ + public function getLegacyKey() { + + if ( + isset( $_SESSION['legacyKey'] ) + && !empty( $_SESSION['legacyKey'] ) + ) { + + return $_SESSION['legacyKey']; + + } else { + + return false; + + } + + } } \ No newline at end of file diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index a17a4514fa..f634db7a38 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -49,9 +49,10 @@ class Stream { public static $sourceStreams = array(); - # TODO: make all below properties private again once unit testing is configured correctly + // TODO: make all below properties private again once unit testing is + // configured correctly public $rawPath; // The raw path received by stream_open - public $path_f; // The raw path formatted to include username and data directory + public $path_f; // The raw path formatted to include username and data dir private $userId; private $handle; // Resource returned by fopen private $path; @@ -235,10 +236,12 @@ class Stream { */ public function getKey() { - // If a keyfile already exists for a file named identically to file to be written + // If a keyfile already exists for a file named identically to + // file to be written if ( self::$view->file_exists( $this->userId . '/'. 'files_encryption' . '/' . 'keyfiles' . '/' . $this->rawPath . '.key' ) ) { - # TODO: add error handling for when file exists but no keyfile + // TODO: add error handling for when file exists but no + // keyfile // Fetch existing keyfile $this->encKeyfile = Keymanager::getFileKey( $this->rootView, $this->userId, $this->rawPath ); @@ -266,13 +269,14 @@ class Stream { // Only get the user again if it isn't already set if ( empty( $this->userId ) ) { - # TODO: Move this user call out of here - it belongs elsewhere + // TODO: Move this user call out of here - it belongs + // elsewhere $this->userId = \OCP\User::getUser(); } - # TODO: Add a method for getting the user in case OCP\User:: - # getUser() doesn't work (can that scenario ever occur?) + // TODO: Add a method for getting the user in case OCP\User:: + // getUser() doesn't work (can that scenario ever occur?) } @@ -287,7 +291,10 @@ class Stream { */ public function stream_write( $data ) { - // Disable the file proxies so that encryption is not automatically attempted when the file is written to disk - we are handling that separately here and we don't want to get into an infinite loop + // Disable the file proxies so that encryption is not + // automatically attempted when the file is written to disk - + // we are handling that separately here and we don't want to + // get into an infinite loop \OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling @@ -296,14 +303,15 @@ class Stream { // So far this round, no data has been written $written = 0; - // Find out where we are up to in the writing of data to the file + // Find out where we are up to in the writing of data to the + // file $pointer = ftell( $this->handle ); // Make sure the userId is set $this->getuser(); - # TODO: Check if file is shared, if so, use multiKeyEncrypt and - # save shareKeys in necessary user directories + // TODO: Check if file is shared, if so, use multiKeyEncrypt and + // save shareKeys in necessary user directories // Get / generate the keyfile for the file we're handling // If we're writing a new file (not overwriting an existing @@ -324,19 +332,24 @@ class Stream { } - // If extra data is left over from the last round, make sure it is integrated into the next 6126 / 8192 block + // If extra data is left over from the last round, make sure it + // is integrated into the next 6126 / 8192 block if ( $this->writeCache ) { // Concat writeCache to start of $data $data = $this->writeCache . $data; - // Clear the write cache, ready for resuse - it has been flushed and its old contents processed + // Clear the write cache, ready for resuse - it has been + // flushed and its old contents processed $this->writeCache = ''; } // // // Make sure we always start on a block start - if ( 0 != ( $pointer % 8192 ) ) { // if the current positoin of file indicator is not aligned to a 8192 byte block, fix it so that it is + if ( 0 != ( $pointer % 8192 ) ) { + // if the current positoin of + // file indicator is not aligned to a 8192 byte block, fix it + // so that it is // fseek( $this->handle, - ( $pointer % 8192 ), SEEK_CUR ); // @@ -361,14 +374,22 @@ class Stream { // // While there still remains somed data to be processed & written while( strlen( $data ) > 0 ) { // -// // Remaining length for this iteration, not of the entire file (may be greater than 8192 bytes) +// // Remaining length for this iteration, not of the +// // entire file (may be greater than 8192 bytes) // $remainingLength = strlen( $data ); // -// // If data remaining to be written is less than the size of 1 6126 byte block +// // If data remaining to be written is less than the +// // size of 1 6126 byte block if ( strlen( $data ) < 6126 ) { // Set writeCache to contents of $data - // The writeCache will be carried over to the next write round, and added to the start of $data to ensure that written blocks are always the correct length. If there is still data in writeCache after the writing round has finished, then the data will be written to disk by $this->flush(). + // The writeCache will be carried over to the + // next write round, and added to the start of + // $data to ensure that written blocks are + // always the correct length. If there is still + // data in writeCache after the writing round + // has finished, then the data will be written + // to disk by $this->flush(). $this->writeCache = $data; // Clear $data ready for next round @@ -381,13 +402,17 @@ class Stream { $encrypted = $this->preWriteEncrypt( $chunk, $this->keyfile ); - // Write the data chunk to disk. This will be addended to the last data chunk if the file being handled totals more than 6126 bytes + // Write the data chunk to disk. This will be + // addended to the last data chunk if the file + // being handled totals more than 6126 bytes fwrite( $this->handle, $encrypted ); $writtenLen = strlen( $encrypted ); //fseek( $this->handle, $writtenLen, SEEK_CUR ); - // Remove the chunk we just processed from $data, leaving only unprocessed data in $data var, for handling on the next round + // Remove the chunk we just processed from + // $data, leaving only unprocessed data in $data + // var, for handling on the next round $data = substr( $data, 6126 ); } @@ -401,16 +426,16 @@ class Stream { } - public function stream_set_option($option,$arg1,$arg2) { + public function stream_set_option( $option, $arg1, $arg2 ) { switch($option) { case STREAM_OPTION_BLOCKING: - stream_set_blocking($this->handle,$arg1); + stream_set_blocking( $this->handle, $arg1 ); break; case STREAM_OPTION_READ_TIMEOUT: - stream_set_timeout($this->handle,$arg1,$arg2); + stream_set_timeout( $this->handle, $arg1, $arg2 ); break; case STREAM_OPTION_WRITE_BUFFER: - stream_set_write_buffer($this->handle,$arg1,$arg2); + stream_set_write_buffer( $this->handle, $arg1, $arg2 ); } } @@ -418,13 +443,14 @@ class Stream { return fstat($this->handle); } - public function stream_lock($mode) { - flock($this->handle,$mode); + public function stream_lock( $mode ) { + flock( $this->handle, $mode ); } public function stream_flush() { - return fflush($this->handle); // Not a typo: http://php.net/manual/en/function.fflush.php + return fflush( $this->handle ); + // Not a typo: http://php.net/manual/en/function.fflush.php } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index f70839e39f..fd4d7a9fcc 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -24,9 +24,13 @@ // Todo: // - Crypt/decrypt button in the userinterface // - Setting if crypto should be on by default -// - Add a setting "Don´t encrypt files larger than xx because of performance reasons" -// - Transparent decrypt/encrypt in filesystem.php. Autodetect if a file is encrypted (.encrypted extension) -// - Don't use a password directly as encryption key. but a key which is stored on the server and encrypted with the user password. -> password change faster +// - Add a setting "Don´t encrypt files larger than xx because of performance +// reasons" +// - Transparent decrypt/encrypt in filesystem.php. Autodetect if a file is +// encrypted (.encrypted extension) +// - Don't use a password directly as encryption key. but a key which is +// stored on the server and encrypted with the user password. -> password +// change faster // - IMPORTANT! Check if the block lenght of the encrypted data stays the same namespace OCA\Encryption; @@ -41,56 +45,57 @@ namespace OCA\Encryption; class Util { - # Web UI: + // Web UI: - ## DONE: files created via web ui are encrypted - ## DONE: file created & encrypted via web ui are readable in web ui - ## DONE: file created & encrypted via web ui are readable via webdav + //// DONE: files created via web ui are encrypted + //// DONE: file created & encrypted via web ui are readable in web ui + //// DONE: file created & encrypted via web ui are readable via webdav - # WebDAV: + // WebDAV: - ## DONE: new data filled files added via webdav get encrypted - ## DONE: new data filled files added via webdav are readable via webdav - ## DONE: reading unencrypted files when encryption is enabled works via webdav - ## DONE: files created & encrypted via web ui are readable via webdav + //// DONE: new data filled files added via webdav get encrypted + //// DONE: new data filled files added via webdav are readable via webdav + //// DONE: reading unencrypted files when encryption is enabled works via + //// webdav + //// DONE: files created & encrypted via web ui are readable via webdav - # Legacy support: + // Legacy support: - ## DONE: add method to check if file is encrypted using new system - ## DONE: add method to check if file is encrypted using old system - ## DONE: add method to fetch legacy key - ## DONE: add method to decrypt legacy encrypted data + //// DONE: add method to check if file is encrypted using new system + //// DONE: add method to check if file is encrypted using old system + //// DONE: add method to fetch legacy key + //// DONE: add method to decrypt legacy encrypted data - ## TODO: add method to encrypt all user files using new system - ## TODO: add method to decrypt all user files using new system - ## TODO: add method to encrypt all user files using old system - ## TODO: add method to decrypt all user files using old system + //// TODO: add method to encrypt all user files using new system + //// TODO: add method to decrypt all user files using new system + //// TODO: add method to encrypt all user files using old system + //// TODO: add method to decrypt all user files using old system - # Admin UI: + // Admin UI: - ## DONE: changing user password also changes encryption passphrase + //// DONE: changing user password also changes encryption passphrase - ## TODO: add support for optional recovery in case of lost passphrase / keys - ## TODO: add admin optional required long passphrase for users - ## TODO: add UI buttons for encrypt / decrypt everything - ## TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. + //// TODO: add support for optional recovery in case of lost passphrase / keys + //// TODO: add admin optional required long passphrase for users + //// TODO: add UI buttons for encrypt / decrypt everything + //// TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. - # Sharing: + // Sharing: - ## TODO: add support for encrypting to multiple public keys - ## TODO: add support for decrypting to multiple private keys + //// TODO: add support for encrypting to multiple public keys + //// TODO: add support for decrypting to multiple private keys - # Integration testing: + // Integration testing: - ## TODO: test new encryption with webdav - ## TODO: test new encryption with versioning - ## TODO: test new encryption with sharing - ## TODO: test new encryption with proxies + //// TODO: test new encryption with webdav + //// TODO: test new encryption with versioning + //// TODO: test new encryption with sharing + //// TODO: test new encryption with proxies private $view; // OC_FilesystemView object for filesystem operations @@ -190,8 +195,8 @@ class Util { // Create user keypair if ( - ! $this->view->file_exists( $this->publicKeyPath ) - or ! $this->view->file_exists( $this->privateKeyPath ) + ! $this->view->file_exists( $this->publicKeyPath ) + or ! $this->view->file_exists( $this->privateKeyPath ) ) { // Generate keypair @@ -212,11 +217,6 @@ class Util { } - $publicKey = Keymanager::getPublicKey( $this->view, $this->userId ); - - // Encrypt existing user files: - $this->encryptAll( $publicKey, $this->userFilesDir ); - return true; } @@ -235,8 +235,8 @@ class Util { $found = array( 'plain' => array(), 'encrypted' => array(), 'legacy' => array() ); if ( - $this->view->is_dir( $directory ) - && $handle = $this->view->opendir( $directory ) + $this->view->is_dir( $directory ) + && $handle = $this->view->opendir( $directory ) ) { while ( false !== ( $file = readdir( $handle ) ) ) { @@ -330,7 +330,7 @@ class Util { * @param string $dirPath the directory whose files will be encrypted * @note Encryption is recursive */ - public function encryptAll( $publicKey, $dirPath ) { + public function encryptAll( $publicKey, $dirPath, $legacyPassphrase = null, $newPassphrase = null ) { if ( $found = $this->findFiles( $dirPath ) ) { @@ -353,20 +353,27 @@ class Util { // FIXME: Legacy recrypting here isn't finished yet // Encrypt legacy encrypted files - foreach ( $found['legacy'] as $legacyFilePath ) { + if ( + ! empty( $legacyPassphrase ) + && ! empty( $newPassphrase ) + ) { - // Fetch data from file - $legacyData = $this->view->file_get_contents( $legacyFilePath ); - - // Recrypt data, generate catfile - $recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKey, $newPassphrase ); + foreach ( $found['legacy'] as $legacyFilePath ) { - // Save catfile - Keymanager::setFileKey( $this->view, $plainFilePath, $this->userId, $recrypted['key'] ); + // Fetch data from file + $legacyData = $this->view->file_get_contents( $legacyFilePath ); + + // Recrypt data, generate catfile + $recrypted = Crypt::legacyKeyRecryptKeyfile( $legacyData, $legacyPassphrase, $publicKey, $newPassphrase ); + + // Save catfile + Keymanager::setFileKey( $this->view, $plainFilePath, $this->userId, $recrypted['key'] ); + + // Overwrite the existing file with the encrypted one + $this->view->file_put_contents( $plainFilePath, $recrypted['data'] ); + + } - // Overwrite the existing file with the encrypted one - $this->view->file_put_contents( $plainFilePath, $recrypted['data'] ); - } } diff --git a/apps/files_encryption/templates/settings-personal.php b/apps/files_encryption/templates/settings-personal.php index c8144da563..ad34a0d78b 100644 --- a/apps/files_encryption/templates/settings-personal.php +++ b/apps/files_encryption/templates/settings-personal.php @@ -1,6 +1,6 @@
- t('Choose encryption mode:'); ?> + t( 'Choose encryption mode:' ); ?>

+ style="width:20px;" /> - t('Server side encryption (allows you to access your files from the web interface)'); ?> + t( 'Server side encryption (allows you to access your files from the web interface)' ); ?>
+ /> - t('None (no encryption at all)'); ?> + t( 'None (no encryption at all)' ); ?>

diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php index 17ac1fd224..f7ef8a8efe 100644 --- a/apps/files_encryption/templates/settings.php +++ b/apps/files_encryption/templates/settings.php @@ -2,17 +2,17 @@

- t('Encryption'); ?> + t( 'Encryption' ); ?> - t("Exclude the following file types from encryption:"); ?> + t( "Exclude the following file types from encryption:" ); ?>