Ejemplo n.º 1
0
 /**
  * @medium
  * @brief Test that data that is written by the crypto stream wrapper
  * @note Encrypted data is manually prepared and decrypted here to avoid dependency on success of stream_read
  * @note If this test fails with truncate content, check that enough array slices are being rejoined to form $e, as the crypt.php file may have gotten longer and broken the manual
  * reassembly of its data
  */
 function testSymmetricStreamEncryptLongFileContent()
 {
     // Generate a a random filename
     $filename = 'tmp-' . uniqid() . '.test';
     $util = new Encryption\Util(new \OC_FilesystemView(), $this->userId);
     // Save long data as encrypted file using stream wrapper
     $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong . $this->dataLong);
     // Test that data was successfully written
     $this->assertTrue(is_int($cryptedFile));
     // Disable encryption proxy to prevent recursive calls
     $proxyStatus = \OC_FileProxy::$enabled;
     \OC_FileProxy::$enabled = false;
     // Get file contents without using any wrapper to get it's actual contents on disk
     $retreivedCryptedFile = $this->view->file_get_contents($this->userId . '/files/' . $filename);
     // Re-enable proxy - our work is done
     \OC_FileProxy::$enabled = $proxyStatus;
     // Check that the file was encrypted before being written to disk
     $this->assertNotEquals($this->dataLong . $this->dataLong, $retreivedCryptedFile);
     // Manuallly split saved file into separate IVs and encrypted chunks
     $r = preg_split('/(00iv00.{16,18})/', $retreivedCryptedFile, NULL, PREG_SPLIT_DELIM_CAPTURE);
     //print_r($r);
     // Join IVs and their respective data chunks
     $e = array();
     $i = 0;
     while ($i < count($r) - 1) {
         $e[] = $r[$i] . $r[$i + 1];
         $i = $i + 2;
     }
     //print_r($e);
     // Get the encrypted keyfile
     $encKeyfile = Encryption\Keymanager::getFileKey($this->view, $util, $filename);
     // Attempt to fetch the user's shareKey
     $shareKey = Encryption\Keymanager::getShareKey($this->view, $this->userId, $util, $filename);
     // get session
     $session = new \OCA\Encryption\Session($this->view);
     // get private key
     $privateKey = $session->getPrivateKey($this->userId);
     // Decrypt keyfile with shareKey
     $plainKeyfile = Encryption\Crypt::multiKeyDecrypt($encKeyfile, $shareKey, $privateKey);
     // Set var for reassembling decrypted content
     $decrypt = '';
     // Manually decrypt chunk
     foreach ($e as $chunk) {
         $chunkDecrypt = Encryption\Crypt::symmetricDecryptFileContent($chunk, $plainKeyfile);
         // Assemble decrypted chunks
         $decrypt .= $chunkDecrypt;
     }
     $this->assertEquals($this->dataLong . $this->dataLong, $decrypt);
     // Teardown
     $this->view->unlink($this->userId . '/files/' . $filename);
     Encryption\Keymanager::deleteFileKey($this->view, $filename);
 }
