@ -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;
}
/**