From cf3a8f274f05170b69cb3872d0d8c9045a5876d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= <bjoern@schiessle.org>
Date: Tue, 5 Jan 2016 15:29:44 +0100
Subject: [PATCH] make it backward compatible to work with signed and un-signed
 files

---
 apps/encryption/lib/crypto/crypt.php          |  4 +--
 apps/encryption/lib/crypto/encryption.php     | 25 +++++++++++++------
 .../files/storage/wrapper/encryption.php      |  6 +++--
 lib/private/files/stream/encryption.php       | 10 +++++---
 lib/public/encryption/iencryptionmodule.php   |  7 +++---
 5 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/apps/encryption/lib/crypto/crypt.php b/apps/encryption/lib/crypto/crypt.php
index f4c47d33f00..e935f364551 100644
--- a/apps/encryption/lib/crypto/crypt.php
+++ b/apps/encryption/lib/crypto/crypt.php
@@ -462,7 +462,7 @@ class Crypt {
 	 */
 	private function checkSignature($data, $passPhrase, $expectedSignature) {
 		$signature = $this->createSignature($data, $passPhrase);
-		if (hash_equals($expectedSignature, $signature)) {
+		if (!hash_equals($expectedSignature, $signature)) {
 			throw new HintException('Bad Signature', $this->l->t('Bad Signature'));
 		}
 	}
@@ -517,7 +517,7 @@ class Crypt {
 			$meta = substr($catFile, -22);
 			$iv = substr($meta, -16);
 			$sig = false;
-			$encrypted = substr($catFile, 0, -93);
+			$encrypted = substr($catFile, 0, -22);
 		}
 
 		return [
diff --git a/apps/encryption/lib/crypto/encryption.php b/apps/encryption/lib/crypto/encryption.php
index 7099f53e2ab..4843284f7a3 100644
--- a/apps/encryption/lib/crypto/encryption.php
+++ b/apps/encryption/lib/crypto/encryption.php
@@ -94,8 +94,12 @@ 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 = 6072;
+	private $unencryptedBlockSize = 6126;
+
 
 	/**
 	 *
@@ -198,7 +202,7 @@ class Encryption implements IEncryptionModule {
 			$this->cipher = $this->crypt->getLegacyCipher();
 		}
 
-		return array('cipher' => $this->cipher);
+		return array('cipher' => $this->cipher, 'signed' => 'true');
 	}
 
 	/**
@@ -278,7 +282,7 @@ class Encryption implements IEncryptionModule {
 
 			// If data remaining to be written is less than the
 			// size of 1 6126 byte block
-			if ($remainingLength < $this->unencryptedBlockSize) {
+			if ($remainingLength < $this->unencryptedBlockSizeSigned) {
 
 				// Set writeCache to contents of $data
 				// The writeCache will be carried over to the
@@ -296,14 +300,14 @@ class Encryption implements IEncryptionModule {
 			} else {
 
 				// Read the chunk from the start of $data
-				$chunk = substr($data, 0, $this->unencryptedBlockSize);
+				$chunk = substr($data, 0, $this->unencryptedBlockSizeSigned);
 
 				$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, $this->unencryptedBlockSize);
+				$data = substr($data, $this->unencryptedBlockSizeSigned);
 
 			}
 
@@ -410,10 +414,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 $this->unencryptedBlockSize;
+	public function getUnencryptedBlockSize($signed = false) {
+		if ($signed === false) {
+			return $this->unencryptedBlockSize;
+		}
+
+		return $this->unencryptedBlockSizeSigned;
 	}
 
 	/**
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index f358bd59239..96d642e7780 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -343,6 +343,7 @@ class Encryption extends Wrapper {
 		$shouldEncrypt = false;
 		$encryptionModule = null;
 		$header = $this->getHeader($path);
+		$signed = (isset($header['signed']) && $header['signed'] === 'true') ? true : false;
 		$fullPath = $this->getFullPath($path);
 		$encryptionModuleId = $this->util->getEncryptionModuleId($header);
 
@@ -377,7 +378,7 @@ class Encryption extends Wrapper {
 					|| $mode === 'wb'
 					|| $mode === 'wb+'
 				) {
-					// don't overwrite encrypted files if encyption is not enabled
+					// don't overwrite encrypted files if encryption is not enabled
 					if ($targetIsEncrypted && $encryptionEnabled === false) {
 						throw new GenericEncryptionException('Tried to access encrypted file but encryption is not enabled');
 					}
@@ -385,6 +386,7 @@ class Encryption extends Wrapper {
 						// if $encryptionModuleId is empty, the default module will be used
 						$encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId);
 						$shouldEncrypt = $encryptionModule->shouldEncrypt($fullPath);
+						$signed = true;
 					}
 				} else {
 					$info = $this->getCache()->get($path);
@@ -422,7 +424,7 @@ class Encryption extends Wrapper {
 				}
 				$handle = \OC\Files\Stream\Encryption::wrap($source, $path, $fullPath, $header,
 					$this->uid, $encryptionModule, $this->storage, $this, $this->util, $this->fileHelper, $mode,
-					$size, $unencryptedSize, $headerSize);
+					$size, $unencryptedSize, $headerSize, $signed);
 				return $handle;
 			}
 
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index c884cd8fa07..11e2b218d17 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -110,7 +110,8 @@ class Encryption extends Wrapper {
 			'size',
 			'unencryptedSize',
 			'encryptionStorage',
-			'headerSize'
+			'headerSize',
+			'signed'
 		);
 	}
 
@@ -132,6 +133,7 @@ class Encryption extends Wrapper {
 	 * @param int $size
 	 * @param int $unencryptedSize
 	 * @param int $headerSize
+	 * @param bool $signed
 	 * @param string $wrapper stream wrapper class
 	 * @return resource
 	 *
@@ -148,6 +150,7 @@ class Encryption extends Wrapper {
 								$size,
 								$unencryptedSize,
 								$headerSize,
+								$signed,
 								$wrapper =  'OC\Files\Stream\Encryption') {
 
 		$context = stream_context_create(array(
@@ -164,7 +167,8 @@ class Encryption extends Wrapper {
 				'size' => $size,
 				'unencryptedSize' => $unencryptedSize,
 				'encryptionStorage' => $encStorage,
-				'headerSize' => $headerSize
+				'headerSize' => $headerSize,
+				'signed' => $signed
 			)
 		));
 
@@ -225,7 +229,7 @@ class Encryption extends Wrapper {
 		$this->position = 0;
 		$this->cache = '';
 		$this->writeFlag = false;
-		$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize();
+		$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize($this->signed);
 
 		if (
 			$mode === 'w'
diff --git a/lib/public/encryption/iencryptionmodule.php b/lib/public/encryption/iencryptionmodule.php
index 426e4ddecce..45e0b79c2a9 100644
--- a/lib/public/encryption/iencryptionmodule.php
+++ b/lib/public/encryption/iencryptionmodule.php
@@ -119,10 +119,11 @@ interface IEncryptionModule {
 	 * get size of the unencrypted payload per block.
 	 * ownCloud read/write files with a block size of 8192 byte
 	 *
-	 * @return integer
-	 * @since 8.1.0
+	 * @param bool $signed
+	 * @return int
+	 * @since 8.1.0 optional parameter $signed was added in 9.0.0
 	 */
-	public function getUnencryptedBlockSize();
+	public function getUnencryptedBlockSize($signed = false);
 
 	/**
 	 * check if the encryption module is able to read the file,
-- 
GitLab