Ejemplo n.º 2
0
 /**
  * @brief Change a user's encryption passphrase
  * @param array $params keys: uid, password
  */
 public static function setPassphrase($params)
 {
     if (\OCP\App::isEnabled('files_encryption') === false) {
         return true;
     }
     // Only attempt to change passphrase if server-side encryption
     // is in use (client-side encryption does not have access to
     // the necessary keys)
     if (Crypt::mode() === 'server') {
         $view = new \OC_FilesystemView('/');
         $session = new \OCA\Encryption\Session($view);
         // Get existing decrypted private key
         $privateKey = $session->getPrivateKey();
         if ($params['uid'] === \OCP\User::getUser() && $privateKey) {
             // Encrypt private key with new user pwd as passphrase
             $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password']);
             // Save private key
             if ($encryptedPrivateKey) {
                 Keymanager::setPrivateKey($encryptedPrivateKey);
             } else {
                 \OCP\Util::writeLog('files_encryption', 'Could not update users encryption password', \OCP\Util::ERROR);
             }
             // NOTE: Session does not need to be updated as the
             // private key has not changed, only the passphrase
             // used to decrypt it has changed
         } else {
             // admin changed the password for a different user, create new keys and reencrypt file keys
             $user = $params['uid'];
             $util = new Util($view, $user);
             $recoveryPassword = isset($params['recoveryPassword']) ? $params['recoveryPassword'] : null;
             // we generate new keys if...
             // ...we have a recovery password and the user enabled the recovery key
             // ...encryption was activated for the first time (no keys exists)
             // ...the user doesn't have any files
             if ($util->recoveryEnabledForUser() && $recoveryPassword || !$util->userKeysExists() || !$view->file_exists($user . '/files')) {
                 // backup old keys
                 $util->backupAllKeys('recovery');
                 $newUserPassword = $params['password'];
                 // make sure that the users home is mounted
                 \OC\Files\Filesystem::initMountPoints($user);
                 $keypair = Crypt::createKeypair();
                 // Disable encryption proxy to prevent recursive calls
                 $proxyStatus = \OC_FileProxy::$enabled;
                 \OC_FileProxy::$enabled = false;
                 // Save public key
                 $view->file_put_contents('/public-keys/' . $user . '.public.key', $keypair['publicKey']);
                 // Encrypt private key empty passphrase
                 $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword);
                 // Save private key
                 $view->file_put_contents('/' . $user . '/files_encryption/' . $user . '.private.key', $encryptedPrivateKey);
                 if ($recoveryPassword) {
                     // if recovery key is set we can re-encrypt the key files
                     $util = new Util($view, $user);
                     $util->recoverUsersFiles($recoveryPassword);
                 }
                 \OC_FileProxy::$enabled = $proxyStatus;
             }
         }
     }
 }
Ejemplo n.º 3
0
 /**
  * get the file size of the unencrypted file
  * @param string $path absolute path
  * @return bool
  */
 public function getFileSize($path)
 {
     $result = 0;
     // Disable encryption proxy to prevent recursive calls
     $proxyStatus = \OC_FileProxy::$enabled;
     \OC_FileProxy::$enabled = false;
     // split the path parts
     $pathParts = explode('/', $path);
     if (isset($pathParts[2]) && $pathParts[2] === 'files' && $this->view->file_exists($path) && $this->isEncryptedPath($path)) {
         $cipher = 'AES-128-CFB';
         $realSize = 0;
         // get the size from filesystem
         $size = $this->view->filesize($path);
         // open stream
         $stream = $this->view->fopen($path, "r");
         if (is_resource($stream)) {
             // if the file contains a encryption header we
             // we set the cipher
             // and we update the size
             if ($this->containHeader($path)) {
                 $data = fread($stream, Crypt::BLOCKSIZE);
                 $header = Crypt::parseHeader($data);
                 $cipher = Crypt::getCipher($header);
                 $size -= Crypt::BLOCKSIZE;
             }
             // fast path, else the calculation for $lastChunkNr is bogus
             if ($size === 0) {
                 \OC_FileProxy::$enabled = $proxyStatus;
                 return 0;
             }
             // calculate last chunk nr
             // next highest is end of chunks, one subtracted is last one
             // we have to read the last chunk, we can't just calculate it (because of padding etc)
             $lastChunkNr = ceil($size / Crypt::BLOCKSIZE) - 1;
             // calculate last chunk position
             $lastChunkPos = $lastChunkNr * Crypt::BLOCKSIZE;
             // get the content of the last chunk
             if (@fseek($stream, $lastChunkPos, SEEK_CUR) === 0) {
                 $realSize += $lastChunkNr * 6126;
             }
             $lastChunkContentEncrypted = '';
             $count = Crypt::BLOCKSIZE;
             while ($count > 0) {
                 $data = fread($stream, Crypt::BLOCKSIZE);
                 $count = strlen($data);
                 $lastChunkContentEncrypted .= $data;
                 if (strlen($lastChunkContentEncrypted) > Crypt::BLOCKSIZE) {
                     $realSize += 6126;
                     $lastChunkContentEncrypted = substr($lastChunkContentEncrypted, Crypt::BLOCKSIZE);
                 }
             }
             fclose($stream);
             $relPath = \OCA\Encryption\Helper::stripUserFilesPath($path);
             $shareKey = Keymanager::getShareKey($this->view, $this->keyId, $this, $relPath);
             if ($shareKey === false) {
                 \OC_FileProxy::$enabled = $proxyStatus;
                 return $result;
             }
             $session = new \OCA\Encryption\Session($this->view);
             $privateKey = $session->getPrivateKey();
             $plainKeyfile = $this->decryptKeyfile($relPath, $privateKey);
             $plainKey = Crypt::multiKeyDecrypt($plainKeyfile, $shareKey, $privateKey);
             $lastChunkContent = Crypt::symmetricDecryptFileContent($lastChunkContentEncrypted, $plainKey, $cipher);
             // calc the real file size with the size of the last chunk
             $realSize += strlen($lastChunkContent);
             // store file size
             $result = $realSize;
         }
     }
     \OC_FileProxy::$enabled = $proxyStatus;
     return $result;
 }
