summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files_encryption/appinfo/app.php9
-rw-r--r--apps/files_encryption/hooks/hooks.php10
-rwxr-xr-xapps/files_encryption/lib/crypt.php25
-rwxr-xr-xapps/files_encryption/lib/keymanager.php20
-rw-r--r--apps/files_encryption/lib/proxy.php27
-rw-r--r--apps/files_encryption/lib/session.php66
-rw-r--r--apps/files_encryption/lib/stream.php54
-rw-r--r--apps/files_encryption/lib/util.php4
-rwxr-xr-xapps/files_encryption/tests/crypt.php67
-rw-r--r--apps/files_encryption/tests/proxy.php19
10 files changed, 227 insertions, 74 deletions
diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php
index 12920aa8291..7a8eee41bb5 100644
--- a/apps/files_encryption/appinfo/app.php
+++ b/apps/files_encryption/appinfo/app.php
@@ -6,6 +6,7 @@ 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());
@@ -14,7 +15,13 @@ OCP\Util::connectHook('OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks',
stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream');
-if( !isset( $_SESSION['enckey'] ) && OCP\User::isLoggedIn() && OCA\Encryption\Crypt::mode() == 'server' ) {
+$session = new OCA\Encryption\Session();
+
+if (
+! $session->getPrivateKey( \OCP\USER::getUser() )
+&& 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 20ce45244ac..9752dbf0a15 100644
--- a/apps/files_encryption/hooks/hooks.php
+++ b/apps/files_encryption/hooks/hooks.php
@@ -65,11 +65,11 @@ class Hooks {
// trigger_error( "\$params['password'] = {$params['password']}" );
- $_SESSION['enckey'] = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
+ $privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
- \OC_FileProxy::$enabled = false;
- file_put_contents( '/home/samtuke/enckey', $_SESSION['enckey'] );
- \OC_FileProxy::$enabled = true;
+ $session = new Session();
+
+ $session->setPrivateKey( $privateKey, $params['uid'] );
$view1 = new \OC_FilesystemView( '/' . $params['uid'] );
@@ -81,7 +81,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 8df3cd43270..5e1078c9e1b 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
- $combinedKeyfile = self::concatIv( $encryptedContent, $iv );
+ $catfile = self::concatIv( $encryptedContent, $iv );
- $padded = self::addPadding( $combinedKeyfile );
+ $padded = self::addPadding( $catfile );
return $padded;
@@ -468,7 +468,8 @@ class Crypt {
/**
* @brief Encrypts content symmetrically and generates keyfile asymmetrically
- * @returns array keys: encrypted, key
+ * @returns array containing catfile and new keyfile.
+ * keys: data, key
* @note this method is a wrapper for combining other crypt class methods
*/
public static function keyEncryptKeyfile( $plainContent, $publicKey ) {
@@ -484,18 +485,20 @@ class Crypt {
}
/**
- * @brief Takes encrypted data, encrypted catfile, and private key, and
+ * @brief Takes catfile, keyfile, 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( $encryptedData, $encryptedKey, $privateKey ) {
+ public static function keyDecryptKeyfile( $catfile, $keyfile, $privateKey ) {
- // Decrypt keyfile
- $decryptedKey = self::keyDecrypt( $encryptedKey, $privateKey );
+ // Decrypt the keyfile with the user's private key
+ $decryptedKey = self::keyDecrypt( $keyfile, $privateKey );
- // Decrypt encrypted file
- $decryptedData = self::symmetricDecryptFileContent( $encryptedData, $decryptedKey );
+// trigger_error( "\$keyfile = ".var_export($keyfile, 1));
+
+ // Decrypt the catfile symmetrically using the decrypted keyfile
+ $decryptedData = self::symmetricDecryptFileContent( $catfile, $decryptedKey );
return $decryptedData;
@@ -684,7 +687,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 );
@@ -708,7 +711,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 02fb6acbaa1..9eb9bad3db4 100755
--- a/apps/files_encryption/lib/keymanager.php
+++ b/apps/files_encryption/lib/keymanager.php
@@ -46,11 +46,19 @@ class Keymanager {
* @brief retrieve public key for a specified user
* @return string public key or false
*/
- public static function getPublicKey() {
+ public static function getPublicKey( $userId = NULL ) {
- $user = \OCP\User::getUser();
+ // If the username wasn't specified, fetch it
+ if ( ! $userId ) {
+
+ $userId = \OCP\User::getUser();
+
+ }
+
+ // Create new view with the right
$view = new \OC_FilesystemView( '/public-keys/' );
- return $view->file_get_contents( '/' . $user . '.public.key' );
+
+ return $view->file_get_contents( '/' . $userId . '.public.key' );
}
@@ -119,10 +127,12 @@ class Keymanager {
}
/**
- * @brief retrieve file encryption key
+ * @brief retrieve keyfile for an encrypted file
*
* @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' ) {
@@ -228,6 +238,8 @@ 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 914632d3387..85664734d7a 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -131,6 +131,10 @@ 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
@@ -138,24 +142,27 @@ 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");
- $filePath = explode( '/', $path );
+ $split = explode( '/', $path );
- $filePath = array_slice( $filePath, 3 );
+ $filePath = array_slice( $split, 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'] )
@@ -163,14 +170,20 @@ class Proxy extends \OC_FileProxy {
) {
trigger_error("mong");
- $data = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] );
+ $decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] );
//trigger_error($data);
}
\OC_FileProxy::$enabled = true;
- return $data;
+ if ( ! isset( $decrypted ) ) {
+
+ $decrypted = $data;
+
+ }
+
+ return $decrypted;
}
diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php
new file mode 100644
index 00000000000..946e5a6eddd
--- /dev/null
+++ b/apps/files_encryption/lib/session.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Sam Tuke
+ * @copyright 2012 Sam Tuke samtuke@owncloud.com
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+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 74dff1531a9..ac5fadd4e03 100644
--- a/apps/files_encryption/lib/stream.php
+++ b/apps/files_encryption/lib/stream.php
@@ -59,7 +59,9 @@ 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 ) {
@@ -246,7 +248,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( $generate = true ) {
+ public function getKey() {
//echo "\n\$this->rawPath = {$this->rawPath}";
@@ -256,23 +258,37 @@ class Stream {
# TODO: add error handling for when file exists but no keyfile
// Fetch existing keyfile
- $this->keyfile = Keymanager::getFileKey( $this->rawPath );
+ $this->encKeyfile = Keymanager::getFileKey( $this->rawPath );
+
+ $this->getUser();
+
+ $session = new Session();
+
+ $this->keyfile = Crypt::keyDecrypt( $this->encKeyfile, $session->getPrivateKey( $this->userId ) );
return true;
} else {
- if ( $generate ) {
-
- // If the data is to be written to a new file, generate a new keyfile
- $this->keyfile = Crypt::generateKey();
-
- return false;
-
- }
-
+ 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?)
+
}
/**
@@ -306,15 +322,23 @@ class Stream {
//echo "\$pointer = $pointer\n";
- # TODO: Move this user call out of here - it belongs elsewhere
- $user = \OCP\User::getUser();
+ // Make sure the userId is set
+ $this->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( '/' ) );
- // Save keyfile in parallel directory structure
- Keymanager::setFileKey( $this->rawPath, $this->keyfile, new \OC_FilesystemView( '/' ) );
+ # TODO: move this new OCFSV out of here some how, use DI
}
diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php
index 907a04e5c00..77f8dffe00f 100644
--- a/apps/files_encryption/lib/util.php
+++ b/apps/files_encryption/lib/util.php
@@ -45,6 +45,7 @@ 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:
@@ -52,8 +53,7 @@ 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
-
- # TODO: files created & encrypted via web ui are readable via webdav
+ ## DONE: 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 09347dd578a..f72f15ca236 100755
--- a/apps/files_encryption/tests/crypt.php
+++ b/apps/files_encryption/tests/crypt.php
@@ -21,6 +21,10 @@ 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() {
@@ -41,8 +45,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
$this->userId = 'admin';
$this->pass = 'admin';
-
- \OC_User::setUserId( $this->userId );
}
@@ -434,6 +436,7 @@ 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
@@ -456,6 +459,22 @@ 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 );
+
+ }
/**
@@ -474,17 +493,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
@@ -502,17 +521,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 8b2c92c2f53..87151234e0e 100644
--- a/apps/files_encryption/tests/proxy.php
+++ b/apps/files_encryption/tests/proxy.php
@@ -45,10 +45,17 @@ 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';
-$_SESSION['enckey'] = '-----BEGIN PRIVATE KEY-----
+ $this->session = new Encryption\Session();
+
+$this->session->setPrivateKey(
+'-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx
s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0
GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz
@@ -76,7 +83,9 @@ k1kbgyS7KKB7opVxI5+ChEqyUDijS3Y9FZixrRIWE6i2uGu86UG+v2lbKvSbM4Qm
xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d
Y1d5piFV8PXK3Fg2F+Cj5qg=
-----END PRIVATE KEY-----
-';
+'
+, $this->userId
+);
\OC_User::setUserId( $this->userId );
@@ -113,11 +122,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['enckey'])?$_SESSION['enckey']:null;
+// $this->oldKey=isset($_SESSION['privateKey'])?$_SESSION['privateKey']:null;
//
//
// //set testing key
-// $_SESSION['enckey']=md5(time());
+// $_SESSION['privateKey']=md5(time());
//
// //clear all proxies and hooks so we can do clean testing
// OC_FileProxy::clearProxies();
@@ -141,7 +150,7 @@ Y1d5piFV8PXK3Fg2F+Cj5qg=
// public function tearDown(){
// OCP\Config::setAppValue('files_encryption','enable_encryption',$this->oldConfig);
// if(!is_null($this->oldKey)){
-// $_SESSION['enckey']=$this->oldKey;
+// $_SESSION['privateKey']=$this->oldKey;
// }
// }
//