Made proxy class reuse existing keyfiles not gen new ones;

Added notes about reusing shareKeys
This commit is contained in:
Sam Tuke 2013-02-27 18:46:44 +00:00
parent 69bc42f920
commit 953319a2c3
3 changed files with 65 additions and 33 deletions

View File

@ -368,8 +368,6 @@ class Keymanager {
} else { } else {
trigger_error("Could not delete shareKey; does not exist: $shareKeyPath");
\OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR ); \OC_Log::write( 'Encryption library', 'Could not delete shareKey; does not exist: "' . $shareKeyPath, \OC_Log::ERROR );
$result = false; $result = false;

View File

@ -93,16 +93,17 @@ class Proxy extends \OC_FileProxy {
public function preFile_put_contents( $path, &$data ) { 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 ) ) { if ( self::shouldEncrypt( $path ) ) {
// Stream put contents should have been converted to fopen // Stream put contents should have been converted to fopen
if ( !is_resource( $data ) ) { if ( !is_resource( $data ) ) {
// TODO check who is the owner of the file in case of shared folders
$userId = \OCP\USER::getUser(); $userId = \OCP\USER::getUser();
$rootView = new \OC_FilesystemView( '/' ); $rootView = new \OC_FilesystemView( '/' );
$util = new Util( $rootView, $userId ); $util = new Util( $rootView, $userId );
$session = new Session();
$fileOwner = \OC\Files\Filesystem::getOwner( $path );
$privateKey = $session->getPrivateKey();
$filePath = $util->stripUserFilesPath( $path ); $filePath = $util->stripUserFilesPath( $path );
// Set the filesize for userland, before encrypting // Set the filesize for userland, before encrypting
$size = strlen( $data ); $size = strlen( $data );
@ -110,45 +111,62 @@ class Proxy extends \OC_FileProxy {
// Disable encryption proxy to prevent recursive calls // Disable encryption proxy to prevent recursive calls
\OC_FileProxy::$enabled = false; \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 // Encrypt data
$encData = Crypt::symmetricEncryptFileContentKeyfile( $data ); $encData = Crypt::symmetricEncryptFileContent( $data, $plainKey );
// Check if the keyfile needs to be shared // Check if the keyfile needs to be shared
if ( ($userIds = \OCP\Share::getUsersSharingFile( $filePath, true )) ) { if ( $userIds = \OCP\Share::getUsersSharingFile( $filePath, true ) ) {
// $fileOwner = \OC\Files\Filesystem::getOwner( $path );
$publicKeys = Keymanager::getPublicKeys( $rootView, $userIds ); $publicKeys = Keymanager::getPublicKeys( $rootView, $userIds );
\OC_FileProxy::$enabled = false; \OC_FileProxy::$enabled = false;
// Encrypt plain keyfile to multiple sharefiles // Encrypt plain keyfile to multiple sharefiles
$multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys ); $multiEncrypted = Crypt::multiKeyEncrypt( $plainKey, $publicKeys );
// Save sharekeys to user folders // 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'] ); Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
// Set encrypted keyfile as common varname // Set encrypted keyfile as common varname
$encKey = $multiEncrypted['encrypted']; $encKey = $multiEncrypted['encrypted'];
} else { } else {
$publicKey = Keymanager::getPublicKey( $rootView, $userId ); $publicKey = Keymanager::getPublicKey( $rootView, $userId );
// Encrypt plain data to a single user // 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 // Save keyfile for newly encrypted file in parallel directory tree
Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey ); Keymanager::setFileKey( $rootView, $filePath, $fileOwner, $encKey );
}
// Replace plain content with encrypted content by reference // Replace plain content with encrypted content by reference
$data = $encData['encrypted']; $data = $encData;
// Update the file cache with file info // Update the file cache with file info
\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' ); \OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );

View File

@ -626,25 +626,15 @@ class Util {
} }
/** /**
* @brief Encrypt keyfile to multiple users * @brief Decrypt a keyfile without knowing how it was encrypted
* @param array $users list of users which should be able to access the file * @param string $filePath
* @param string $filePath path of the file to be shared * @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 ) { public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) {
// 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 );
// Get the encrypted keyfile // Get the encrypted keyfile
// NOTE: the keyfile format depends on how it was encrypted! At // NOTE: the keyfile format depends on how it was encrypted! At
// this stage we don't know how it was encrypted // this stage we don't know how it was encrypted
@ -671,6 +661,32 @@ class Util {
} }
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 // Re-enc keyfile to (additional) sharekeys
$multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys ); $multiEncKey = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys );