From 4bbdcfbccfe1fef28d3b6feea8a742e156295a63 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 21 Jul 2014 13:02:28 +0200 Subject: support aes 256 --- apps/files_encryption/lib/crypt.php | 131 ++++++++++++++++++++++++++----- apps/files_encryption/lib/exceptions.php | 9 +++ apps/files_encryption/lib/helper.php | 39 ++++++--- apps/files_encryption/lib/keymanager.php | 37 ++++++++- apps/files_encryption/lib/session.php | 12 +-- apps/files_encryption/lib/stream.php | 91 +++++++++++++++++---- apps/files_encryption/lib/util.php | 45 +++++++++-- 7 files changed, 304 insertions(+), 60 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 18f0224391d..8ca96899f88 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -36,6 +36,11 @@ class Crypt { const ENCRYPTION_PRIVATE_KEY_NOT_VALID_ERROR = 2; const ENCRYPTION_NO_SHARE_KEY_FOUND = 3; + const BLOCKSIZE = 8192; // block size will always be 8192 for a PHP stream https://bugs.php.net/bug.php?id=21641 + const DEFAULT_CIPHER = 'AES-256-CFB'; + + const HEADERSTART = 'HBEGIN'; + const HEADEREND = 'HEND'; /** * return encryption mode client or server side encryption @@ -181,19 +186,22 @@ class Crypt { * @param string $plainContent * @param string $iv * @param string $passphrase + * @param string $cypher used for encryption, currently we support AES-128-CFB and AES-256-CFB * @return string encrypted file content + * @throws \OCA\Encryption\Exceptions\EncryptionException */ - private static function encrypt($plainContent, $iv, $passphrase = '') { + private static function encrypt($plainContent, $iv, $passphrase = '', $cipher = Crypt::DEFAULT_CIPHER) { - if ($encryptedContent = openssl_encrypt($plainContent, 'AES-128-CFB', $passphrase, false, $iv)) { - return $encryptedContent; - } else { - \OCP\Util::writeLog('Encryption library', 'Encryption (symmetric) of content failed', \OCP\Util::ERROR); - \OCP\Util::writeLog('Encryption library', openssl_error_string(), \OCP\Util::ERROR); - return false; + $encryptedContent = openssl_encrypt($plainContent, $cipher, $passphrase, false, $iv); + if (!$encryptedContent) { + $error = "Encryption (symmetric) of content failed: " . openssl_error_string(); + \OCP\Util::writeLog('Encryption library', $error, \OCP\Util::ERROR); + throw new Exceptions\EncryptionException($error, 50); } + return $encryptedContent; + } /** @@ -201,19 +209,18 @@ class Crypt { * @param string $encryptedContent * @param string $iv * @param string $passphrase + * @param string $cipher cipher user for decryption, currently we support aes128 and aes256 * @throws \Exception * @return string decrypted file content */ - private static function decrypt($encryptedContent, $iv, $passphrase) { + private static function decrypt($encryptedContent, $iv, $passphrase, $cipher = Crypt::DEFAULT_CIPHER) { - if ($plainContent = openssl_decrypt($encryptedContent, 'AES-128-CFB', $passphrase, false, $iv)) { + $plainContent = openssl_decrypt($encryptedContent, $cipher, $passphrase, false, $iv); + if ($plainContent) { return $plainContent; - } else { - throw new \Exception('Encryption library: Decryption (symmetric) of content failed'); - } } @@ -261,11 +268,12 @@ class Crypt { * Symmetrically encrypts a string and returns keyfile content * @param string $plainContent content to be encrypted in keyfile * @param string $passphrase + * @param string $cypher used for encryption, currently we support AES-128-CFB and AES-256-CFB * @return false|string encrypted content combined with IV * @note IV need not be specified, as it will be stored in the returned keyfile * and remain accessible therein. */ - public static function symmetricEncryptFileContent($plainContent, $passphrase = '') { + public static function symmetricEncryptFileContent($plainContent, $passphrase = '', $cipher = Crypt::DEFAULT_CIPHER) { if (!$plainContent) { \OCP\Util::writeLog('Encryption library', 'symmetrically encryption failed, no content given.', \OCP\Util::ERROR); @@ -274,15 +282,16 @@ class Crypt { $iv = self::generateIv(); - if ($encryptedContent = self::encrypt($plainContent, $iv, $passphrase)) { + try { + $encryptedContent = self::encrypt($plainContent, $iv, $passphrase, $cipher); // Combine content to encrypt with IV identifier and actual IV $catfile = self::concatIv($encryptedContent, $iv); $padded = self::addPadding($catfile); return $padded; - - } else { - \OCP\Util::writeLog('Encryption library', 'Encryption (symmetric) of keyfile content failed', \OCP\Util::ERROR); + } catch (OCA\Encryption\Exceptions\EncryptionException $e) { + $message = 'Could not encrypt file content (code: ' . $e->getCode . '): '; + \OCP\Util::writeLog('files_encryption', $message . $e->getMessage, \OCP\Util::ERROR); return false; } @@ -293,6 +302,7 @@ class Crypt { * Symmetrically decrypts keyfile content * @param string $keyfileContent * @param string $passphrase + * @param string $cipher cipher used for decryption, currently aes128 and aes256 is supported. * @throws \Exception * @return string|false * @internal param string $source @@ -302,7 +312,7 @@ class Crypt { * * This function decrypts a file */ - public static function symmetricDecryptFileContent($keyfileContent, $passphrase = '') { + public static function symmetricDecryptFileContent($keyfileContent, $passphrase = '', $cipher = 'AES-128-CFB') { if (!$keyfileContent) { @@ -316,7 +326,7 @@ class Crypt { // Split into enc data and catfile $catfile = self::splitIv($noPadding); - if ($plainContent = self::decrypt($catfile['encrypted'], $catfile['iv'], $passphrase)) { + if ($plainContent = self::decrypt($catfile['encrypted'], $catfile['iv'], $passphrase, $cipher)) { return $plainContent; @@ -328,6 +338,7 @@ class Crypt { /** * Decrypt private key and check if the result is a valid keyfile + * * @param string $encryptedKey encrypted keyfile * @param string $passphrase to decrypt keyfile * @return string|false encrypted private key or false @@ -336,7 +347,15 @@ class Crypt { */ public static function decryptPrivateKey($encryptedKey, $passphrase) { - $plainKey = self::symmetricDecryptFileContent($encryptedKey, $passphrase); + $header = self::parseHeader($encryptedKey); + $cipher = self::getCipher($header); + + // if we found a header we need to remove it from the key we want to decrypt + if (!empty($header)) { + $encryptedKey = substr($encryptedKey, strpos($encryptedKey, self::HEADEREND) + strlen(self::HEADEREND)); + } + + $plainKey = self::symmetricDecryptFileContent($encryptedKey, $passphrase, $cipher); // check if this a valid private key $res = openssl_pkey_get_private($plainKey); @@ -481,4 +500,76 @@ class Crypt { } + /** + * read header into array + * + * @param string $data + * @return array + */ + public static function parseHeader($data) { + + $result = array(); + + if (substr($data, 0, strlen(self::HEADERSTART)) === self::HEADERSTART) { + $endAt = strpos($data, self::HEADEREND); + $header = substr($data, 0, $endAt + strlen(self::HEADEREND)); + + // +1 to not start with an ':' which would result in empty element at the beginning + $exploded = explode(':', substr($header, strlen(self::HEADERSTART)+1)); + + $element = array_shift($exploded); + while ($element !== self::HEADEREND) { + + $result[$element] = array_shift($exploded); + + $element = array_shift($exploded); + + } + } + + return $result; + } + + /** + * check if data block is the header + * + * @param string $data + * @return boolean + */ + public static function isHeader($data) { + + if (substr($data, 0, strlen(self::HEADERSTART)) === self::HEADERSTART) { + return true; + } + + return false; + } + + /** + * get chiper from header + * + * @param array $header + * @throws \OCA\Encryption\Exceptions\EncryptionException + */ + public static function getCipher($header) { + $cipher = isset($header['cipher']) ? $header['cipher'] : 'AES-128-CFB'; + + if ($cipher !== 'AES-256-CFB' && $cipher !== 'AES-128-CFB') { + + throw new \OCA\Encryption\Exceptions\EncryptionException('file header broken, no supported cipher defined', 40); + } + + return $cipher; + } + + /** + * generate header for encrypted file + */ + public static function generateHeader() { + $cipher = Helper::getCipher(); + $header = self::HEADERSTART . ':cipher:' . $cipher . ':' . self::HEADEREND; + + return $header; + } + } diff --git a/apps/files_encryption/lib/exceptions.php b/apps/files_encryption/lib/exceptions.php index a409b0f0fb2..3ea27faf406 100644 --- a/apps/files_encryption/lib/exceptions.php +++ b/apps/files_encryption/lib/exceptions.php @@ -22,6 +22,15 @@ namespace OCA\Encryption\Exceptions; +/** + * General encryption exception + * Possible Error Codes: + * 10 - unexpected end of encryption header + * 20 - unexpected blog size + * 30 - encryption header to large + * 40 - unknown cipher + * 50 - encryption failed + */ class EncryptionException extends \Exception { } diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index fed0788028f..5894c40fe92 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -141,19 +141,17 @@ class Helper { $view->file_put_contents('/public-keys/' . $recoveryKeyId . '.public.key', $keypair['publicKey']); - // Encrypt private key empty passphrase - $encryptedPrivateKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $recoveryPassword); - - // Save private key - $view->file_put_contents('/owncloud_private_key/' . $recoveryKeyId . '.private.key', $encryptedPrivateKey); + $cipher = \OCA\Encryption\Helper::getCipher(); + $encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], $recoveryPassword, $cipher); + if ($encryptedKey) { + Keymanager::setPrivateSystemKey($encryptedKey, $recoveryKeyId . '.private.key'); + // Set recoveryAdmin as enabled + $appConfig->setValue('files_encryption', 'recoveryAdminEnabled', 1); + $return = true; + } \OC_FileProxy::$enabled = true; - // Set recoveryAdmin as enabled - $appConfig->setValue('files_encryption', 'recoveryAdminEnabled', 1); - - $return = true; - } else { // get recovery key and check the password $util = new \OCA\Encryption\Util(new \OC\Files\View('/'), \OCP\User::getUser()); $return = $util->checkRecoveryPassword($recoveryPassword); @@ -227,7 +225,6 @@ class Helper { return $return; } - /** * checks if access is public/anonymous user * @return bool @@ -475,5 +472,25 @@ class Helper { return false; } + + /** + * read the cipher used for encryption from the config.php + * + * @return string + */ + public static function getCipher() { + + $cipher = \OCP\Config::getSystemValue('cipher', Crypt::DEFAULT_CIPHER); + + if ($cipher !== 'AES-256-CFB' && $cipher !== 'AES-128-CFB') { + \OCP\Util::writeLog('files_encryption', + 'wrong cipher defined in config.php, only AES-128-CFB and AES-256-CFB is supported. Fall back ' . Crypt::DEFAULT_CIPHER, + \OCP\Util::WARN); + + $cipher = Crypt::DEFAULT_CIPHER; + } + + return $cipher; + } } diff --git a/apps/files_encryption/lib/keymanager.php b/apps/files_encryption/lib/keymanager.php index da84e975a05..931469f4b74 100755 --- a/apps/files_encryption/lib/keymanager.php +++ b/apps/files_encryption/lib/keymanager.php @@ -258,9 +258,13 @@ class Keymanager { * @note Encryption of the private key must be performed by client code * as no encryption takes place here */ - public static function setPrivateKey($key) { + public static function setPrivateKey($key, $user = '') { - $user = \OCP\User::getUser(); + if ($user === '') { + $user = \OCP\User::getUser(); + } + + $header = Crypt::generateHeader(); $view = new \OC\Files\View('/' . $user . '/files_encryption'); @@ -271,7 +275,7 @@ class Keymanager { $view->mkdir(''); } - $result = $view->file_put_contents($user . '.private.key', $key); + $result = $view->file_put_contents($user . '.private.key', $header . $key); \OC_FileProxy::$enabled = $proxyStatus; @@ -279,6 +283,33 @@ class Keymanager { } + /** + * write private system key (recovery and public share key) to disk + * + * @param string $key encrypted key + * @param string $keyName name of the key file + * @return boolean + */ + public static function setPrivateSystemKey($key, $keyName) { + + $header = Crypt::generateHeader(); + + $view = new \OC\Files\View('/owncloud_private_key'); + + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + if (!$view->file_exists('')) { + $view->mkdir(''); + } + + $result = $view->file_put_contents($keyName, $header . $key); + + \OC_FileProxy::$enabled = $proxyStatus; + + return $result; + } + /** * store share key * diff --git a/apps/files_encryption/lib/session.php b/apps/files_encryption/lib/session.php index 4b28f0ce676..accefa559a2 100644 --- a/apps/files_encryption/lib/session.php +++ b/apps/files_encryption/lib/session.php @@ -80,11 +80,13 @@ class Session { $this->view->file_put_contents('/public-keys/' . $publicShareKeyId . '.public.key', $keypair['publicKey']); // Encrypt private key empty passphrase - $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], ''); - - // Save private key - $this->view->file_put_contents( - '/owncloud_private_key/' . $publicShareKeyId . '.private.key', $encryptedPrivateKey); + $cipher = \OCA\Encryption\Helper::getCipher(); + $encryptedKey = \OCA\Encryption\Crypt::symmetricEncryptFileContent($keypair['privateKey'], '', $cipher); + if ($encryptedKey) { + Keymanager::setPrivateSystemKey($encryptedKey, $publicShareKeyId . '.private.key'); + } else { + \OCP\Util::writeLog('files_encryption', 'Could not create public share keys', \OCP\Util::ERROR); + } \OC_FileProxy::$enabled = $proxyStatus; diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php index 341114214d5..f74812a7253 100644 --- a/apps/files_encryption/lib/stream.php +++ b/apps/files_encryption/lib/stream.php @@ -2,9 +2,10 @@ /** * ownCloud * - * @author Robin Appelman - * @copyright 2012 Sam Tuke , 2011 Robin Appelman - * + * @author Bjoern Schiessle, Robin Appelman + * @copyright 2014 Bjoern Schiessle + * 2012 Sam Tuke , + * 2011 Robin Appelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -49,9 +50,11 @@ namespace OCA\Encryption; * encryption proxies are used and keyfiles deleted. */ class Stream { + + const PADDING_CHAR = '-'; + private $plainKey; private $encKeyfiles; - private $rawPath; // The raw path relative to the data dir private $relPath; // rel path to users file dir private $userId; @@ -66,6 +69,9 @@ class Stream { private $newFile; // helper var, we only need to write the keyfile for new files private $isLocalTmpFile = false; // do we operate on a local tmp file private $localTmpFile; // path of local tmp file + private $headerWritten = false; + private $containHeader = false; // the file contain a header + private $cipher; // cipher used for encryption/decryption /** * @var \OC\Files\View @@ -87,6 +93,9 @@ class Stream { */ public function stream_open($path, $mode, $options, &$opened_path) { + // read default cipher from config + $this->cipher = Helper::getCipher(); + // assume that the file already exist before we decide it finally in getKey() $this->newFile = false; @@ -150,6 +159,9 @@ class Stream { } $this->size = $this->rootView->filesize($this->rawPath); + + $this->readHeader(); + } if ($this->isLocalTmpFile) { @@ -178,6 +190,29 @@ class Stream { } + private function readHeader() { + + if ($this->isLocalTmpFile) { + $handle = fopen($this->localTmpFile, 'r'); + } else { + $handle = $this->rootView->fopen($this->rawPath, 'r'); + } + + if (is_resource($handle)) { + $data = fread($handle, Crypt::BLOCKSIZE); + + $header = Crypt::parseHeader($data); + $this->cipher = Crypt::getCipher($header); + + // remeber that we found a header + if (!empty($header)) { + $this->containHeader = true; + } + + fclose($handle); + } + } + /** * Returns the current position of the file pointer * @return int position of the file pointer @@ -195,6 +230,11 @@ class Stream { $this->flush(); + // ignore the header and just overstep it + if ($this->containHeader) { + $offset += Crypt::BLOCKSIZE; + } + // this wrapper needs to return "true" for success. // the fseek call itself returns 0 on succeess return !fseek($this->handle, $offset, $whence); @@ -204,25 +244,25 @@ class Stream { /** * @param int $count * @return bool|string - * @throws \Exception + * @throws \OCA\Encryption\Exceptions\EncryptionException */ public function stream_read($count) { $this->writeCache = ''; - if ($count !== 8192) { - - // $count will always be 8192 https://bugs.php.net/bug.php?id=21641 - // This makes this function a lot simpler, but will break this class if the above 'bug' gets 'fixed' + if ($count !== Crypt::BLOCKSIZE) { \OCP\Util::writeLog('Encryption library', 'PHP "bug" 21641 no longer holds, decryption system requires refactoring', \OCP\Util::FATAL); - - die(); - + throw new \OCA\Encryption\Exceptions\EncryptionException('expected a blog size of 8192 byte', 20); } // Get the data from the file handle $data = fread($this->handle, $count); + // if this block contained the header we move on to the next block + if (Crypt::isHeader($data)) { + $data = fread($this->handle, $count); + } + $result = null; if (strlen($data)) { @@ -236,7 +276,7 @@ class Stream { } else { // Decrypt data - $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey); + $result = Crypt::symmetricDecryptFileContent($data, $this->plainKey, $this->cipher); } } @@ -254,7 +294,7 @@ class Stream { public function preWriteEncrypt($plainData, $key) { // Encrypt data to 'catfile', which includes IV - if ($encrypted = Crypt::symmetricEncryptFileContent($plainData, $key)) { + if ($encrypted = Crypt::symmetricEncryptFileContent($plainData, $key, $this->cipher)) { return $encrypted; @@ -317,6 +357,25 @@ class Stream { } + /** + * write header at beginning of encrypted file + * + * @throws Exceptions\EncryptionException + */ + private function writeHeader() { + + $header = Crypt::generateHeader(); + + if (strlen($header) > Crypt::BLOCKSIZE) { + throw new Exceptions\EncryptionException('max header size exceeded', 30); + } + + $paddedHeader = str_pad($header, Crypt::BLOCKSIZE, self::PADDING_CHAR, STR_PAD_RIGHT); + + fwrite($this->handle, $paddedHeader); + $this->headerWritten = true; + } + /** * Handle plain data from the stream, and write it in 8192 byte blocks * @param string $data data to be written to disk @@ -334,6 +393,10 @@ class Stream { return strlen($data); } + if ($this->headerWritten === false) { + $this->writeHeader(); + } + // Disable the file proxies so that encryption is not // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index e44a8bd3dda..495f22c4014 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -167,11 +167,12 @@ class Util { \OC_FileProxy::$enabled = false; // Encrypt private key with user pwd as passphrase - $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $passphrase); + $encryptedPrivateKey = Crypt::symmetricEncryptFileContent($keypair['privateKey'], $passphrase, Helper::getCipher()); // Save key-pair if ($encryptedPrivateKey) { - $this->view->file_put_contents($this->privateKeyPath, $encryptedPrivateKey); + $header = crypt::generateHeader(); + $this->view->file_put_contents($this->privateKeyPath, $header . $encryptedPrivateKey); $this->view->file_put_contents($this->publicKeyPath, $keypair['publicKey']); } @@ -384,8 +385,14 @@ class Util { && $this->isEncryptedPath($path) ) { - // get the size from filesystem - $size = $this->view->filesize($path); + $offset = 0; + if ($this->containHeader($path)) { + $offset = Crypt::BLOCKSIZE; + } + + // get the size from filesystem if the file contains a encryption header we + // we substract it + $size = $this->view->filesize($path) - $offset; // fast path, else the calculation for $lastChunkNr is bogus if ($size === 0) { @@ -396,15 +403,15 @@ class Util { // 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/ 8192) - 1; - $lastChunkSize = $size - ($lastChunkNr * 8192); + $lastChunkNr = ceil($size/ Crypt::BLOCKSIZE) - 1; + $lastChunkSize = $size - ($lastChunkNr * Crypt::BLOCKSIZE); // open stream $stream = fopen('crypt://' . $path, "r"); if (is_resource($stream)) { // calculate last chunk position - $lastChunckPos = ($lastChunkNr * 8192); + $lastChunckPos = ($lastChunkNr * Crypt::BLOCKSIZE); // seek to end if (@fseek($stream, $lastChunckPos) === -1) { @@ -438,6 +445,30 @@ class Util { return $result; } + /** + * check if encrypted file contain a encryption header + * + * @param string $path + * @return boolean + */ + private function containHeader($path) { + // Disable encryption proxy to read the raw data + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + + $isHeader = false; + $handle = $this->view->fopen($path, 'r'); + + if (is_resource($handle)) { + $firstBlock = fread($handle, Crypt::BLOCKSIZE); + $isHeader = Crypt::isHeader($firstBlock); + } + + \OC_FileProxy::$enabled = $proxyStatus; + + return $isHeader; + } + /** * fix the file size of the encrypted file * @param string $path absolute path -- cgit v1.2.3 From de9d3797ffc712f8fa3552411c82b24486461daf Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 21 Jul 2014 23:36:20 +0200 Subject: update existing unit tests --- apps/files_encryption/lib/crypt.php | 2 +- apps/files_encryption/tests/crypt.php | 129 ++--------------------------- apps/files_encryption/tests/keymanager.php | 4 +- apps/files_encryption/tests/share.php | 6 +- apps/files_encryption/tests/util.php | 2 +- 5 files changed, 16 insertions(+), 127 deletions(-) (limited to 'apps/files_encryption/lib') diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 8ca96899f88..7974598729e 100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -312,7 +312,7 @@ class Crypt { * * This function decrypts a file */ - public static function symmetricDecryptFileContent($keyfileContent, $passphrase = '', $cipher = 'AES-128-CFB') { + public static function symmetricDecryptFileContent($keyfileContent, $passphrase = '', $cipher = Crypt::DEFAULT_CIPHER) { if (!$keyfileContent) { diff --git a/apps/files_encryption/tests/crypt.php b/apps/files_encryption/tests/crypt.php index a1a51c749b0..d1ff6eec7dc 100755 --- a/apps/files_encryption/tests/crypt.php +++ b/apps/files_encryption/tests/crypt.php @@ -121,7 +121,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // test successful decrypt $crypted = Encryption\Crypt::symmetricEncryptFileContent($this->genPrivateKey, 'hat'); - $decrypted = Encryption\Crypt::decryptPrivateKey($crypted, 'hat'); + $header = Encryption\Crypt::generateHeader(); + + $decrypted = Encryption\Crypt::decryptPrivateKey($header . $crypted, 'hat'); $this->assertEquals($this->genPrivateKey, $decrypted); @@ -158,8 +160,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $filename = 'tmp-' . uniqid() . '.test'; - $util = new Encryption\Util(new \OC\Files\View(), $this->userId); - $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/'. $filename, $this->dataShort); // Test that data was successfully written @@ -178,26 +178,11 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // Check that the file was encrypted before being written to disk $this->assertNotEquals($this->dataShort, $retreivedCryptedFile); - // 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); - - // Manually decrypt - $manualDecrypt = Encryption\Crypt::symmetricDecryptFileContent($retreivedCryptedFile, $plainKeyfile); + // Get file contents with the encryption wrapper + $decrypted = file_get_contents('crypt:///' . $this->userId . '/files/'. $filename); // Check that decrypted data matches - $this->assertEquals($this->dataShort, $manualDecrypt); + $this->assertEquals($this->dataShort, $decrypted); // Teardown $this->view->unlink($this->userId . '/files/' . $filename); @@ -217,8 +202,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // Generate a a random filename $filename = 'tmp-' . uniqid() . '.test'; - $util = new Encryption\Util(new \OC\Files\View(), $this->userId); - // Save long data as encrypted file using stream wrapper $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong . $this->dataLong); @@ -239,50 +222,9 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { // 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 = ''; + $decrypted = file_get_contents('crypt:///' . $this->userId . '/files/'. $filename); - // 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); + $this->assertEquals($this->dataLong . $this->dataLong, $decrypted); // Teardown @@ -292,59 +234,6 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { } - /** - * @medium - * Test that data that is read by the crypto stream wrapper - */ - function testSymmetricStreamDecryptShortFileContent() { - - $filename = 'tmp-' . uniqid(); - - // Save long data as encrypted file using stream wrapper - $cryptedFile = file_put_contents('crypt:///'. $this->userId . '/files/' . $filename, $this->dataShort); - - // 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; - - $this->assertTrue(Encryption\Crypt::isEncryptedMeta($filename)); - - \OC_FileProxy::$enabled = $proxyStatus; - - // Get file decrypted contents - $decrypt = file_get_contents('crypt:///' . $this->userId . '/files/' . $filename); - - $this->assertEquals($this->dataShort, $decrypt); - - // tear down - $this->view->unlink($this->userId . '/files/' . $filename); - } - - /** - * @medium - */ - function testSymmetricStreamDecryptLongFileContent() { - - $filename = 'tmp-' . uniqid(); - - // Save long data as encrypted file using stream wrapper - $cryptedFile = file_put_contents('crypt:///' . $this->userId . '/files/' . $filename, $this->dataLong); - - // Test that data was successfully written - $this->assertTrue(is_int($cryptedFile)); - - // Get file decrypted contents - $decrypt = file_get_contents('crypt:///' . $this->userId . '/files/' . $filename); - - $this->assertEquals($this->dataLong, $decrypt); - - // tear down - $this->view->unlink($this->userId . '/files/' . $filename); - } - /** * @medium */ @@ -354,7 +243,7 @@ class Test_Encryption_Crypt extends \PHPUnit_Framework_TestCase { $this->assertFalse(Encryption\Crypt::isCatfileContent($this->legacyEncryptedData)); - $keyfileContent = Encryption\Crypt::symmetricEncryptFileContent($this->dataUrl, 'hat'); + $keyfileContent = Encryption\Crypt::symmetricEncryptFileContent($this->dataUrl, 'hat', 'AES-128-CFB'); $this->assertTrue(Encryption\Crypt::isCatfileContent($keyfileContent)); diff --git a/apps/files_encryption/tests/keymanager.php b/apps/files_encryption/tests/keymanager.php index e779f8341e6..b5537837051 100644 --- a/apps/files_encryption/tests/keymanager.php +++ b/apps/files_encryption/tests/keymanager.php @@ -107,7 +107,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $key = Encryption\Keymanager::getPrivateKey($this->view, $this->userId); - $privateKey = Encryption\Crypt::symmetricDecryptFileContent($key, $this->pass); + $privateKey = Encryption\Crypt::decryptPrivateKey($key, $this->pass); $res = openssl_pkey_get_private($privateKey); @@ -189,7 +189,7 @@ class Test_Encryption_Keymanager extends \PHPUnit_Framework_TestCase { $this->assertArrayHasKey('key', $sslInfoPublic); - $privateKey = Encryption\Crypt::symmetricDecryptFileContent($keys['privateKey'], $this->pass); + $privateKey = Encryption\Crypt::decryptPrivateKey($keys['privateKey'], $this->pass); $resPrivate = openssl_pkey_get_private($privateKey); diff --git a/apps/files_encryption/tests/share.php b/apps/files_encryption/tests/share.php index 7bbea6488bc..1f1304bb527 100755 --- a/apps/files_encryption/tests/share.php +++ b/apps/files_encryption/tests/share.php @@ -540,9 +540,9 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase { . $this->filename . '.' . $publicShareKeyId . '.shareKey')); // some hacking to simulate public link - $GLOBALS['app'] = 'files_sharing'; - $GLOBALS['fileOwner'] = \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1; - \OC_User::setUserId(false); + //$GLOBALS['app'] = 'files_sharing'; + //$GLOBALS['fileOwner'] = \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1; + \Test_Encryption_Util::logoutHelper(); // get file contents $retrievedCryptedFile = file_get_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 3142b83c5a6..480f14852f3 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -490,7 +490,7 @@ class Test_Encryption_Util extends \PHPUnit_Framework_TestCase { public static function logoutHelper() { \OC_Util::tearDownFS(); - \OC_User::setUserId(''); + \OC_User::setUserId(false); \OC\Files\Filesystem::tearDown(); } -- cgit v1.2.3