public function preFile_put_contents( $path, &$data ) {
- // TODO check for existing key file and reuse it if possible to avoid problems with versioning etc.
if ( self::shouldEncrypt( $path ) ) {
// Stream put contents should have been converted to fopen
if ( !is_resource( $data ) ) {
- // TODO check who is the owner of the file in case of shared folders
$userId = \OCP\USER::getUser();
$rootView = new \OC_FilesystemView( '/' );
$util = new Util( $rootView, $userId );
+ $session = new Session();
+ $fileOwner = \OC\Files\Filesystem::getOwner( $path );
+ $privateKey = $session->getPrivateKey();
$filePath = $util->stripUserFilesPath( $path );
// Set the filesize for userland, before encrypting
$size = strlen( $data );
// Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false;
+ // Check if there is an existing key we can reuse
+ if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) {
+
+ $keyPreExists = true;
+
+ // Decrypt the keyfile
+ $plainKey = $util->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey );
+
+ } else {
+
+ $keyPreExists = false;
+
+ // Make a new key
+ $plainKey = Crypt::generateKey();
+
+ }
+
// Encrypt data
- $encData = Crypt::symmetricEncryptFileContentKeyfile( $data );
+ $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
// Check if the keyfile needs to be shared
- if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) {
-
-// $fileOwner = \OC\Files\Filesystem::getOwner( $path );
+ if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) {
$publicKeys = Keymanager::getPublicKeys( $rootView, $userIds );
\OC_FileProxy::$enabled = false;
// Encrypt plain keyfile to multiple sharefiles
- $multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys );
+ $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
// Save sharekeys to user folders
+ // TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones
Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
// Set encrypted keyfile as common varname
$encKey = $multiEncrypted['encrypted'];
-
-
} else {
$publicKey = Keymanager::getPublicKey( $rootView, $userId );
// Encrypt plain data to a single user
- $encKey = Crypt::keyEncrypt( $encData['key'], $publicKey );
+ $encKey = Crypt::keyEncrypt( $plainKey, $publicKey );
}
- // TODO: Replace userID with ownerId so keyfile is saved centrally
+ // Save the key if its new
+ if ( ! $keyPreExists ) {
- // Save keyfile for newly encrypted file in parallel directory tree
- Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey );
+ // Save keyfile for newly encrypted file in parallel directory tree
+ Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey );
+
+ }
// Replace plain content with encrypted content by reference
- $data = $encData['encrypted'];
+ $data = $encData;
// Update the file cache with file info
\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
}
/**
- * @brief Encrypt keyfile to multiple users
- * @param array $users list of users which should be able to access the file
- * @param string $filePath path of the file to be shared
+ * @brief Decrypt a keyfile without knowing how it was encrypted
+ * @param string $filePath
+ * @param string $fileOwner
+ * @param string $privateKey
+ * @note Checks whether file was encrypted with openssl_seal or
+ * openssl_encrypt, and decrypts accrdingly
*/
- public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) {
-
- // Make sure users are capable of sharing
- $filteredUids = $this->filterShareReadyUsers( $users );
-
- // Get public keys for each user, ready for generating sharekeys
- $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key
+ public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) {
- \OC_FileProxy::$enabled = false;
-
- // Get the current users's private key for decrypting existing keyfile
- $privateKey = $session->getPrivateKey();
-
- $fileOwner = \OC\Files\Filesystem::getOwner( $filePath );
-
// Get the encrypted keyfile
// NOTE: the keyfile format depends on how it was encrypted! At
// this stage we don't know how it was encrypted
}
+ return $plainKeyfile;
+
+ }
+
+ /**
+ * @brief Encrypt keyfile to multiple users
+ * @param array $users list of users which should be able to access the file
+ * @param string $filePath path of the file to be shared
+ */
+ public function setSharedFileKeyfiles( Session $session, array $users, $filePath ) {
+
+ // Make sure users are capable of sharing
+ $filteredUids = $this->filterShareReadyUsers( $users );
+
+ // Get public keys for each user, ready for generating sharekeys
+ $userPubKeys = Keymanager::getPublicKeys( $this->view, $filteredUids ); // TODO: check this includes the owner's public key
+
+ \OC_FileProxy::$enabled = false;
+
+ // Get the current users's private key for decrypting existing keyfile
+ $privateKey = $session->getPrivateKey();
+
+ $fileOwner = \OC\Files\Filesystem::getOwner( $filePath );
+
+ $plainKeyfile = $this->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey );
+
// Re-enc keyfile to (additional) sharekeys
$multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys );