diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php
index e4e3fb084f31902dd6fcd5d47a3b35b94b704c37..7d0612ae30e1d49ae8978b44aa222df01a1e205a 100644
--- a/lib/private/encryption/keys/storage.php
+++ b/lib/private/encryption/keys/storage.php
@@ -283,7 +283,12 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
 	 * @param string $owner
 	 * @param bool $systemWide
 	 */
-	public function renameKeys($source, $target, $owner, $systemWide) {
+	public function renameKeys($source, $target) {
+
+		list($owner, $source) = $this->util->getUidAndFilename($source);
+		list(, $target) = $this->util->getUidAndFilename($target);
+		$systemWide = $this->util->isSystemWideMountPoint($target);
+
 		if ($systemWide) {
 			$sourcePath = $this->keys_base_dir . $source . '/';
 			$targetPath = $this->keys_base_dir . $target . '/';
@@ -298,6 +303,34 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
 		}
 	}
 
+	/**
+	 * copy keys if a file was renamed
+	 *
+	 * @param string $source
+	 * @param string $target
+	 * @param string $owner
+	 * @param bool $systemWide
+	 */
+	public function copyKeys($source, $target) {
+
+		list($owner, $source) = $this->util->getUidAndFilename($source);
+		list(, $target) = $this->util->getUidAndFilename($target);
+		$systemWide = $this->util->isSystemWideMountPoint($target);
+
+		if ($systemWide) {
+			$sourcePath = $this->keys_base_dir . $source . '/';
+			$targetPath = $this->keys_base_dir . $target . '/';
+		} else {
+			$sourcePath = '/' . $owner . $this->keys_base_dir . $source . '/';
+			$targetPath = '/' . $owner . $this->keys_base_dir . $target . '/';
+		}
+
+		if ($this->view->file_exists($sourcePath)) {
+			$this->keySetPreparation(dirname($targetPath));
+			$this->view->copy($sourcePath, $targetPath);
+		}
+	}
+
 	/**
 	 * Make preparations to filesystem for saving a keyfile
 	 *
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 3ea3b987d4c4ad79d1d60273c941d75adb018ec3..2e5bbfd97becc0394499b6a15e03015d78d23c64 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -173,17 +173,14 @@ class Encryption extends Wrapper {
 			return $this->storage->rename($path1, $path2);
 		}
 
-		$fullPath1 = $this->getFullPath($path1);
-		list($owner, $source) = $this->util->getUidAndFilename($fullPath1);
+		$source = $this->getFullPath($path1);
 		$result = $this->storage->rename($path1, $path2);
 		if ($result) {
-			$fullPath2 = $this->getFullPath($path2);
-			$systemWide = $this->util->isSystemWideMountPoint($this->mountPoint);
-			list(, $target) = $this->util->getUidAndFilename($fullPath2);
+			$target = $this->getFullPath($path2);
 			$encryptionModule = $this->getEncryptionModule($path2);
 			if ($encryptionModule) {
 				$keyStorage = $this->getKeyStorage($encryptionModule->getId());
-				$keyStorage->renameKeys($source, $target, $owner, $systemWide);
+				$keyStorage->renameKeys($source, $target);
 			}
 		}
 
@@ -198,9 +195,22 @@ class Encryption extends Wrapper {
 	 * @return bool
 	 */
 	public function copy($path1, $path2) {
-		// todo copy encryption keys, get users with access to the file and reencrypt
-		// or is this to encryption module specific? Then we can hand this over
-		return $this->storage->copy($path1, $path2);
+		if ($this->util->isExcluded($path1)) {
+			return $this->storage->rename($path1, $path2);
+		}
+
+		$source = $this->getFullPath($path1);
+		$result = $this->storage->copy($path1, $path2);
+		if ($result) {
+			$target = $this->getFullPath($path2);
+			$encryptionModule = $this->getEncryptionModule($path2);
+			if ($encryptionModule) {
+				$keyStorage = $this->getKeyStorage($encryptionModule->getId());
+				$keyStorage->copyKeys($source, $target);
+			}
+		}
+
+		return $result;
 	}
 
 	/**
diff --git a/lib/public/encryption/keys/istorage.php b/lib/public/encryption/keys/istorage.php
index 0a3ed44d378cb48b02959f1f0a3194e1364ec258..2d1672face5406eb3ba538412f75feceb2062d4e 100644
--- a/lib/public/encryption/keys/istorage.php
+++ b/lib/public/encryption/keys/istorage.php
@@ -122,14 +122,20 @@ interface IStorage {
 	 */
 	public function deleteSystemUserKey($keyId);
 
+	/**
+	 * copy keys if a file was renamed
+	 *
+	 * @param string $source
+	 * @param string $target
+	 */
+	public function renameKeys($source, $target);
+
 	/**
 	 * move keys if a file was renamed
 	 *
 	 * @param string $source
 	 * @param string $target
-	 * @param string $owner
-	 * @param bool $systemWide
 	 */
-	public function renameKeys($source, $target, $owner, $systemWide);
+	public function copyKeys($source, $target);
 
 }