<?php

/**
 * Copyright (c) 2013 Sam Tuke <*****@*****.**>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */
// Add CSS stylesheet
\OC_Util::addStyle('files_encryption', 'settings-personal');
$tmpl = new OCP\Template('files_encryption', 'settings-personal');
$user = \OCP\USER::getUser();
$view = new \OC\Files\View('/');
$util = new \OCA\Encryption\Util($view, $user);
$session = new \OCA\Encryption\Session($view);
$privateKeySet = $session->getPrivateKey() !== false;
// did we tried to initialize the keys for this session?
$initialized = $session->getInitialized();
$recoveryAdminEnabled = \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled');
$recoveryEnabledForUser = $util->recoveryEnabledForUser();
$result = false;
if ($recoveryAdminEnabled || !$privateKeySet) {
    \OCP\Util::addscript('files_encryption', 'settings-personal');
    $tmpl->assign('recoveryEnabled', $recoveryAdminEnabled);
    $tmpl->assign('recoveryEnabledForUser', $recoveryEnabledForUser);
    $tmpl->assign('privateKeySet', $privateKeySet);
    $tmpl->assign('initialized', $initialized);
    $result = $tmpl->fetchPage();
}
return $result;
Ejemplo n.º 5
0
 /**
  * @brief Change a user's encryption passphrase
  * @param array $params keys: uid, password
  */
 public static function setPassphrase($params)
 {
     // Only attempt to change passphrase if server-side encryption
     // is in use (client-side encryption does not have access to
     // the necessary keys)
     if (Crypt::mode() === 'server') {
         if ($params['uid'] === \OCP\User::getUser()) {
             $view = new \OC_FilesystemView('/');
             $session = new \OCA\Encryption\Session($view);
             // Get existing decrypted private key
             $privateKey = $session->getPrivateKey();
             // Encrypt private key with new user pwd as passphrase
             $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($privateKey, $params['password']);
             // 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
         } else {
             // admin changed the password for a different user, create new keys and reencrypt file keys
             $user = $params['uid'];
             $recoveryPassword = $params['recoveryPassword'];
             $newUserPassword = $params['password'];
             $view = new \OC_FilesystemView('/');
             // make sure that the users home is mounted
             \OC\Files\Filesystem::initMountPoints($user);
             $keypair = Crypt::createKeypair();
             // Disable encryption proxy to prevent recursive calls
             $proxyStatus = \OC_FileProxy::$enabled;
             \OC_FileProxy::$enabled = false;
             // Save public key
             $view->file_put_contents('/public-keys/' . $user . '.public.key', $keypair['publicKey']);
             // Encrypt private key empty passphrase
             $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $newUserPassword);
             // Save private key
             $view->file_put_contents('/' . $user . '/files_encryption/' . $user . '.private.key', $encryptedPrivateKey);
             if ($recoveryPassword) {
                 // if recovery key is set we can re-encrypt the key files
                 $util = new Util($view, $user);
                 $util->recoverUsersFiles($recoveryPassword);
             }
             \OC_FileProxy::$enabled = $proxyStatus;
         }
     }
 }