2012-07-11 16:51:27 +00:00
< ? php
/**
* ownCloud
*
* @ author Sam Tuke , Frank Karlitschek
* @ copyright 2012 Sam Tuke samtuke @ owncloud . com ,
* Frank Karlitschek frank @ owncloud . org
*
* 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 />.
*
*/
// 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
// - IMPORTANT! Check if the block lenght of the encrypted data stays the same
namespace OCA_Encryption ;
/**
2012-07-25 14:33:25 +00:00
* @ brief Class for utilities relating to encrypted file storage system
* @ param $view OC_FilesystemView object , expected to have OC '/' as root path
* @ param $client flag indicating status of client side encryption . Currently
* unused , likely to become obsolete shortly
2012-07-11 16:51:27 +00:00
*/
class Util {
2012-07-24 16:53:12 +00:00
# DONE: add method to check if file is encrypted using new system
# DONE: add method to check if file is encrypted using old system
2012-07-25 11:38:40 +00:00
# DONE: add method to fetch legacy key
# DONE: add method to decrypt legacy encrypted data
2012-07-25 14:33:25 +00:00
2012-07-24 16:53:12 +00:00
# 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
2012-07-25 14:33:25 +00:00
2012-07-24 16:53:12 +00:00
# TODO: fix / test the crypt stream proxy class
# TODO: add support for optional recovery user in case of lost passphrase / keys
# TODO: add admin optional required long passphrase for users
# TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc.
# TODO: add UI buttons for encrypt / decrypt everything?
# TODO: test new encryption with webdav
# TODO: test new encryption with versioning
# TODO: test new encryption with sharing
# TODO: test new encryption with proxies
2012-07-11 16:51:27 +00:00
private $view ; // OC_FilesystemView object for filesystem operations
private $pwd ; // User Password
private $client ; // Client side encryption mode flag
2012-07-25 14:33:25 +00:00
public function __construct ( \OC_FilesystemView $view , $userId , $client = false ) {
2012-07-11 16:51:27 +00:00
$this -> view = $view ;
2012-07-25 14:33:25 +00:00
$this -> userId = $userId ;
2012-07-11 16:51:27 +00:00
$this -> client = $client ;
2012-07-25 14:33:25 +00:00
$this -> publicKeyDir = '/' . 'public-keys' ;
$this -> encryptionDir = '/' . $this -> userId . '/' . 'files_encryption' ;
$this -> keyfilesPath = $this -> encryptionDir . '/' . 'keyfiles' ;
$this -> publicKeyPath = $this -> publicKeyDir . '/' . $this -> userId . '.public.key' ; // e.g. data/public-keys/admin.public.key
$this -> privateKeyPath = $this -> encryptionDir . '/' . $this -> userId . '.private.key' ; // e.g. data/admin/admin.private.key
2012-07-11 16:51:27 +00:00
}
public function ready () {
if (
2012-07-25 14:33:25 +00:00
! $this -> view -> file_exists ( $this -> keyfilesPath )
or ! $this -> view -> file_exists ( $this -> publicKeyPath )
or ! $this -> view -> file_exists ( $this -> privateKeyPath )
2012-07-11 16:51:27 +00:00
) {
return false ;
} else {
return true ;
}
}
2012-07-24 16:53:12 +00:00
/**
2012-07-25 14:33:25 +00:00
* @ brief Sets up user folders and keys for serverside encryption
2012-07-24 16:53:12 +00:00
* @ param $passphrase passphrase to encrypt server - stored private key with
*/
2012-07-25 14:33:25 +00:00
public function setupServerSide ( $passphrase = null ) {
2012-07-11 16:51:27 +00:00
// Log changes to user's filesystem
$this -> appInfo = \OC_APP :: getAppInfo ( 'files_encryption' );
2012-07-25 14:33:25 +00:00
\OC_Log :: write ( $this -> appInfo [ 'name' ], 'File encryption for user "' . $this -> userId . '" will be set up' , \OC_Log :: INFO );
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
// Create shared public key directory
if ( ! $this -> view -> file_exists ( $this -> publicKeyDir ) ) {
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
$this -> view -> mkdir ( $this -> publicKeyDir );
2012-07-11 16:51:27 +00:00
}
2012-07-25 14:33:25 +00:00
// Create encryption app directory
if ( ! $this -> view -> file_exists ( $this -> encryptionDir ) ) {
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
$this -> view -> mkdir ( $this -> encryptionDir );
}
// Create mirrored keyfile directory
if ( ! $this -> view -> file_exists ( $this -> keyfilesPath ) ) {
$this -> view -> mkdir ( $this -> keyfilesPath );
2012-07-11 16:51:27 +00:00
}
// Create user keypair
if (
2012-07-25 14:33:25 +00:00
! $this -> view -> file_exists ( $this -> publicKeyPath )
or ! $this -> view -> file_exists ( $this -> privateKeyPath )
2012-07-11 16:51:27 +00:00
) {
// Generate keypair
$keypair = Crypt :: createKeypair ();
2012-07-25 14:33:25 +00:00
\OC_FileProxy :: $enabled = false ;
2012-07-11 16:51:27 +00:00
// Save public key
2012-07-25 14:33:25 +00:00
$this -> view -> file_put_contents ( $this -> publicKeyPath , $keypair [ 'publicKey' ] );
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
// Encrypt private key with user pwd as passphrase
$encryptedPrivateKey = Crypt :: symmetricEncryptFileContent ( $keypair [ 'privateKey' ], $passphrase );
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
// Save private key
$this -> view -> file_put_contents ( $this -> privateKeyPath , $encryptedPrivateKey );
2012-07-11 16:51:27 +00:00
2012-07-25 14:33:25 +00:00
\OC_FileProxy :: $enabled = true ;
2012-07-11 16:51:27 +00:00
}
}
2012-07-24 16:53:12 +00:00
/**
2012-07-25 11:38:40 +00:00
* @ brief Get the blowfish encryption handeler for a key
* @ param $key string ( optional )
* @ return Crypt_Blowfish blowfish object
2012-07-24 16:53:12 +00:00
*
* if the key is left out , the default handeler will be used
*/
2012-07-25 11:38:40 +00:00
public function getBlowfish ( $key = '' ) {
if ( $key ) {
2012-07-24 16:53:12 +00:00
2012-07-25 11:38:40 +00:00
return new \Crypt_Blowfish ( $key );
2012-07-24 16:53:12 +00:00
} else {
return false ;
2012-07-25 11:38:40 +00:00
2012-07-24 16:53:12 +00:00
}
}
/**
2012-07-25 11:38:40 +00:00
* @ brief Fetch the legacy encryption key from user files
* @ param string $login used to locate the legacy key
* @ param string $passphrase used to decrypt the legacy key
* @ return true / false
2012-07-24 16:53:12 +00:00
*
* if the key is left out , the default handeler will be used
*/
2012-07-25 11:38:40 +00:00
public function getLegacyKey ( $passphrase ) {
//OC_FileProxy::$enabled = false;
if (
$passphrase
and $key = $this -> view -> file_get_contents ( '/encryption.key' )
) {
2012-07-24 16:53:12 +00:00
2012-07-25 11:38:40 +00:00
//OC_FileProxy::$enabled = true;
2012-07-24 16:53:12 +00:00
2012-07-25 11:38:40 +00:00
if ( $this -> legacyKey = $this -> legacyDecrypt ( $key , $passphrase ) ) {
return true ;
} else {
return false ;
}
2012-07-24 16:53:12 +00:00
} else {
return false ;
}
}
/**
* @ brief encrypts content using legacy blowfish system
* @ param $content the cleartext message you want to encrypt
* @ param $key the encryption key ( optional )
* @ returns encrypted content
*
* This function encrypts an content
*/
2012-07-25 11:38:40 +00:00
public function legacyEncrypt ( $content , $passphrase = '' ) {
$bf = $this -> getBlowfish ( $passphrase );
return $bf -> encrypt ( $content );
2012-07-24 16:53:12 +00:00
}
/**
* @ brief decryption of an content
* @ param $content the cleartext message you want to decrypt
* @ param $key the encryption key ( optional )
* @ returns cleartext content
*
* This function decrypts an content
*/
2012-07-25 11:38:40 +00:00
public function legacyDecrypt ( $content , $passphrase = '' ) {
2012-07-24 16:53:12 +00:00
2012-07-25 11:38:40 +00:00
$bf = $this -> getBlowfish ( $passphrase );
2012-07-24 16:53:12 +00:00
$data = $bf -> decrypt ( $content );
return $data ;
}
/**
* @ brief Re - encryptes a legacy blowfish encrypted file using AES with integrated IV
* @ param $legacyContent the legacy encrypted content to re - encrypt
* @ returns cleartext content
*
* This function decrypts an content
*/
public function legacyRecrypt ( $legacyContent ) {
# TODO: write me
}
2012-07-11 16:51:27 +00:00
}