]> source.dussan.org Git - nextcloud-server.git/commitdiff
write encrypted file to disc
authorBjoern Schiessle <schiessle@owncloud.com>
Thu, 26 Mar 2015 11:23:36 +0000 (12:23 +0100)
committerThomas Müller <thomas.mueller@tmit.eu>
Tue, 7 Apr 2015 11:30:27 +0000 (13:30 +0200)
apps/encryption/appinfo/encryption.php
apps/encryption/lib/crypto/crypt.php
apps/encryption/lib/crypto/encryption.php
apps/encryption/lib/keymanager.php

index a3ca8ec5624cb10f473305003e8c4d8c1eed4c91..8be3cae5ad5aa8f5b619f7e195fa90ef5ab85f59 100644 (file)
@@ -27,7 +27,6 @@ use OCA\Encryption\Crypto\Crypt;
 use OCA\Encryption\HookManager;
 use OCA\Encryption\Hooks\UserHooks;
 use OCA\Encryption\KeyManager;
-use OCA\Encryption\Migrator;
 use OCA\Encryption\Recovery;
 use OCA\Encryption\Users\Setup;
 use OCA\Encryption\Util;
@@ -98,7 +97,7 @@ class Encryption extends \OCP\AppFramework\App {
        public function registerEncryptionModule() {
                $container = $this->getContainer();
                $container->registerService('EncryptionModule', function (IAppContainer $c) {
-                       return new \OCA\Encryption\Crypto\Encryption($c->query('Crypt'));
+                       return new \OCA\Encryption\Crypto\Encryption($c->query('Crypt'), $c->query('KeyManager'));
                });
                $module = $container->query('EncryptionModule');
                $this->encryptionManager->registerEncryptionModule($module);
@@ -122,8 +121,7 @@ class Encryption extends \OCP\AppFramework\App {
                        function (IAppContainer $c) {
                                $server = $c->getServer();
 
-                               $moduleId = $c->query('EncryptionModule')->getId();
-                               return new KeyManager($server->getEncryptionKeyStorage($moduleId),
+                               return new KeyManager($server->getEncryptionKeyStorage(\OCA\Encryption\Crypto\Encryption::ID),
                                        $c->query('Crypt'),
                                        $server->getConfig(),
                                        $server->getUserSession(),
@@ -137,14 +135,13 @@ class Encryption extends \OCP\AppFramework\App {
                        function (IAppContainer $c) {
                                $server = $c->getServer();
 
-                               $moduleId = $c->query('EncryptionModule')->getId();
                                return new Recovery(
                                        $server->getUserSession(),
                                        $c->query('Crypt'),
                                        $server->getSecureRandom(),
                                        $c->query('KeyManager'),
                                        $server->getConfig(),
-                                       $server->getEncryptionKeyStorage($moduleId));
+                                       $server->getEncryptionKeyStorage(\OCA\Encryption\Crypto\Encryption::ID));
                        });
 
                $container->registerService('UserSetup',
index 9fb93485ef773211a5c822c9c24db206474d92aa..c9f02bfa1cc447e33ef04a0032358671c21e4afc 100644 (file)
@@ -25,6 +25,7 @@ namespace OCA\Encryption\Crypto;
 use OC\Encryption\Exceptions\DecryptionFailedException;
 use OC\Encryption\Exceptions\EncryptionFailedException;
 use OC\Encryption\Exceptions\GenericEncryptionException;
+use OCA\Encryption\KeyManager;
 use OCA\Files_Encryption\Exception\MultiKeyDecryptException;
 use OCA\Files_Encryption\Exception\MultiKeyEncryptException;
 use OCP\IConfig;
@@ -379,6 +380,21 @@ class Crypt {
                throw new GenericEncryptionException('Generating IV Failed');
        }
 
+       /**
+        * Generate a pseudo random 256-bit ASCII key, used as file key
+        * @return string
+        */
+       public static function generateFileKey() {
+               // Generate key
+               $key = base64_encode(openssl_random_pseudo_bytes(32, $strong));
+               if (!$key || !$strong) {
+                               // If OpenSSL indicates randomness is insecure, log error
+                               throw new \Exception('Encryption library, Insecure symmetric key was generated using openssl_random_pseudo_bytes()');
+               }
+
+               return $key;
+       }
+
        /**
         * Check if a file's contents contains an IV and is symmetrically encrypted
         *
index a29575c11e07e33b094e91745c459a21939527f0..66cb1dc434b1e9774451db830d6140844d6b9512 100644 (file)
@@ -11,24 +11,51 @@ namespace OCA\Encryption\Crypto;
 
 
 use OCP\Encryption\IEncryptionModule;
+use OCA\Encryption\KeyManager;
 
 class Encryption implements IEncryptionModule {
 
+       const ID = '42';
+
        /**
         * @var Crypt
         */
        private $crypt;
 
-       public function __construct(Crypt $crypt) {
+       /** @var string */
+       private $cipher;
+
+       /** @var string */
+       private $path;
+
+       /** @var string */
+       private $user;
+
+       /** @var string */
+       private $fileKey;
+
+       /** @var string */
+       private $writeCache;
+
+       /** @var KeyManager */
+       private $keymanager;
+
+       /** @var array */
+       private $accessList;
+
+       /** @var boolean */
+       private $isWriteOperation;
+
+       public function __construct(Crypt $crypt, KeyManager $keymanager) {
                $this->crypt = $crypt;
+               $this->keymanager = $keymanager;
        }
 
        /**
         * @return string defining the technical unique id
         */
        public function getId() {
-               // we need to hard code this value
-               return md5($this->getDisplayName());
+               return self::ID;
        }
 
        /**
@@ -46,6 +73,7 @@ class Encryption implements IEncryptionModule {
         * chunks
         *
         * @param string $path to the file
+        * @param string $user who read/write the file
         * @param array $header contains the header data read from the file
         * @param array $accessList who has access to the file contains the key 'users' and 'public'
         *
@@ -53,9 +81,23 @@ class Encryption implements IEncryptionModule {
         *                       written to the header, in case of a write operation
         *                       or if no additional data is needed return a empty array
         */
-       public function begin($path, $header, $accessList) {
+       public function begin($path, $user, $header, $accessList) {
+
+               if (isset($header['cipher'])) {
+                       $this->cipher = $header['cipher'];
+               } else {
+                       $this->cipher = $this->crypt->getCipher();
+               }
+
+               $this->path = $path;
+               $this->accessList = $accessList;
+               $this->user = $user;
+               $this->writeCache = '';
+               $this->isWriteOperation = false;
 
-               $cipher = $header[''];
+               $this->fileKey = $this->keymanager->getFileKey($path);
+
+               return array('cipher' => $this->cipher);
        }
 
        /**
@@ -68,7 +110,20 @@ class Encryption implements IEncryptionModule {
         *                of a write operation
         */
        public function end($path) {
-               // TODO: Implement end() method.
+               $result = '';
+               if ($this->isWriteOperation) {
+                       if (!empty($this->writeCache)) {
+                               $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey);
+                               $this->writeCache = '';
+                       }
+                       $publicKeys = array();
+                       foreach ($this->accessList['users'] as $user) {
+                               $publicKeys[] = $this->keymanager->getPublicKey($user);
+                       }
+
+                       $result = $this->crypt->multiKeyEncrypt($this->fileKey, $publicKeys);
+               }
+               return $result;
        }
 
        /**
@@ -78,21 +133,80 @@ class Encryption implements IEncryptionModule {
         * @return mixed encrypted data
         */
        public function encrypt($data) {
-               // Todo: xxx Update Signature and usages
-               // passphrase is file key decrypted with user private/share key
-               $this->symmetricEncryptFileContent($data);
+               $this->isWriteOperation = true;
+               if (empty($this->fileKey)) {
+                       $this->fileKey = $this->crypt->generateFileKey();
+               }
+
+               // If extra data is left over from the last round, make sure it
+               // is integrated into the next 6126 / 8192 block
+               if ($this->writeCache) {
+
+                       // Concat writeCache to start of $data
+                       $data = $this->writeCache . $data;
+
+                       // Clear the write cache, ready for reuse - it has been
+                       // flushed and its old contents processed
+                       $this->writeCache = '';
+
+               }
+
+               $encrypted = '';
+               // While there still remains some data to be processed & written
+               while (strlen($data) > 0) {
+
+                       // Remaining length for this iteration, not of the
+                       // entire file (may be greater than 8192 bytes)
+                       $remainingLength = strlen($data);
+
+                       // If data remaining to be written is less than the
+                       // size of 1 6126 byte block
+                       if ($remainingLength < 6126) {
+
+                               // Set writeCache to contents of $data
+                               // The writeCache will be carried over to the
+                               // next write round, and added to the start of
+                               // $data to ensure that written blocks are
+                               // always the correct length. If there is still
+                               // data in writeCache after the writing round
+                               // has finished, then the data will be written
+                               // to disk by $this->flush().
+                               $this->writeCache = $data;
+
+                               // Clear $data ready for next round
+                               $data = '';
+
+                       } else {
+
+                               // Read the chunk from the start of $data
+                               $chunk = substr($data, 0, 6126);
+
+                               $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey);
+
+                               // Remove the chunk we just processed from
+                               // $data, leaving only unprocessed data in $data
+                               // var, for handling on the next round
+                               $data = substr($data, 6126);
+
+                       }
+
+               }
+
+               return $encrypted;
        }
 
        /**
         * decrypt data
         *
         * @param string $data you want to decrypt
-        * @param string $user decrypt as user (null for public access)
         * @return mixed decrypted data
         */
-       public function decrypt($data, $user) {
-               // Todo: xxx Update Usages?
-               $this->symmetricDecryptFileContent($data, $user);
+       public function decrypt($data) {
+               $result = '';
+               if (!empty($data)) {
+                       $result = $this->crypt->symmetricDecryptFileContent($data, $this->fileKey);
+               }
+               return $result;
        }
 
        /**
@@ -113,7 +227,7 @@ class Encryption implements IEncryptionModule {
         * @return boolean
         */
        public function shouldEncrypt($path) {
-               // TODO: Implement shouldEncrypt() method.
+               return true;
        }
 
        /**
@@ -133,6 +247,6 @@ class Encryption implements IEncryptionModule {
         * @return integer
         */
        public function getUnencryptedBlockSize() {
-               // TODO: Implement getUnencryptedBlockSize() method.
+               return 6126;
        }
 }
index c1c1f9811dcb95097d56592a6b8bec834e0e77b3..120254defdd18070daaff844fb1841e83cdd49cc 100644 (file)
@@ -62,21 +62,21 @@ class KeyManager {
        /**
         * @var string
         */
-       private $publicKeyId = 'public';
+       private $publicKeyId = 'publicKey';
        /**
         * @var string
         */
-       private $privateKeyId = 'private';
+       private $privateKeyId = 'privateKey';
 
        /**
         * @var string
         */
-       private $shareKeyId = 'sharekey';
+       private $shareKeyId = 'shareKey';
 
        /**
         * @var string
         */
-       private $fileKeyId = 'filekey';
+       private $fileKeyId = 'fileKey';
        /**
         * @var IConfig
         */