protected function setUp() { parent::setUp(); // set content for encrypting / decrypting in tests $this->dataLong = file_get_contents(__DIR__ . '/../lib/crypt.php'); $this->dataShort = 'hats'; $this->dataUrl = __DIR__ . '/../lib/crypt.php'; $this->legacyData = __DIR__ . '/legacy-text.txt'; $this->legacyEncryptedData = __DIR__ . '/legacy-encrypted-text.txt'; $this->randomKey = \OCA\Files_Encryption\Crypt::generateKey(); $keypair = \OCA\Files_Encryption\Crypt::createKeypair(); $this->genPublicKey = $keypair['publicKey']; $this->genPrivateKey = $keypair['privateKey']; $this->view = new \OC\Files\View('/'); self::loginHelper(self::TEST_USER); $this->userId = self::TEST_USER; $this->pass = self::TEST_USER; $userHome = \OC_User::getHome($this->userId); $this->dataDir = str_replace('/' . $this->userId, '', $userHome); }
/** * Handle plain data from the stream, and write it in 8192 byte blocks * @param string $data data to be written to disk * @note the data will be written to the path stored in the stream handle, set in stream_open() * @note $data is only ever be a maximum of 8192 bytes long. This is set by PHP internally. stream_write() is called multiple times in a loop on data larger than 8192 bytes * @note Because the encryption process used increases the length of $data, a writeCache is used to carry over data which would not fit in the required block size * @note Padding is added to each encrypted block to ensure that the resulting block is exactly 8192 bytes. This is removed during stream_read * @note PHP automatically updates the file pointer after writing data to reflect it's length. There is generally no need to update the poitner manually using fseek */ public function stream_write($data) { // if there is no valid private key return false if ($this->privateKey === false) { $this->size = 0; return strlen($data); } if ($this->headerWritten === false) { $this->writeHeader(); } // Disable the file proxies so that encryption is not // automatically attempted when the file is written to disk - // we are handling that separately here and we don't want to // get into an infinite loop $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // Get the length of the unencrypted data that we are handling $length = strlen($data); // Find out where we are up to in the writing of data to the // file $pointer = ftell($this->handle); // Get / generate the keyfile for the file we're handling // If we're writing a new file (not overwriting an existing // one), save the newly generated keyfile if (!$this->getKey()) { $this->plainKey = Crypt::generateKey(); } // If extra data is left over from the last round, make sure it // is integrated into the next 6126 / 8192 block if ($this->writeCache) { // Concat writeCache to start of $data $data = $this->writeCache . $data; // Clear the write cache, ready for reuse - it has been // flushed and its old contents processed $this->writeCache = ''; } // While there still remains some data to be processed & written while (strlen($data) > 0) { // Remaining length for this iteration, not of the // entire file (may be greater than 8192 bytes) $remainingLength = strlen($data); // If data remaining to be written is less than the // size of 1 6126 byte block if ($remainingLength < 6126) { // Set writeCache to contents of $data // The writeCache will be carried over to the // next write round, and added to the start of // $data to ensure that written blocks are // always the correct length. If there is still // data in writeCache after the writing round // has finished, then the data will be written // to disk by $this->flush(). $this->writeCache = $data; // Clear $data ready for next round $data = ''; } else { // Read the chunk from the start of $data $chunk = substr($data, 0, 6126); $encrypted = $this->preWriteEncrypt($chunk, $this->plainKey); // Write the data chunk to disk. This will be // attended to the last data chunk if the file // being handled totals more than 6126 bytes fwrite($this->handle, $encrypted); // 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); } } $this->size = max($this->size, $pointer + $length); $this->unencryptedSize += $length; \OC_FileProxy::$enabled = $proxyStatus; return $length; }
/** * @medium */ public function testGenerateKey() { # TODO: use more accurate (larger) string length for test confirmation $key = \OCA\Files_Encryption\Crypt::generateKey(); $this->assertTrue(strlen($key) > 16); }