diff options
Diffstat (limited to 'apps/encryption/lib/crypto/encryption.php')
-rw-r--r-- | apps/encryption/lib/crypto/encryption.php | 84 |
1 files changed, 61 insertions, 23 deletions
diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php index 3b66684a7f4..a637f52a869 100644 --- a/apps/encryption/lib/crypto/encryption.php +++ b/apps/encryption/lib/crypto/encryption.php @@ -29,6 +29,7 @@ namespace OCA\Encryption\Crypto; use OC\Encryption\Exceptions\DecryptionFailedException; +use OC\Files\View; use OCA\Encryption\Exceptions\PublicKeyMissingException; use OCA\Encryption\Session; use OCA\Encryption\Util; @@ -56,6 +57,9 @@ class Encryption implements IEncryptionModule { private $path; /** @var string */ + private $realPath; + + /** @var string */ private $user; /** @var string */ @@ -94,6 +98,16 @@ class Encryption implements IEncryptionModule { /** @var DecryptAll */ private $decryptAll; + /** @var int unencrypted block size if block contains signature */ + private $unencryptedBlockSizeSigned = 6072; + + /** @var int unencrypted block size */ + private $unencryptedBlockSize = 6126; + + /** @var int Current version of the file */ + private $version = 0; + + /** * * @param Crypt $crypt @@ -156,8 +170,8 @@ class Encryption implements IEncryptionModule { * or if no additional data is needed return a empty array */ public function begin($path, $user, $mode, array $header, array $accessList) { - $this->path = $this->getPathToRealFile($path); + $this->realPath = $path; $this->accessList = $accessList; $this->user = $user; $this->isWriteOperation = false; @@ -173,6 +187,8 @@ class Encryption implements IEncryptionModule { $this->fileKey = $this->keyManager->getFileKey($this->path, $this->user); } + $this->version = (int)$this->keyManager->getVersion($this->realPath, new View()); + if ( $mode === 'w' || $mode === 'w+' @@ -185,17 +201,17 @@ class Encryption implements IEncryptionModule { } } - if (isset($header['cipher'])) { - $this->cipher = $header['cipher']; - } elseif ($this->isWriteOperation) { + if ($this->isWriteOperation) { $this->cipher = $this->crypt->getCipher(); + } elseif (isset($header['cipher'])) { + $this->cipher = $header['cipher']; } else { // if we read a file without a header we fall-back to the legacy cipher // which was used in <=oC6 $this->cipher = $this->crypt->getLegacyCipher(); } - return array('cipher' => $this->cipher); + return array('cipher' => $this->cipher, 'signed' => 'true'); } /** @@ -204,17 +220,25 @@ class Encryption implements IEncryptionModule { * buffer. * * @param string $path to the file + * @param int $position * @return string remained data which should be written to the file in case * of a write operation * @throws PublicKeyMissingException * @throws \Exception * @throws \OCA\Encryption\Exceptions\MultiKeyEncryptException */ - public function end($path) { + public function end($path, $position = 0) { $result = ''; if ($this->isWriteOperation) { + // Partial files do not increase the version + if(\OC\Files\Cache\Scanner::isPartialFile($path)) { + $version = $this->version; + } else { + $version = $this->version + 1; + } + $this->keyManager->setVersion($this->path, $this->version+1, new View()); if (!empty($this->writeCache)) { - $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey); + $result = $this->crypt->symmetricEncryptFileContent($this->writeCache, $this->fileKey, $version, $position); $this->writeCache = ''; } $publicKeys = array(); @@ -248,12 +272,12 @@ class Encryption implements IEncryptionModule { * encrypt data * * @param string $data you want to encrypt + * @param int $position * @return string encrypted data */ - public function encrypt($data) { - + public function encrypt($data, $position = 0) { // If extra data is left over from the last round, make sure it - // is integrated into the next 6126 / 8192 block + // is integrated into the next block if ($this->writeCache) { // Concat writeCache to start of $data @@ -275,7 +299,7 @@ class Encryption implements IEncryptionModule { // If data remaining to be written is less than the // size of 1 6126 byte block - if ($remainingLength < 6126) { + if ($remainingLength < $this->unencryptedBlockSizeSigned) { // Set writeCache to contents of $data // The writeCache will be carried over to the @@ -293,14 +317,20 @@ class Encryption implements IEncryptionModule { } else { // Read the chunk from the start of $data - $chunk = substr($data, 0, 6126); + $chunk = substr($data, 0, $this->unencryptedBlockSizeSigned); - $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey); + // Partial files do not increase the version + if(\OC\Files\Cache\Scanner::isPartialFile($this->path)) { + $version = $this->version; + } else { + $version = $this->version + 1; + } + $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $version, $position); // 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); + $data = substr($data, $this->unencryptedBlockSizeSigned); } @@ -313,10 +343,11 @@ class Encryption implements IEncryptionModule { * decrypt data * * @param string $data you want to decrypt + * @param int $position * @return string decrypted data * @throws DecryptionFailedException */ - public function decrypt($data) { + public function decrypt($data, $position = 0) { if (empty($this->fileKey)) { $msg = 'Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.'; $hint = $this->l->t('Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.'); @@ -325,11 +356,7 @@ class Encryption implements IEncryptionModule { throw new DecryptionFailedException($msg, $hint); } - $result = ''; - if (!empty($data)) { - $result = $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher); - } - return $result; + return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position); } /** @@ -342,6 +369,10 @@ class Encryption implements IEncryptionModule { */ public function update($path, $uid, array $accessList) { $fileKey = $this->keyManager->getFileKey($path, $uid); + if(empty($this->realPath)) { + $this->realPath = $path; + } + $version = $this->keyManager->getVersion($this->realPath, new View()); if (!empty($fileKey)) { @@ -362,6 +393,8 @@ class Encryption implements IEncryptionModule { $this->keyManager->setAllFileKeys($path, $encryptedFileKey); + $this->keyManager->setVersion($path, $version, new View()); + } else { $this->logger->debug('no file key found, we assume that the file "{file}" is not encrypted', array('file' => $path, 'app' => 'encryption')); @@ -407,10 +440,15 @@ class Encryption implements IEncryptionModule { * get size of the unencrypted payload per block. * ownCloud read/write files with a block size of 8192 byte * - * @return integer + * @param bool $signed + * @return int */ - public function getUnencryptedBlockSize() { - return 6126; + public function getUnencryptedBlockSize($signed = false) { + if ($signed === false) { + return $this->unencryptedBlockSize; + } + + return $this->unencryptedBlockSizeSigned; } /** |