diff options
Diffstat (limited to 'apps/encryption/lib/Crypto/Encryption.php')
-rw-r--r-- | apps/encryption/lib/Crypto/Encryption.php | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/apps/encryption/lib/Crypto/Encryption.php b/apps/encryption/lib/Crypto/Encryption.php index 58cefcbe087..b44472fd04a 100644 --- a/apps/encryption/lib/Crypto/Encryption.php +++ b/apps/encryption/lib/Crypto/Encryption.php @@ -103,11 +103,7 @@ 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; + private bool $useLegacyBase64Encoding = false; /** @var int Current version of the file */ private $version = 0; @@ -184,6 +180,11 @@ class Encryption implements IEncryptionModule { $this->user = $user; $this->isWriteOperation = false; $this->writeCache = ''; + $this->useLegacyBase64Encoding = true; + + if (isset($header['encoding'])) { + $this->useLegacyBase64Encoding = $header['encoding'] !== Crypt::BINARY_ENCODING_FORMAT; + } if ($this->session->isReady() === false) { // if the master key is enabled we can initialize encryption @@ -229,6 +230,7 @@ class Encryption implements IEncryptionModule { if ($this->isWriteOperation) { $this->cipher = $this->crypt->getCipher(); + $this->useLegacyBase64Encoding = $this->crypt->useLegacyBase64Encoding(); } elseif (isset($header['cipher'])) { $this->cipher = $header['cipher']; } else { @@ -237,7 +239,13 @@ class Encryption implements IEncryptionModule { $this->cipher = $this->crypt->getLegacyCipher(); } - return ['cipher' => $this->cipher, 'signed' => 'true']; + $result = ['cipher' => $this->cipher, 'signed' => 'true']; + + if ($this->useLegacyBase64Encoding !== true) { + $result['encoding'] = Crypt::BINARY_ENCODING_FORMAT; + } + + return $result; } /** @@ -325,8 +333,8 @@ class Encryption implements IEncryptionModule { $remainingLength = strlen($data); // If data remaining to be written is less than the - // size of 1 6126 byte block - if ($remainingLength < $this->unencryptedBlockSizeSigned) { + // size of 1 unencrypted block + if ($remainingLength < $this->getUnencryptedBlockSize(true)) { // Set writeCache to contents of $data // The writeCache will be carried over to the @@ -343,14 +351,14 @@ class Encryption implements IEncryptionModule { } else { // Read the chunk from the start of $data - $chunk = substr($data, 0, $this->unencryptedBlockSizeSigned); + $chunk = substr($data, 0, $this->getUnencryptedBlockSize(true)); $encrypted .= $this->crypt->symmetricEncryptFileContent($chunk, $this->fileKey, $this->version + 1, $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, $this->unencryptedBlockSizeSigned); + $data = substr($data, $this->getUnencryptedBlockSize(true)); } } @@ -374,7 +382,7 @@ class Encryption implements IEncryptionModule { throw new DecryptionFailedException($msg, $hint); } - return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position); + return $this->crypt->symmetricDecryptFileContent($data, $this->fileKey, $this->cipher, $this->version, $position, !$this->useLegacyBase64Encoding); } /** @@ -462,15 +470,27 @@ class Encryption implements IEncryptionModule { * get size of the unencrypted payload per block. * Nextcloud read/write files with a block size of 8192 byte * + * Encrypted blocks have a 22-byte IV and 2 bytes of padding, encrypted and + * signed blocks have also a 71-byte signature and 1 more byte of padding, + * resulting respectively in: + * + * 8192 - 22 - 2 = 8168 bytes in each unsigned unencrypted block + * 8192 - 22 - 2 - 71 - 1 = 8096 bytes in each signed unencrypted block + * + * Legacy base64 encoding then reduces the available size by a 3/4 factor: + * + * 8168 * (3/4) = 6126 bytes in each base64-encoded unsigned unencrypted block + * 8096 * (3/4) = 6072 bytes in each base64-encoded signed unencrypted block + * * @param bool $signed * @return int */ public function getUnencryptedBlockSize($signed = false) { - if ($signed === false) { - return $this->unencryptedBlockSize; + if ($this->useLegacyBase64Encoding) { + return $signed ? 6072 : 6126; + } else { + return $signed ? 8096 : 8168; } - - return $this->unencryptedBlockSizeSigned; } /** |