You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

encryptionTest.php 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. /**
  3. * @author Björn Schießle <schiessle@owncloud.com>
  4. * @author Joas Schilling <nickvergessen@owncloud.com>
  5. * @author Morris Jobke <hey@morrisjobke.de>
  6. * @author Thomas Müller <thomas.mueller@tmit.eu>
  7. *
  8. * @copyright Copyright (c) 2015, ownCloud, Inc.
  9. * @license AGPL-3.0
  10. *
  11. * This code is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU Affero General Public License, version 3,
  13. * as published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License, version 3,
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>
  22. *
  23. */
  24. namespace OCA\Encryption\Tests\lib\Crypto;
  25. use OCA\Encryption\Exceptions\PublicKeyMissingException;
  26. use Test\TestCase;
  27. use OCA\Encryption\Crypto\Encryption;
  28. class EncryptionTest extends TestCase {
  29. /** @var Encryption */
  30. private $instance;
  31. /** @var \PHPUnit_Framework_MockObject_MockObject */
  32. private $keyManagerMock;
  33. /** @var \PHPUnit_Framework_MockObject_MockObject */
  34. private $cryptMock;
  35. /** @var \PHPUnit_Framework_MockObject_MockObject */
  36. private $utilMock;
  37. /** @var \PHPUnit_Framework_MockObject_MockObject */
  38. private $loggerMock;
  39. /** @var \PHPUnit_Framework_MockObject_MockObject */
  40. private $l10nMock;
  41. public function setUp() {
  42. parent::setUp();
  43. $this->cryptMock = $this->getMockBuilder('OCA\Encryption\Crypto\Crypt')
  44. ->disableOriginalConstructor()
  45. ->getMock();
  46. $this->utilMock = $this->getMockBuilder('OCA\Encryption\Util')
  47. ->disableOriginalConstructor()
  48. ->getMock();
  49. $this->keyManagerMock = $this->getMockBuilder('OCA\Encryption\KeyManager')
  50. ->disableOriginalConstructor()
  51. ->getMock();
  52. $this->loggerMock = $this->getMockBuilder('OCP\ILogger')
  53. ->disableOriginalConstructor()
  54. ->getMock();
  55. $this->l10nMock = $this->getMockBuilder('OCP\IL10N')
  56. ->disableOriginalConstructor()
  57. ->getMock();
  58. $this->l10nMock->expects($this->any())
  59. ->method('t')
  60. ->with($this->anything())
  61. ->willReturnArgument(0);
  62. $this->instance = new Encryption(
  63. $this->cryptMock,
  64. $this->keyManagerMock,
  65. $this->utilMock,
  66. $this->loggerMock,
  67. $this->l10nMock
  68. );
  69. }
  70. /**
  71. * test if public key from one of the recipients is missing
  72. */
  73. public function testEndUser1() {
  74. $this->instance->begin('/foo/bar', 'user1', 'r', array(), array('users' => array('user1', 'user2', 'user3')));
  75. $this->endTest();
  76. }
  77. /**
  78. * test if public key from owner is missing
  79. *
  80. * @expectedException \OCA\Encryption\Exceptions\PublicKeyMissingException
  81. */
  82. public function testEndUser2() {
  83. $this->instance->begin('/foo/bar', 'user2', 'r', array(), array('users' => array('user1', 'user2', 'user3')));
  84. $this->endTest();
  85. }
  86. /**
  87. * common part of testEndUser1 and testEndUser2
  88. *
  89. * @throws PublicKeyMissingException
  90. */
  91. public function endTest() {
  92. // prepare internal variables
  93. self::invokePrivate($this->instance, 'isWriteOperation', [true]);
  94. self::invokePrivate($this->instance, 'writeCache', ['']);
  95. $this->keyManagerMock->expects($this->any())
  96. ->method('getPublicKey')
  97. ->will($this->returnCallback([$this, 'getPublicKeyCallback']));
  98. $this->keyManagerMock->expects($this->any())
  99. ->method('addSystemKeys')
  100. ->will($this->returnCallback([$this, 'addSystemKeysCallback']));
  101. $this->cryptMock->expects($this->any())
  102. ->method('multiKeyEncrypt')
  103. ->willReturn(true);
  104. $this->cryptMock->expects($this->any())
  105. ->method('setAllFileKeys')
  106. ->willReturn(true);
  107. $this->instance->end('/foo/bar');
  108. }
  109. public function getPublicKeyCallback($uid) {
  110. if ($uid === 'user2') {
  111. throw new PublicKeyMissingException($uid);
  112. }
  113. return $uid;
  114. }
  115. public function addSystemKeysCallback($accessList, $publicKeys) {
  116. $this->assertSame(2, count($publicKeys));
  117. $this->assertArrayHasKey('user1', $publicKeys);
  118. $this->assertArrayHasKey('user3', $publicKeys);
  119. return $publicKeys;
  120. }
  121. /**
  122. * @dataProvider dataProviderForTestGetPathToRealFile
  123. */
  124. public function testGetPathToRealFile($path, $expected) {
  125. $this->assertSame($expected,
  126. self::invokePrivate($this->instance, 'getPathToRealFile', array($path))
  127. );
  128. }
  129. public function dataProviderForTestGetPathToRealFile() {
  130. return array(
  131. array('/user/files/foo/bar.txt', '/user/files/foo/bar.txt'),
  132. array('/user/files/foo.txt', '/user/files/foo.txt'),
  133. array('/user/files_versions/foo.txt.v543534', '/user/files/foo.txt'),
  134. array('/user/files_versions/foo/bar.txt.v5454', '/user/files/foo/bar.txt'),
  135. );
  136. }
  137. /**
  138. * @dataProvider dataTestBegin
  139. */
  140. public function testBegin($mode, $header, $legacyCipher, $defaultCipher, $fileKey, $expected) {
  141. $this->cryptMock->expects($this->any())
  142. ->method('getCipher')
  143. ->willReturn($defaultCipher);
  144. $this->cryptMock->expects($this->any())
  145. ->method('getLegacyCipher')
  146. ->willReturn($legacyCipher);
  147. if (empty($fileKey)) {
  148. $this->cryptMock->expects($this->once())
  149. ->method('generateFileKey')
  150. ->willReturn('fileKey');
  151. } else {
  152. $this->cryptMock->expects($this->never())
  153. ->method('generateFileKey');
  154. }
  155. $this->keyManagerMock->expects($this->once())
  156. ->method('getFileKey')
  157. ->willReturn($fileKey);
  158. $result = $this->instance->begin('/user/files/foo.txt', 'user', $mode, $header, []);
  159. $this->assertArrayHasKey('cipher', $result);
  160. $this->assertSame($expected, $result['cipher']);
  161. if ($mode === 'w') {
  162. $this->assertTrue(self::invokePrivate($this->instance, 'isWriteOperation'));
  163. } else {
  164. $this->assertFalse(self::invokePrivate($this->instance, 'isWriteOperation'));
  165. }
  166. }
  167. public function dataTestBegin() {
  168. return array(
  169. array('w', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'fileKey', 'myCipher'),
  170. array('r', ['cipher' => 'myCipher'], 'legacyCipher', 'defaultCipher', 'fileKey', 'myCipher'),
  171. array('w', [], 'legacyCipher', 'defaultCipher', '', 'defaultCipher'),
  172. array('r', [], 'legacyCipher', 'defaultCipher', 'file_key', 'legacyCipher'),
  173. );
  174. }
  175. /**
  176. * @dataProvider dataTestUpdate
  177. *
  178. * @param string $fileKey
  179. * @param boolean $expected
  180. */
  181. public function testUpdate($fileKey, $expected) {
  182. $this->keyManagerMock->expects($this->once())
  183. ->method('getFileKey')->willReturn($fileKey);
  184. $this->keyManagerMock->expects($this->any())
  185. ->method('getPublicKey')->willReturn('publicKey');
  186. $this->keyManagerMock->expects($this->any())
  187. ->method('addSystemKeys')
  188. ->willReturnCallback(function($accessList, $publicKeys) {
  189. return $publicKeys;
  190. });
  191. $this->assertSame($expected,
  192. $this->instance->update('path', 'user1', ['users' => ['user1']])
  193. );
  194. }
  195. public function dataTestUpdate() {
  196. return array(
  197. array('', false),
  198. array('fileKey', true)
  199. );
  200. }
  201. /**
  202. * by default the encryption module should encrypt regular files, files in
  203. * files_versions and files in files_trashbin
  204. *
  205. * @dataProvider dataTestShouldEncrypt
  206. */
  207. public function testShouldEncrypt($path, $expected) {
  208. $this->assertSame($expected,
  209. $this->instance->shouldEncrypt($path)
  210. );
  211. }
  212. public function dataTestShouldEncrypt() {
  213. return array(
  214. array('/user1/files/foo.txt', true),
  215. array('/user1/files_versions/foo.txt', true),
  216. array('/user1/files_trashbin/foo.txt', true),
  217. array('/user1/some_folder/foo.txt', false),
  218. array('/user1/foo.txt', false),
  219. array('/user1/files', false),
  220. array('/user1/files_trashbin', false),
  221. array('/user1/files_versions', false),
  222. );
  223. }
  224. /**
  225. * @expectedException \OC\Encryption\Exceptions\DecryptionFailedException
  226. * @expectedExceptionMessage Can not decrypt this file, probably this is a shared file. Please ask the file owner to reshare the file with you.
  227. */
  228. public function testDecrypt() {
  229. $this->instance->decrypt('abc');
  230. }
  231. }