diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 6c082b1938..45f43d70ff 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -6,7 +6,6 @@ OC::$CLASSPATH['OCA\Encryption\Util'] = 'apps/files_encryption/lib/util.php'; OC::$CLASSPATH['OCA\Encryption\Keymanager'] = 'apps/files_encryption/lib/keymanager.php'; OC::$CLASSPATH['OCA\Encryption\Stream'] = 'apps/files_encryption/lib/stream.php'; OC::$CLASSPATH['OCA\Encryption\Proxy'] = 'apps/files_encryption/lib/proxy.php'; -OC::$CLASSPATH['OCA\Encryption\Session'] = 'apps/files_encryption/lib/session.php'; OC_FileProxy::register(new OCA\Encryption\Proxy()); @@ -16,13 +15,7 @@ OCP\Util::connectHook('OC_User','post_setPassword','OCA\Encryption\Hooks','setPa 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' -) { +if( !isset( $_SESSION['enckey'] ) && OCP\User::isLoggedIn() && OCA\Encryption\Crypt::mode() == 'server' ) { // Force the user to re-log in if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled) OCP\User::logout(); diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 8e391ca388..5cb59dbbf8 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -70,11 +70,11 @@ class Hooks { // trigger_error( "\$params['password'] = {$params['password']}" ); - $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); + $_SESSION['enckey'] = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); - $session = new Session(); - - $session->setPrivateKey( $privateKey, $params['uid'] ); + \OC_FileProxy::$enabled = false; + file_put_contents( '/home/samtuke/enckey', $_SESSION['enckey'] ); + \OC_FileProxy::$enabled = true; $view1 = new \OC_FilesystemView( '/' . $params['uid'] ); @@ -86,7 +86,7 @@ class Hooks { ) { $_SESSION['legacyenckey'] = Crypt::legacyDecrypt( $legacyKey, $params['password'] ); -// trigger_error('leg enc key = '.$_SESSION['legacyenckey']); + trigger_error('leg enc key = '.$_SESSION['legacyenckey']); } // } diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 5e1078c9e1..8df3cd4327 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -305,9 +305,9 @@ class Crypt { if ( $encryptedContent = self::encrypt( $plainContent, $iv, $passphrase ) ) { // Combine content to encrypt with IV identifier and actual IV - $catfile = self::concatIv( $encryptedContent, $iv ); + $combinedKeyfile = self::concatIv( $encryptedContent, $iv ); - $padded = self::addPadding( $catfile ); + $padded = self::addPadding( $combinedKeyfile ); return $padded; @@ -468,8 +468,7 @@ class Crypt { /** * @brief Encrypts content symmetrically and generates keyfile asymmetrically - * @returns array containing catfile and new keyfile. - * keys: data, key + * @returns array keys: encrypted, key * @note this method is a wrapper for combining other crypt class methods */ public static function keyEncryptKeyfile( $plainContent, $publicKey ) { @@ -485,20 +484,18 @@ class Crypt { } /** - * @brief Takes catfile, keyfile, and private key, and + * @brief Takes encrypted data, encrypted catfile, and private key, and * performs decryption * @returns decrypted content * @note this method is a wrapper for combining other crypt class methods */ - public static function keyDecryptKeyfile( $catfile, $keyfile, $privateKey ) { + public static function keyDecryptKeyfile( $encryptedData, $encryptedKey, $privateKey ) { - // Decrypt the keyfile with the user's private key - $decryptedKey = self::keyDecrypt( $keyfile, $privateKey ); + // Decrypt keyfile + $decryptedKey = self::keyDecrypt( $encryptedKey, $privateKey ); -// trigger_error( "\$keyfile = ".var_export($keyfile, 1)); - - // Decrypt the catfile symmetrically using the decrypted keyfile - $decryptedData = self::symmetricDecryptFileContent( $catfile, $decryptedKey ); + // Decrypt encrypted file + $decryptedData = self::symmetricDecryptFileContent( $encryptedData, $decryptedKey ); return $decryptedData; @@ -687,7 +684,7 @@ class Crypt { */ public static function legacyEncrypt( $content, $passphrase = '' ) { - //trigger_error("OC2 enc \$content = $content \$passphrase = ".var_export($passphrase, 1) ); + trigger_error("OC2 enc \$content = $content \$passphrase = ".var_export($passphrase, 1) ); $bf = self::getBlowfish( $passphrase ); @@ -711,7 +708,7 @@ class Crypt { $bf = self::getBlowfish( "67362885833455692562" ); -// trigger_error(var_export($bf, 1) ); + trigger_error(var_export($bf, 1) ); $decrypted = $bf->decrypt( $content ); diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index 55d7530c46..2f73097128 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -46,19 +46,11 @@ class Keymanager { * @brief retrieve public key for a specified user * @return string public key or false */ - public static function getPublicKey( $userId = NULL ) { + public static function getPublicKey() { - // If the username wasn't specified, fetch it - if ( ! $userId ) { - - $userId = \OCP\User::getUser(); - - } - - // Create new view with the right + $user = \OCP\User::getUser(); $view = new \OC_FilesystemView( '/public-keys/' ); - - return $view->file_get_contents( '/' . $userId . '.public.key' ); + return $view->file_get_contents( '/' . $user . '.public.key' ); } @@ -127,12 +119,10 @@ class Keymanager { } /** - * @brief retrieve keyfile for an encrypted file + * @brief retrieve file encryption key * * @param string file name * @return string file key or false - * @note The keyfile returned is asymmetrically encrypted. Decryption - * of the keyfile must be performed by client code */ public static function getFileKey( $path, $staticUserClass = 'OCP\User' ) { @@ -251,8 +241,6 @@ class Keymanager { * @param string $path relative path of the file, including filename * @param string $key * @return bool true/false - * @note The keyfile is not encrypted here. Client code must - * asymmetrically encrypt the keyfile before passing it to this method */ public static function setFileKey( $path, $key, $view = Null, $dbClassName = '\OC_DB') { diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 85664734d7..914632d338 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -131,10 +131,6 @@ class Proxy extends \OC_FileProxy { } - /** - * @param string $path Path of file from which has been read - * @param string $data Data that has been read from file - */ public function postFile_get_contents( $path, $data ) { # TODO: Use dependency injection to add required args for view and user etc. to this method @@ -142,27 +138,24 @@ class Proxy extends \OC_FileProxy { // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; - // If data is a catfile if ( Crypt::mode() == 'server' && Crypt::isEncryptedContent( $data ) ) { -// trigger_error("bong"); + //trigger_error("bong"); - $split = explode( '/', $path ); + $filePath = explode( '/', $path ); - $filePath = array_slice( $split, 3 ); + $filePath = array_slice( $filePath, 3 ); $filePath = '/' . implode( '/', $filePath ); //$cached = \OC_FileCache_Cached::get( $path, '' ); $keyFile = Keymanager::getFileKey( $filePath ); - - $session = new Session(); - - $decrypted = Crypt::keyDecryptKeyfile( $data, $keyFile, $session->getPrivateKey( $split[1] ) ); + $data = Crypt::keyDecryptKeyfile( $data, $keyFile, $_SESSION['enckey'] ); + } elseif ( Crypt::mode() == 'server' && isset( $_SESSION['legacyenckey'] ) @@ -170,20 +163,14 @@ class Proxy extends \OC_FileProxy { ) { trigger_error("mong"); - $decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); + $data = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); //trigger_error($data); } \OC_FileProxy::$enabled = true; - if ( ! isset( $decrypted ) ) { - - $decrypted = $data; - - } - - return $decrypted; + return $data; } diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php deleted file mode 100644 index 946e5a6edd..0000000000 --- a/apps/files_encryption/lib/session.php +++ /dev/null @@ -1,66 +0,0 @@ -. - * - */ - -namespace OCA\Encryption; - -/** - * Class for handling encryption related session data - */ - -class Session { - - /** - * @brief Sets user id for session and triggers emit - * @return bool - * - */ - public static function setPrivateKey( $privateKey, $userId ) { - - $_SESSION['privateKey'] = $privateKey; - - return true; - - } - - /** - * @brief Gets user id for session and triggers emit - * @returns string $privateKey The user's plaintext private key - * - */ - public static function getPrivateKey( $userId ) { - - if ( - isset( $_SESSION['privateKey'] ) - && !empty( $_SESSION['privateKey'] ) - ) { - - return $_SESSION['privateKey']; - - } 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 ac5fadd4e0..74dff1531a 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -59,9 +59,7 @@ class Stream { private $count; private $writeCache; public $size; - private $publicKey; private $keyfile; - private $encKeyfile; private static $view; public function stream_open( $path, $mode, $options, &$opened_path ) { @@ -248,7 +246,7 @@ class Stream { * @param bool $generate if true, a new key will be generated if none can be found * @return bool true on key found and set, false on key not found and new key generated and set */ - public function getKey() { + public function getKey( $generate = true ) { //echo "\n\$this->rawPath = {$this->rawPath}"; @@ -258,39 +256,25 @@ class Stream { # TODO: add error handling for when file exists but no keyfile // Fetch existing keyfile - $this->encKeyfile = Keymanager::getFileKey( $this->rawPath ); - - $this->getUser(); - - $session = new Session(); - - $this->keyfile = Crypt::keyDecrypt( $this->encKeyfile, $session->getPrivateKey( $this->userId ) ); + $this->keyfile = Keymanager::getFileKey( $this->rawPath ); return true; } else { - return false; - + if ( $generate ) { + + // If the data is to be written to a new file, generate a new keyfile + $this->keyfile = Crypt::generateKey(); + + return false; + + } + } } - public function getuser() { - - // 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 - $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?) - - } - /** * @brief Handle plain data from the stream, and write it in 8192 byte blocks * @param string $data data to be written to disk @@ -322,23 +306,15 @@ class Stream { //echo "\$pointer = $pointer\n"; - // Make sure the userId is set - $this->getuser(); + # TODO: Move this user call out of here - it belongs elsewhere + $user = \OCP\User::getUser(); // Get / generate the keyfile for the file we're handling // If we're writing a new file (not overwriting an existing one), save the newly generated keyfile if ( ! $this->getKey() ) { - - $this->keyfile = Crypt::generateKey(); - $this->publicKey = Keymanager::getPublicKey( $this->userId ); - - $this->encKeyfile = Crypt::keyEncrypt( $this->keyfile, $this->publicKey ); - - // Save the new encrypted file key - Keymanager::setFileKey( $this->rawPath, $this->encKeyfile, new \OC_FilesystemView( '/' ) ); - - # TODO: move this new OCFSV out of here some how, use DI + // Save keyfile in parallel directory structure + Keymanager::setFileKey( $this->rawPath, $this->keyfile, new \OC_FilesystemView( '/' ) ); } diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index 77f8dffe00..907a04e5c0 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -45,7 +45,6 @@ class Util { ## 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: @@ -53,7 +52,8 @@ class Util { ## 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 + + # TODO: files created & encrypted via web ui are readable via webdav # Legacy support: diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index f72f15ca23..09347dd578 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -21,10 +21,6 @@ require_once realpath( dirname(__FILE__).'/../appinfo/app.php' ); use OCA\Encryption; -// This has to go here because otherwise session errors arise, and the private -// encryption key needs to be saved in the session -\OC_User::login( 'admin', 'admin' ); - class Test_Crypt extends \PHPUnit_Framework_TestCase { function setUp() { @@ -45,6 +41,8 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->userId = 'admin'; $this->pass = 'admin'; + + \OC_User::setUserId( $this->userId ); } @@ -436,7 +434,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { } - // What is the point of this test? It doesn't use keyEncryptKeyfile() function testKeyEncryptKeyfile() { # TODO: Don't repeat encryption from previous tests, use PHPUnit test interdependency instead @@ -459,22 +456,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { $this->assertEquals( $this->dataUrl, $decryptData ); } - - /** - * @brief test functionality of keyEncryptKeyfile() and - * keyDecryptKeyfile() - */ - function testKeyDecryptKeyfile() { - - $encrypted = Encryption\Crypt::keyEncryptKeyfile( $this->dataShort, $this->genPublicKey ); - - $this->assertNotEquals( $encrypted['data'], $this->dataShort ); - - $decrypted = Encryption\Crypt::keyDecryptKeyfile( $encrypted['data'], $encrypted['key'], $this->genPrivateKey ); - - $this->assertEquals( $decrypted, $this->dataShort ); - - } /** @@ -493,17 +474,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { } -// /** -// * @brief test decryption using legacy blowfish method -// * @depends testLegacyEncryptShort -// */ -// function testLegacyDecryptShort( $crypted ) { -// -// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); -// -// $this->assertEquals( $this->dataShort, $decrypted ); -// -// } + /** + * @brief test decryption using legacy blowfish method + * @depends testLegacyEncryptShort + */ + function testLegacyDecryptShort( $crypted ) { + + $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); + + $this->assertEquals( $this->dataShort, $decrypted ); + + } /** * @brief test encryption using legacy blowfish method @@ -521,17 +502,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase { } -// /** -// * @brief test decryption using legacy blowfish method -// * @depends testLegacyEncryptLong -// */ -// function testLegacyDecryptLong( $crypted ) { -// -// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); -// -// $this->assertEquals( $this->dataLong, $decrypted ); -// -// } + /** + * @brief test decryption using legacy blowfish method + * @depends testLegacyEncryptLong + */ + function testLegacyDecryptLong( $crypted ) { + + $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); + + $this->assertEquals( $this->dataLong, $decrypted ); + + } /** * @brief test generation of legacy encryption key diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 87151234e0..8b2c92c2f5 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -45,17 +45,10 @@ class Test_Util extends \PHPUnit_Framework_TestCase { $this->data1 = file_get_contents( realpath( dirname(__FILE__).'/../../../data/admin/files/enc-test.txt' ) ); - \OC_FileProxy::$enabled = false; - $this->Encdata1 = file_get_contents( realpath( dirname(__FILE__).'/../../../data/admin/files/enc-test.txt' ) ); - \OC_FileProxy::$enabled = true; - $this->userId = 'admin'; $this->pass = 'admin'; - $this->session = new Encryption\Session(); - -$this->session->setPrivateKey( -'-----BEGIN PRIVATE KEY----- +$_SESSION['enckey'] = '-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0 GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz @@ -83,9 +76,7 @@ k1kbgyS7KKB7opVxI5+ChEqyUDijS3Y9FZixrRIWE6i2uGu86UG+v2lbKvSbM4Qm xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d Y1d5piFV8PXK3Fg2F+Cj5qg= -----END PRIVATE KEY----- -' -, $this->userId -); +'; \OC_User::setUserId( $this->userId ); @@ -122,11 +113,11 @@ Y1d5piFV8PXK3Fg2F+Cj5qg= // // $this->oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true'); // OCP\Config::setAppValue('files_encryption','enable_encryption','true'); -// $this->oldKey=isset($_SESSION['privateKey'])?$_SESSION['privateKey']:null; +// $this->oldKey=isset($_SESSION['enckey'])?$_SESSION['enckey']:null; // // // //set testing key -// $_SESSION['privateKey']=md5(time()); +// $_SESSION['enckey']=md5(time()); // // //clear all proxies and hooks so we can do clean testing // OC_FileProxy::clearProxies(); @@ -150,7 +141,7 @@ Y1d5piFV8PXK3Fg2F+Cj5qg= // public function tearDown(){ // OCP\Config::setAppValue('files_encryption','enable_encryption',$this->oldConfig); // if(!is_null($this->oldKey)){ -// $_SESSION['privateKey']=$this->oldKey; +// $_SESSION['enckey']=$this->oldKey; // } // } //