Revert "Development snapshot"

This reverts commit c56fb905d1.
This commit is contained in:
Sam Tuke 2012-12-11 15:10:39 +00:00
parent aabef796a0
commit b66d38ecae
10 changed files with 74 additions and 227 deletions

View File

@ -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\Keymanager'] = 'apps/files_encryption/lib/keymanager.php';
OC::$CLASSPATH['OCA\Encryption\Stream'] = 'apps/files_encryption/lib/stream.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\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()); 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'); stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream');
$session = new OCA\Encryption\Session(); if( !isset( $_SESSION['enckey'] ) && OCP\User::isLoggedIn() && OCA\Encryption\Crypt::mode() == 'server' ) {
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) // 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(); OCP\User::logout();

View File

@ -70,11 +70,11 @@ class Hooks {
// trigger_error( "\$params['password'] = {$params['password']}" ); // trigger_error( "\$params['password'] = {$params['password']}" );
$privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); $_SESSION['enckey'] = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
$session = new Session(); \OC_FileProxy::$enabled = false;
file_put_contents( '/home/samtuke/enckey', $_SESSION['enckey'] );
$session->setPrivateKey( $privateKey, $params['uid'] ); \OC_FileProxy::$enabled = true;
$view1 = new \OC_FilesystemView( '/' . $params['uid'] ); $view1 = new \OC_FilesystemView( '/' . $params['uid'] );
@ -86,7 +86,7 @@ class Hooks {
) { ) {
$_SESSION['legacyenckey'] = Crypt::legacyDecrypt( $legacyKey, $params['password'] ); $_SESSION['legacyenckey'] = Crypt::legacyDecrypt( $legacyKey, $params['password'] );
// trigger_error('leg enc key = '.$_SESSION['legacyenckey']); trigger_error('leg enc key = '.$_SESSION['legacyenckey']);
} }
// } // }

View File

