write encrypted file to disc

This commit is contained in:
Bjoern Schiessle 2015-03-26 12:23:36 +01:00 committed by Thomas Müller
parent 7ffd77fac9
commit 198b73fe32
4 changed files with 152 additions and 25 deletions

View File

@ -27,7 +27,6 @@ use OCA\Encryption\Crypto\Crypt;
use OCA\Encryption\HookManager; use OCA\Encryption\HookManager;
use OCA\Encryption\Hooks\UserHooks; use OCA\Encryption\Hooks\UserHooks;
use OCA\Encryption\KeyManager; use OCA\Encryption\KeyManager;
use OCA\Encryption\Migrator;
use OCA\Encryption\Recovery; use OCA\Encryption\Recovery;
use OCA\Encryption\Users\Setup; use OCA\Encryption\Users\Setup;
use OCA\Encryption\Util; use OCA\Encryption\Util;
@ -98,7 +97,7 @@ class Encryption extends \OCP\AppFramework\App {
public function registerEncryptionModule() { public function registerEncryptionModule() {
$container = $this->getContainer(); $container = $this->getContainer();
$container->registerService('EncryptionModule', function (IAppContainer $c) { $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'); $module = $container->query('EncryptionModule');
$this->encryptionManager->registerEncryptionModule($module); $this->encryptionManager->registerEncryptionModule($module);
@ -122,8 +121,7 @@ class Encryption extends \OCP\AppFramework\App {
function (IAppContainer $c) { function (IAppContainer $c) {
$server = $c->getServer(); $server = $c->getServer();
$moduleId = $c->query('EncryptionModule')->getId(); return new KeyManager($server->getEncryptionKeyStorage(\OCA\Encryption\Crypto\Encryption::ID),
return new KeyManager($server->getEncryptionKeyStorage($moduleId),
$c->query('Crypt'), $c->query('Crypt'),
$server->getConfig(), $server->getConfig(),
$server->getUserSession(), $server->getUserSession(),
@ -137,14 +135,13 @@ class Encryption extends \OCP\AppFramework\App {
function (IAppContainer $c) { function (IAppContainer $c) {
$server = $c->getServer(); $server = $c->getServer();
$moduleId = $c->query('EncryptionModule')->getId();
return new Recovery( return new Recovery(
$server->getUserSession(), $server->getUserSession(),
$c->query('Crypt'), $c->query('Crypt'),
$server->getSecureRandom(), $server->getSecureRandom(),
$c->query('KeyManager'), $c->query('KeyManager'),
$server->getConfig(), $server->getConfig(),
$server->getEncryptionKeyStorage($moduleId)); $server->getEncryptionKeyStorage(\OCA\Encryption\Crypto\Encryption::ID));
}); });
$container->registerService('UserSetup', $container->registerService('UserSetup',

View File

@ -25,6 +25,7 @@ namespace OCA\Encryption\Crypto;
use OC\Encryption\Exceptions\DecryptionFailedException; use OC\Encryption\Exceptions\DecryptionFailedException;
use OC\Encryption\Exceptions\EncryptionFailedException; use OC\Encryption\Exceptions\EncryptionFailedException;
use OC\Encryption\Exceptions\GenericEncryptionException; use OC\Encryption\Exceptions\GenericEncryptionException;
use OCA\Encryption\KeyManager;
use OCA\Files_Encryption\Exception\MultiKeyDecryptException; use OCA\Files_Encryption\Exception\MultiKeyDecryptException;
use OCA\Files_Encryption\Exception\MultiKeyEncryptException; use OCA\Files_Encryption\Exception\MultiKeyEncryptException;
use OCP\IConfig; use OCP\IConfig;
@ -379,6 +380,21 @@ class Crypt {
throw new GenericEncryptionException('Generating IV Failed'); 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 * Check if a file's contents contains an IV and is symmetrically encrypted
* *

View File

@ -11,24 +11,51 @@ namespace OCA\Encryption\Crypto;
use OCP\Encryption\IEncryptionModule; use OCP\Encryption\IEncryptionModule;
use OCA\Encryption\KeyManager;
class Encryption implements IEncryptionModule { class Encryption implements IEncryptionModule {
const ID = '42';
/** /**
* @var Crypt * @var Crypt
*/ */
private $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->crypt = $crypt;
$this->keymanager = $keymanager;
} }
/** /**
* @return string defining the technical unique id * @return string defining the technical unique id
*/ */
public function getId() { public function getId() {
// we need to hard code this value return self::ID;
return md5($this->getDisplayName());
} }
/** /**
@ -46,6 +73,7 @@ class Encryption implements IEncryptionModule {
* chunks * chunks
* *
* @param string $path to the file * @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 $header contains the header data read from the file
* @param array $accessList who has access to the file contains the key 'users' and 'public' * @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 * written to the header, in case of a write operation
* or if no additional data is needed return a empty array * or if no additional data is needed return a empty array
*/ */
public function begin($path, $header, $accessList) { public function begin($path, $user, $header, $accessList) {
$cipher = $header['']; 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;
$this->fileKey = $this->keymanager->getFileKey($path);
return array('cipher' => $this->cipher);
} }
/** /**
@ -68,7 +110,20 @@ class Encryption implements IEncryptionModule {
* of a write operation * of a write operation
*/ */
public function end($path) { 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 * @return mixed encrypted data
*/ */
public function encrypt($data) { public function encrypt($data) {
// Todo: xxx Update Signature and usages $this->isWriteOperation = true;
// passphrase is file key decrypted with user private/share key if (empty($this->fileKey)) {
$this->symmetricEncryptFileContent($data); $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 * decrypt data
* *
* @param string $data you want to decrypt * @param string $data you want to decrypt
* @param string $user decrypt as user (null for public access)
* @return mixed decrypted data * @return mixed decrypted data
*/ */
public function decrypt($data, $user) { public function decrypt($data) {
// Todo: xxx Update Usages? $result = '';
$this->symmetricDecryptFileContent($data, $user); if (!empty($data)) {
$result = $this->crypt->symmetricDecryptFileContent($data, $this->fileKey);
}
return $result;
} }
/** /**
@ -113,7 +227,7 @@ class Encryption implements IEncryptionModule {
* @return boolean * @return boolean
*/ */
public function shouldEncrypt($path) { public function shouldEncrypt($path) {
// TODO: Implement shouldEncrypt() method. return true;
} }
/** /**
@ -133,6 +247,6 @@ class Encryption implements IEncryptionModule {
* @return integer * @return integer
*/ */
public function getUnencryptedBlockSize() { public function getUnencryptedBlockSize() {
// TODO: Implement getUnencryptedBlockSize() method. return 6126;
} }
} }

View File

@ -62,21 +62,21 @@ class KeyManager {
/** /**
* @var string * @var string
*/ */
private $publicKeyId = 'public'; private $publicKeyId = 'publicKey';
/** /**
* @var string * @var string
*/ */
private $privateKeyId = 'private'; private $privateKeyId = 'privateKey';
/** /**
* @var string * @var string
*/ */
private $shareKeyId = 'sharekey'; private $shareKeyId = 'shareKey';
/** /**
* @var string * @var string
*/ */
private $fileKeyId = 'filekey'; private $fileKeyId = 'fileKey';
/** /**
* @var IConfig * @var IConfig
*/ */