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