@ -305,9 +305,9 @@ class Crypt {
if ( $encryptedContent = self::encrypt( $plainContent, $iv, $passphrase ) ) { if ( $encryptedContent = self::encrypt( $plainContent, $iv, $passphrase ) ) {
// Combine content to encrypt with IV identifier and actual IV // 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; return $padded;
@ -468,8 +468,7 @@ class Crypt {
/** /**
* @brief Encrypts content symmetrically and generates keyfile asymmetrically * @brief Encrypts content symmetrically and generates keyfile asymmetrically
* @returns array containing catfile and new keyfile. * @returns array keys: encrypted, key
* keys: data, key
* @note this method is a wrapper for combining other crypt class methods * @note this method is a wrapper for combining other crypt class methods
*/ */
public static function keyEncryptKeyfile( $plainContent, $publicKey ) { 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 * performs decryption
* @returns decrypted content * @returns decrypted content
* @note this method is a wrapper for combining other crypt class methods * @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 // Decrypt keyfile
$decryptedKey = self::keyDecrypt( $keyfile, $privateKey ); $decryptedKey = self::keyDecrypt( $encryptedKey, $privateKey );
// trigger_error( "\$keyfile = ".var_export($keyfile, 1)); // Decrypt encrypted file
$decryptedData = self::symmetricDecryptFileContent( $encryptedData, $decryptedKey );
// Decrypt the catfile symmetrically using the decrypted keyfile
$decryptedData = self::symmetricDecryptFileContent( $catfile, $decryptedKey );
return $decryptedData; return $decryptedData;
@ -687,7 +684,7 @@ class Crypt {
*/ */
public static function legacyEncrypt( $content, $passphrase = '' ) { 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 ); $bf = self::getBlowfish( $passphrase );
@ -711,7 +708,7 @@ class Crypt {
$bf = self::getBlowfish( "67362885833455692562" ); $bf = self::getBlowfish( "67362885833455692562" );
// trigger_error(var_export($bf, 1) ); trigger_error(var_export($bf, 1) );
$decrypted = $bf->decrypt( $content ); $decrypted = $bf->decrypt( $content );

View File

@ -46,19 +46,11 @@ class Keymanager {
* @brief retrieve public key for a specified user * @brief retrieve public key for a specified user
* @return string public key or false * @return string public key or false
*/ */
public static function getPublicKey( $userId = NULL ) { public static function getPublicKey() {
// If the username wasn't specified, fetch it $user = \OCP\User::getUser();
if ( ! $userId ) {
$userId = \OCP\User::getUser();
}
// Create new view with the right
$view = new \OC_FilesystemView( '/public-keys/' ); $view = new \OC_FilesystemView( '/public-keys/' );
return $view->file_get_contents( '/' . $user . '.public.key' );
return $view->file_get_contents( '/' . $userId . '.public.key' );
} }
@ -127,12 +119,10 @@ class Keymanager {
} }
/** /**
* @brief retrieve keyfile for an encrypted file * @brief retrieve file encryption key
* *
* @param string file name * @param string file name
* @return string file key or false * @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' ) { 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 $path relative path of the file, including filename
* @param string $key * @param string $key
* @return bool true/false * @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') { public static function setFileKey( $path, $key, $view = Null, $dbClassName = '\OC_DB') {

View File

@ -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 ) { 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
@ -142,16 +138,15 @@ class Proxy extends \OC_FileProxy {
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;
// If data is a catfile
if ( if (
Crypt::mode() == 'server' Crypt::mode() == 'server'
&& Crypt::isEncryptedContent( $data ) && 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 ); $filePath = '/' . implode( '/', $filePath );
@ -159,9 +154,7 @@ class Proxy extends \OC_FileProxy {
$keyFile = Keymanager::getFileKey( $filePath ); $keyFile = Keymanager::getFileKey( $filePath );
$session = new Session(); $data = Crypt::keyDecryptKeyfile( $data, $keyFile, $_SESSION['enckey'] );
$decrypted = Crypt::keyDecryptKeyfile( $data, $keyFile, $session->getPrivateKey( $split[1] ) );
} elseif ( } elseif (
Crypt::mode() == 'server' Crypt::mode() == 'server'
@ -170,20 +163,14 @@ class Proxy extends \OC_FileProxy {
) { ) {
trigger_error("mong"); trigger_error("mong");
$decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); $data = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] );
//trigger_error($data); //trigger_error($data);
} }
\OC_FileProxy::$enabled = true; \OC_FileProxy::$enabled = true;
if ( ! isset( $decrypted ) ) { return $data;
$decrypted = $data;
}
return $decrypted;
} }

View File

@ -1,66 +0,0 @@
<?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;
}
}
}

View File

@ -59,9 +59,7 @@ class Stream {
private $count; private $count;
private $writeCache; private $writeCache;
public $size; public $size;
private $publicKey;
private $keyfile; private $keyfile;
private $encKeyfile;
private static $view; private static $view;
public function stream_open( $path, $mode, $options, &$opened_path ) { 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 * @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 * @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}"; //echo "\n\$this->rawPath = {$this->rawPath}";
@ -258,39 +256,25 @@ class Stream {
# 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 // Fetch existing keyfile
$this->encKeyfile = Keymanager::getFileKey( $this->rawPath ); $this->keyfile = Keymanager::getFileKey( $this->rawPath );
$this->getUser();
$session = new Session();
$this->keyfile = Crypt::keyDecrypt( $this->encKeyfile, $session->getPrivateKey( $this->userId ) );
return true; return true;
} else { } 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 * @brief Handle plain data from the stream, and write it in 8192 byte blocks
* @param string $data data to be written to disk * @param string $data data to be written to disk
@ -322,23 +306,15 @@ class Stream {
//echo "\$pointer = $pointer\n"; //echo "\$pointer = $pointer\n";
// Make sure the userId is set # TODO: Move this user call out of here - it belongs elsewhere
$this->getuser(); $user = \OCP\User::getUser();
// Get / generate the keyfile for the file we're handling // 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 we're writing a new file (not overwriting an existing one), save the newly generated keyfile
if ( ! $this->getKey() ) { if ( ! $this->getKey() ) {
$this->keyfile = Crypt::generateKey(); // Save keyfile in parallel directory structure
Keymanager::setFileKey( $this->rawPath, $this->keyfile, new \OC_FilesystemView( '/' ) );
$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
} }

View File

@ -45,7 +45,6 @@ class Util {
## DONE: files created via web ui are encrypted ## 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 in web ui
## DONE: file created & encrypted via web ui are readable via webdav
# 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 get encrypted
## DONE: new data filled files added via webdav are readable via webdav ## DONE: new data filled files added via webdav are readable via webdav
## DONE: reading unencrypted files when encryption is enabled works 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: # Legacy support:

View File

@ -21,10 +21,6 @@ require_once realpath( dirname(__FILE__).'/../appinfo/app.php' );
use OCA\Encryption; 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 { class Test_Crypt extends \PHPUnit_Framework_TestCase {
function setUp() { function setUp() {
@ -46,6 +42,8 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
$this->userId = 'admin'; $this->userId = 'admin';
$this->pass = 'admin'; $this->pass = 'admin';
\OC_User::setUserId( $this->userId );
} }
function tearDown(){} function tearDown(){}
@ -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() { function testKeyEncryptKeyfile() {
# TODO: Don't repeat encryption from previous tests, use PHPUnit test interdependency instead # TODO: Don't repeat encryption from previous tests, use PHPUnit test interdependency instead
@ -460,22 +457,6 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
} }
/**
* @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 );
}
/** /**
* @brief test encryption using legacy blowfish method * @brief test encryption using legacy blowfish method
@ -493,17 +474,17 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
} }
// /** /**
// * @brief test decryption using legacy blowfish method * @brief test decryption using legacy blowfish method
// * @depends testLegacyEncryptShort * @depends testLegacyEncryptShort
// */ */
// function testLegacyDecryptShort( $crypted ) { function testLegacyDecryptShort( $crypted ) {
//
// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass );
//
// $this->assertEquals( $this->dataShort, $decrypted ); $this->assertEquals( $this->dataShort, $decrypted );
//
// } }
/** /**
* @brief test encryption using legacy blowfish method * @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 * @brief test decryption using legacy blowfish method
// * @depends testLegacyEncryptLong * @depends testLegacyEncryptLong
// */ */
// function testLegacyDecryptLong( $crypted ) { function testLegacyDecryptLong( $crypted ) {
//
// $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass ); $decrypted = Encryption\Crypt::legacyDecrypt( $crypted, $this->pass );
//
// $this->assertEquals( $this->dataLong, $decrypted ); $this->assertEquals( $this->dataLong, $decrypted );
//
// } }
/** /**
* @brief test generation of legacy encryption key * @brief test generation of legacy encryption key

View File

@ -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' ) ); $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->userId = 'admin';
$this->pass = 'admin'; $this->pass = 'admin';
$this->session = new Encryption\Session(); $_SESSION['enckey'] = '-----BEGIN PRIVATE KEY-----
$this->session->setPrivateKey(
'-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx
s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0 s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0
GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz
@ -83,9 +76,7 @@ k1kbgyS7KKB7opVxI5+ChEqyUDijS3Y9FZixrRIWE6i2uGu86UG+v2lbKvSbM4Qm
xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d
Y1d5piFV8PXK3Fg2F+Cj5qg= Y1d5piFV8PXK3Fg2F+Cj5qg=
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
' ';
, $this->userId
);
\OC_User::setUserId( $this->userId ); \OC_User::setUserId( $this->userId );
@ -122,11 +113,11 @@ Y1d5piFV8PXK3Fg2F+Cj5qg=
// //
// $this->oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true'); // $this->oldConfig=OCP\Config::getAppValue('files_encryption','enable_encryption','true');
// OCP\Config::setAppValue('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 // //set testing key
// $_SESSION['privateKey']=md5(time()); // $_SESSION['enckey']=md5(time());
// //
// //clear all proxies and hooks so we can do clean testing // //clear all proxies and hooks so we can do clean testing
// OC_FileProxy::clearProxies(); // OC_FileProxy::clearProxies();
@ -150,7 +141,7 @@ Y1d5piFV8PXK3Fg2F+Cj5qg=
// public function tearDown(){ // public function tearDown(){
// OCP\Config::setAppValue('files_encryption','enable_encryption',$this->oldConfig); // OCP\Config::setAppValue('files_encryption','enable_encryption',$this->oldConfig);
// if(!is_null($this->oldKey)){ // if(!is_null($this->oldKey)){
// $_SESSION['privateKey']=$this->oldKey; // $_SESSION['enckey']=$this->oldKey;
// } // }
// } // }
// //