diff --git a/tests/lib/encryption/keys/storage.php b/tests/lib/encryption/keys/storage.php
index c2e5bdbd3d1eeea93973b1d2e6737ce0afdb45d2..be32f0e44a1337884750097542928e914b5d7fe7 100644
--- a/tests/lib/encryption/keys/storage.php
+++ b/tests/lib/encryption/keys/storage.php
@@ -277,4 +277,80 @@ class StorageTest extends TestCase {
 		);
 	}
 
+	/**
+	 * @dataProvider dataProviderCopyRename
+	 */
+	public function testRenameKeys($source, $target, $systemWideMount, $expectedSource, $expectedTarget) {
+		$this->view->expects($this->any())
+			->method('file_exists')
+			->willReturn(true);
+		$this->view->expects($this->any())
+			->method('is_dir')
+			->willReturn(true);
+		$this->view->expects($this->once())
+			->method('rename')
+			->with(
+				$this->equalTo($expectedSource),
+				$this->equalTo($expectedTarget))
+			->willReturn(true);
+		$this->util->expects($this->any())
+			->method('getUidAndFilename')
+			->will($this->returnCallback(array($this, 'getUidAndFilenameCallback')));
+		$this->util->expects($this->any())
+			->method('isSystemWideMountPoint')
+			->willReturn($systemWideMount);
+
+		$storage = new Storage('encModule', $this->view, $this->util);
+		$storage->renameKeys($source, $target);
+	}
+
+	/**
+	 * @dataProvider dataProviderCopyRename
+	 */
+	public function testCopyKeys($source, $target, $systemWideMount, $expectedSource, $expectedTarget) {
+		$this->view->expects($this->any())
+			->method('file_exists')
+			->willReturn(true);
+		$this->view->expects($this->any())
+			->method('is_dir')
+			->willReturn(true);
+		$this->view->expects($this->once())
+			->method('copy')
+			->with(
+				$this->equalTo($expectedSource),
+				$this->equalTo($expectedTarget))
+			->willReturn(true);
+		$this->util->expects($this->any())
+			->method('getUidAndFilename')
+			->will($this->returnCallback(array($this, 'getUidAndFilenameCallback')));
+		$this->util->expects($this->any())
+			->method('isSystemWideMountPoint')
+			->willReturn($systemWideMount);
+
+		$storage = new Storage('encModule', $this->view, $this->util);
+		$storage->copyKeys($source, $target);
+	}
+
+	public function getUidAndFilenameCallback() {
+		$args = func_get_args();
+
+		$path = $args[0];
+		$parts = explode('/', $path);
+
+		return array($parts[1], '/' . implode('/', array_slice($parts, 2)));
+	}
+
+	public function dataProviderCopyRename() {
+		return array(
+			array('/user1/files/foo.txt', '/user1/files/bar.txt', false,
+				'/user1/files_encryption/keys/files/foo.txt/', '/user1/files_encryption/keys/files/bar.txt/'),
+				array('/user1/files/foo/foo.txt', '/user1/files/bar.txt', false,
+				'/user1/files_encryption/keys/files/foo/foo.txt/', '/user1/files_encryption/keys/files/bar.txt/'),
+			array('/user1/files/foo.txt', '/user1/files/foo/bar.txt', false,
+				'/user1/files_encryption/keys/files/foo.txt/', '/user1/files_encryption/keys/files/foo/bar.txt/'),
+			array('/user1/files/foo.txt', '/user1/files/foo/bar.txt', true,
+				'/files_encryption/keys/files/foo.txt/', '/files_encryption/keys/files/foo/bar.txt/'),
+		);
+	}
+
 }